HttpClient 抛出“发送请求时出错”。

use*_*700 8 c# rest httpclient asp.net-web-api asp.net-web-api2

我有三层应用程序架构。

我的客户 --> 我的服务A(在 IIS 中托管的 REST) --> 其他团队的服务X (REST)。

服务 A 是 ASP.Net 4.6.1 框架,而不是 ASP.Net Core。

客户端使用 HttpClient 与 A 通信,A 使用 HttpClient 与 X 通信。

客户向 A 和 X 的服务发出了近 2500 次调用。

2500 次调用服务 A 随机(可能是 10 次调用)失败并出现以下异常。它是不可复制的。

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> 
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a 
receive. ---> System.IO.IOException: Unable to read data from the transport connection: An     
established connection was aborted by the software in your host machine. ---> 
System.Net.Sockets.SocketException: An established connection was aborted by the software in your 
host machine
at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags 
socketFlags, AsyncCallback callback, Object state)
at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback 
callback, Object state)
 --- End of inner exception stack trace ---
at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
at System.Net.TlsStream.EndRead(IAsyncResult asyncResult)
at System.Net.Connection.ReadCallback(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
--- End of inner exception stack trace --
Run Code Online (Sandbox Code Playgroud)

这是我的服务电话。IIS 中的 A 调用下面的代码块,并由每个请求调用它。X 正在获取用户凭据并根据用户返回数据,因此我们不会在调用之间共享 HttpClient。

var user = (System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity;
            System.Security.Principal.WindowsIdentity.RunImpersonated(user.AccessToken, () =>
      {
        static HttpClient Client = new HttpClient();
        static string CallX(string[] args)
        {
            HttpClientHandler handler = new HttpClientHandler
            {
                UseDefaultCredentials = true
            };    

            Client = new HttpClient(handler)
            {
                BaseAddress = new Uri("http://XserviceUrl/api/")
            };
            Client.Timeout = TimeSpan.FromSeconds(600);    
            var result = Client.PostAsync("Fake X controller"
                , new StringContent(JsonConvert.SerializeObject(args)
                , Encoding.UTF8, "application/json")).Result;    

            result.EnsureSuccessStatusCode();

            var json = result.Content.ReadAsStringAsync().Result;
            return DosomethingWithResult(json);    
        }
    });
Run Code Online (Sandbox Code Playgroud)

我尝试过的事情:

建议的一些 SO 帖子可能是超时问题。所以我在客户端和服务 A 中添加了 600 秒。我还将 IIS 请求超时从默认的 2 分钟更改为 10(600 秒)。

use*_*700 12

经过一番挖掘后我解决了这个问题。当 A 向 X 发送请求时,A 正在设置Connection: keep-alive,并且 X 会在标头中使用Connection: Close属性进行响应。

因此,在一些调用之后,A 因打开的 tcp 连接而耗尽,并且随机地抛出错误。

(Fiddler 帮助我解决了这个问题)

所以我所要做的就是设置 HttpClient 的 ConnectionClose 属性

_client.DefaultRequestHeaders.ConnectionClose = true;
Run Code Online (Sandbox Code Playgroud)