2

我使用以下代码对运行在 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
很绝望,有人见过这种不一致的行为吗?谢谢

4

1 回答 1

-1

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

将您的代码修改为:

InstResponse s = await httpResponseMessage.Content.ReadAsAsync<InstResponse>();
于 2019-12-23T20:50:09.777 回答