【问题标题】:C# HttpClient randomly getting error while copying content to a streamC# HttpClient 在将内容复制到流时随机出现错误
【发布时间】:2019-12-23 19:14:33
【问题描述】:

我使用以下代码对运行在 IIS 服务器上的远程 ASP .Net WebApi 执行 HTTP GET 请求。该请求返回一个大小约为 5 兆字节的 JSON 对象。几乎所有时间,这个请求都成功了,我得到了正确的 JSON 响应,但是(大约 2-3% 的时间,随机分布)我在响应正文中得到了一个不完整的 JSON。响应代码为 200 OK,但 JSON 数据在随机位置被截断。 在 Fiddler 中,我确实看到响应 JSON 在随机位置被剪切,所以看起来服务器出于某种原因正在关闭中间的连接。

我在其他 SO 线程中读到,迁移到 HTTP V1.0 或将 Connection 标头设置为“关闭”可能会解决问题,但它对我没有用。这是我在这里缺少的 IIS 服务器设置吗?还是客户端配置错误?

在来自相同 api 的其他路由上使用相同代码时,该问题似乎不会重现,返回的 JSON 响应要小得多(小于 1 兆字节)。

还需要注意的是,我们的客户端和 IIS 服务器(Incapsula)之间有一些负载平衡器机制。此负载均衡器还提供 DDos 预防。

这是我的 C# 代码(我使用的是最新的 HttpClient 版本):

 using (var httpClient = new HttpClient())
 {
     var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, new Uri("https://api-real.bgtm.com/Orders"));

     using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
     {
          InstResponse s = httpResponseMessage.Content.ReadAsAsync<InstResponse>().GetAwaiter().GetResult();
         Console.Write("Finished without error.");
     }
 }

这是我在尝试从响应流中读取不完整的 JSON 时得到的完整异常详细信息:

{System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: The server returned an invalid or unrecognized response.
   at System.Net.Http.HttpConnection.FillAsync()
   at System.Net.Http.HttpConnection.CopyToExactLengthAsync(Stream destination, UInt64 length, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.ContentLengthReadStream.CompleteCopyToAsync(Task copyTask, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.HttpConnectionResponseContent.SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken)
   at System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task serializeToStreamTask, MemoryStream tempBuffer)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task serializeToStreamTask, MemoryStream tempBuffer)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at ConsoleApp1.Program.MainAsync ()}

我还可以添加来自 WireShark 的屏幕截图,显示服务器是第一个发送 FIN 消息的服务器。服务器 IP 为 107.154.192.59,客户端 IP 为 10.10.80.146:ScreenShot
非常绝望,有人见过这种不一致的行为吗? 谢谢

【问题讨论】:

  • 这可能有关系,也可能没有关系,但你应该看看这篇关于套接字耗尽的文章:aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
  • 200 响应不完整主要是异步任务造成的。如果是 IIS 错误,您可能会重现此问题。响应不完整的 200 显示异步任务异常。你有没有注意到,当你得到不完整的 json 时,完成请求需要多长时间。
  • 不完整的JSON请求似乎需要更长的时间:成功的请求大约需要1秒,不成功的大约需要4秒。
  • 听起来应用程序达到了一些缓冲区限制。您是否尝试过更改某些 httpruntime 或服务器运行时配置并监控其影响?

标签: c# asp.net json iis httpclient


【解决方案1】:

.GetAwaiter().GetResult() 不是异步操作。错误是零星的原因。

将您的代码修改为:

InstResponse s = await httpResponseMessage.Content.ReadAsAsync<InstResponse>();

【讨论】:

    猜你喜欢
    • 2018-02-15
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    • 1970-01-01
    • 2020-04-10
    • 2020-12-12
    相关资源
    最近更新 更多