【问题标题】:Why does HttpClient.PostAsync buffer response?为什么 HttpClient.PostAsync 缓冲响应?
【发布时间】:2015-05-27 06:59:26
【问题描述】:

最近我在 .Net 4.5.1 上使用 HttpClients.PostAsync 时遇到了性能问题。最初服务器(Owin + WebApi)在发送之前缓冲响应。这导致了巨大的内存使用开销(序列化响应大小> 1Gb)。在我打开服务器客户端上的响应流之后,实际上停止了工作。事实证明,原因是从服务器读取响应时客户端上的缓冲区重新分配。我检查了 HttpClient 的实现,在HttpClient.SendAsync 方法中发现了这个有趣的部分:

if (result.Content == null || completionOption == HttpCompletionOption.ResponseHeadersRead)
{
    this.SetTaskCompleted(request, linkedCts, tcs, result);
}
else
{
    this.StartContentBuffering(request, linkedCts, tcs, result);
}

所以当completionOption 不是ResponseHeadersRead 时,响应总是被缓冲。根据SendAsync documentation 实现的SendAsync 与意图是一致的。

现在,由于 PostAsync 已实现发送 ResponseContentRead,因此响应流始终在 POST 上缓冲。那么问题是为什么 PostAsync 必须等待(和缓冲)整个响应才能在处理继续之前到达?

【问题讨论】:

  • 嗨 @koruyucu,我想使用 HttpClient 调用 SOAP Web 服务,因此,我不会使用 PostAsync 发送请求,我想知道它是否适用于你要改用SendAsync 吗?我问这个是因为 HttpClient 自 2015 年以来发生了变化。谢谢

标签: c# httpclient


【解决方案1】:

有一个明显的部分——如果你不指定HttpCompletionOption.ResponseHeadersReadTask 只会在读取整个响应时完成;同时,您必须将响应数据存储在某处

为什么PostAsync 不允许您指定HttpCompletionOption.ResponseHeadersRead?可能是因为在大多数情况下,它并不是真的那么有用。 POST 用于发布数据,而不是用于检索数据 - 这是 GET 的工作。 HttpClient 是围绕 WebAPI 和“REST”服务设计的,并正确使用了 HTTP 动词。

如果您需要使用POST 来检索如此大量的数据,您有两个基本选择:

  • 使用SendAsync
  • 不要使用HttpClientHttpWebRequest 有点复杂,但可以提供更多控制权)

【讨论】:

  • 我必须使用 POST,因为我的请求对象在 GET 方法中“不适合”。无论如何,我将实现更改为显式调用 SendAsync
  • @koruyucu 是的,这可能很棘手。完全解决这个 REST 的常用方法是使用例如PUT 将您的请求对象推送到服务器,这将返回一个 URL 到 GET 以检索响应。但它可能会造成比它解决的更多的麻烦:D
  • @Luaan 因为它会解决 nothing,要明确 :)
  • 它会拉出某些超时问题,但不是初始请求有效负载,也不是最终响应有效负载。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多