当前位置: 首页 > 知识库问答 >
问题:

HttpClient与ASP.NET Core 2.0 webservice之间的连接关闭错误

狄宪
2023-03-14
[HttpGet()]
public IActionResult Test()
{
    // do some db updates and get data
    var result = DoSomeStuff();
    // serialize data to byte array
    var output = Serialize(result);

    return File(output, "application/octet-stream");
}

我有10个客户。当他们串行调用webservice时,一切都正常工作。当我并行强调webservice和fire客户端时,我几乎总是在其中一些客户端上得到一个错误(通常一两个失败,有时甚至4-5个)。

以下是异常,它是从ReadAsByteArrayAsync调用引发的:

System.AggregateException: One or more errors occurred. ---> System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Net.ConnectStream.EndRead(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
...
---> (Inner Exception #0) System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Net.ConnectStream.EndRead(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
...

我发现了几个与这种异常相关的SO线程(例如这里),所以我最初认为这是一个与客户端相关的问题。建议回答:

    null

对我没什么用。我想我在什么地方读到HttpClient中有一些bug(现在找不到源)。我尝试使用NuGet最新的system.net.http包。同样的问题。我创建了.NET核心控制台应用程序,并使用HttpClient的核心版本。同样的问题。我使用了httpwebrequest而不是httpclient。同样的潜在问题。

我在同一台虚拟机上运行webservice和客户端。为了排除一些本地问题,我从其他计算机同时运行客户端。同样的问题。

所以我最后用了以下简化代码(只有一个包含10个线程的应用程序):

private async void Test_Click(object sender, RoutedEventArgs e)
{
    try
    {
        var tasks = Enumerable.Range(1, 10).Select(async i => await Task.Run(async () => await GetContent(i))).ToList();

        await Task.WhenAll(tasks);

        MessageBox.Show(String.Join(Environment.NewLine, tasks.Select(t => t.Result.ToString())));
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

private async Task<Int32> GetContent(Int32 id)
{
    using (var httpClient = new HttpClient())
    {
        var url = "http://localhost/TestService/api/test";

        using (var responseMessage = await httpClient.GetAsync(url).ConfigureAwait(false))
        {
            // just read everything and return length
            // ReadAsByteArrayAsync throws sometimes an exception
            var content = await responseMessage.Content.ReadAsByteArrayAsync();
            return content.Length;
        }
    }
}
info: Microsoft.AspNetCore.Server.Kestrel[28]
      Connection id "0HL89D9NUNEOQ", Request id "0HL89D9NUNEOQ:00000001": the connection was closed becuase the response was not read by the client at the specified minimum data rate.
dbug: Microsoft.AspNetCore.Server.Kestrel[10]
      Connection id "0HL89D9NUNEOQ" disconnecting.
...
info: Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv[14]
      Connection id "0HL89D9NUNEOQ" communication error.
Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking.UvException: Error -4081 ECANCELED operation canceled
<system.applicationHost>
  <webLimits minBytesPerSecond="0"/>
</system.applicationHost>

有什么建议吗?我至少想知道这是服务器还是客户端相关的问题。

共有1个答案

林烨华
2023-03-14

您的吞吐量似乎低于最小数据速率。此行为在Kestrel基础知识中进行了描述:

Kestrel每秒检查数据是否以指定的速率(字节/秒)传入。如果速率低于最小值,则连接超时。宽限期是Kestrel为客户端提供的将其发送速率提高到最小的时间量;在此期间不检查费率。宽限期有助于避免由于TCP慢速启动而断开最初以慢速速率发送数据的连接。

默认最小速率为240字节/秒,宽限期为5秒。

var host = new WebHostBuilder() 
    .UseKestrel(options => 
    { 
        options.Limits.MinResponseDataRate = null;
    })
 类似资料:
  • 我正在使用HttpClient v4.5.5 我有一个如下: 然后我使用超文本传输协议客户端如下: 通过定期调用(每隔几分钟) 偶尔我会出错 ,据我所知,这种情况要么发生在旧的HttpClient版本上,要么发生在您关闭HttpClient时。我没有这样做。所以我不明白为什么会出现这个错误。它会恢复,但有这样的异常是个问题。

  • 版本 上下文 我只是想在核心示例io中运行http客户端。维特斯。实例果心http。易于理解的客户运行此示例时,its发现已建立的连接在请求完成后未关闭。 服务器端我没有看到任何问题。因为在尝试使用jmeter和服务器时,它工作得很好。所以我认为问题在于HttpClient。 有人能帮我吗? 提前谢谢。复制的步骤 额外的 即使在请求和响应结束后,仍会显示以下内容。在给LINUX 窗户 在LINUX

  • 我在web应用程序中遇到了一个HttpClient(版本4.5.2)的问题,我的意思是,以多线程的方式。在正常情况下,当一个连接请求到达时,从池中租用一个连接,然后使用,最后再次释放回池中,以便在以后的请求中再次使用,作为id为673890的连接状态日志的以下部分。 在以我上面提到的正常方式多次使用上述连接(id 673890)后,我注意到代码中发生了以下情况: 日志说连接被请求、租用、使用、关闭

  • 我使用weblogic应用服务器和oracle数据库。我使用jdbc与oracle数据库通信。我从weblogic数据源获得连接,并向表中插入一条记录。问题是,当我想关闭连接(插入数据库后)时,我会遇到一个异常(连接已经关闭)。这是我的代码: 但是联系。close语句引发异常: 我试图避免连接。close语句(因为我教过连接是自动关闭的!!但过了一段时间,所有的连接都打开了,因此引发了一个异常)

  • 我正在使用mybatis连接到Oracle。 我的mybatis配置是: 我的开放会话代码就像 由于类的应用范围,而sqlSession不能在应用范围内使用,所以我必须自己管理sqlSession。 2019-04-11 15:30:41,861信息[stdout](默认任务-57)声称连接过期962608913。 2019-04-11 15:30:41,861信息[stdout](默认任务-57

  • 在请求完成后,应该如何告诉OkHttp关闭与HTTP服务器的连接? 假设我使用以下代码向google发出请求。通用域名格式 通过使用“连接:关闭”,我能够让远程服务器发送FIN(如果我不这样做,远程服务器只是挂起等待新请求)。尽管如此,在客户端没有产生FIN,并且连接保持半打开显然有一段不确定的时间。