5
votes

We are using HttpClient to access the WebAPI hosted on another server. We have a MVC5 application which is getting data form WebAPI window server 2012 R2 with IIS 8.5

Below is the code which using to get data from webapi

//creating static instance of http client
private static HttpClient client = new HttpClient();

//static method to add common header
static ApiCall()
{
   client.DefaultRequestHeaders.Add("Authorization", 
                 string.Format("Value {0}", AppSettings.ApiSecurityKey));
   client.DefaultRequestHeaders.ConnectionClose = true;
}

//finally posting data to the api
//objprop contains the data and other setting
string url = "apiurl";
var postContent = new StringContent(objprop.DataForPost, 
      System.Text.Encoding.UTF8, objprop.ContentType);
response = client.PostAsync(url, postContent).Result;

But during the PT test I am getting multiple request in TIME_WAIT state. Due to this we are getting socket exception.

What are the best practices to use HttpClient?

Is there any setting which can release the socket after the use.

Similar Question is here
1. How do I prevent Socket/Port Exhaustion?
2. Why does HttpClient leave sockets open?
but it did not helped me.

Edit 1 More detail

: InnerException- System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted x.x.x:80 at System.Net.Sockets.Socket.InternalEndConnect(IAsyncResult asyncResult) at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception) --- End of inner exception stack trace --- at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) --- End of inner exception stack trace --- : URL- http://x.x.x.com//api/GetMenu

1
@शेखर how does that link advocate multiple instances of HttpClient? It is about the fact that you are blocking the async code with .Result and you are probably awaiting the call to this code though you haven't shown it in context.Crowcoder
@Crowcoder I did went through the whole code sorry for the comment. I am looking into that.शेखर
@Crowcoder do you think this is causing the state in TIME_WAIT?शेखर
I'm not a network engineer but if you are not deadlocking then I wouldn't worry about it though you should refactor to not need blocking code for other reasons. HttpClient will re-use connections, that is a reason to use a shared static instance in the first place, so I believe it is by design.Crowcoder

1 Answers

3
votes

Your usage of HttpClient is correct; although its better to use async all the way up as some have commented, its not the cause of your error.

TIME_WAIT is a mandatory phase of a TCP/IP connection; once a connection is established, the side that initiates connection close will go into this state for a preconfigured time.

TCP/IP has a limited pool of ports for connections in and out.

New connections use a subset of these (aka dynamic or ephemeral port range) to allocate a port on each side.

Your app gets error "Address in use" when trying to create a new outgoing connection, but TCP has run out of local ports in the dynamic range.

Depending on which end initiates connection close, it may be your client or server which runs out of ports.

This article from Microsoft details how to modify Windows TCP/IP settings for high connection rates:

  • Change TIME_WAIT period from 120 to 30 seconds
  • Increase the dynamic port count from 16384 to 64511

Doing both of these will increase the max connection rate from 136 connections/second to about 2150.