Reputation: 452
I have a cluster/server with multiple nodes that handle requests from the application.
The application the user is running, opens 2 web clients with the following URLs:
In order to support stickiness (I want each of the 2 web clients will keep the connection against the nodes - persistence), the ConnectionLeaseTimeout stayed with the default value, which means "don't close the connection" and because the DefaultPersistentConnectionLimit is 2 by default, I set the DefaultConnectionLimit to 1.
The problem:
servicePoint.CurrentConnections is 2, although servicePoint.ConnectionLimit is 1.
In the server, I see that the remote host port is changing, i.e. I see more than 2 ports (more than 1 port for each client).
What am I doing wrong?
My class output:
CommunicationWebClient https://myprocess.myapp.com/api/json/v1
CommunicationWebClient https://myprocess.myapp.com/api/protobuf/v1
SendAsync _uri=https://myprocess.myapp.com/api/json/v1 servicePoint.Address=https://myprocess.myapp.com/api/json/v1 servicePoint.ConnectionLimit=1 servicePoint.CurrentConnections=2
...
SendAsync _uri=https://myprocess.myapp.com/api/protobuf/v1 servicePoint.Address=https://myprocess.myapp.com/api/json/v1 servicePoint.ConnectionLimit=1 servicePoint.CurrentConnections=2
...
public sealed class CommunicationWebClient : IDisposable
{
private HttpClient _httpClient;
private Uri _uri;
public CommunicationWebClient(Uri uri)
{
Logger.Debug($"{nameof(CommunicationWebClient)} {nameof(uri)}={uri}");
_uri = uri;
ServicePointManager.DefaultConnectionLimit = 1;
_httpClient = new HttpClient(new WebRequestHandler())
{
Timeout = 10.Minutes(),
};
}
public void Dispose()
{
_httpClient.Dispose();
}
public async Task SendAsync(
ByteArrayContent content)
{
var servicePoint = ServicePointManager.FindServicePoint(_uri);
Logger.Debug($"{nameof(SendAsync)} " +
$"{nameof(_uri)}={_uri} " +
$"{nameof(servicePoint.Address)}={servicePoint.Address} " +
$"{nameof(servicePoint.ConnectionLimit)}={servicePoint.ConnectionLimit} " +
$"{nameof(servicePoint.CurrentConnections)}={servicePoint.CurrentConnections}");
using (var httpResponseMessage = await _httpClient.PostAsync(_uri, content))
{
...
}
}
}
Upvotes: 1
Views: 1590
Reputation: 121
In most cases, http client are recommended to use one per application. Disposing http client doesn't get throwing the socket it used right away .
Upvotes: -1
Reputation: 1
If you still have a problem, check that your CommunicationWebClient is not disposed too often. It disposes HttpClient but it behaves not as usually people expect.
Checkout this article: https://learn.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/
Shortly speaking when you dispose HttpClient in case of windows, you ask windows to close all opened sockets. But by default windows have 4 minute timeout to completely close the socket. So for all these 4 minutes there will be a connection between your HttpClient and web server.
Upvotes: 0