为什么HttpClient.PostAsync缓冲区响应? [英] Why does HttpClient.PostAsync buffer response?

查看:118
本文介绍了为什么HttpClient.PostAsync缓冲区响应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Recently I encountered performance issues when using HttpClients.PostAsync on .Net 4.5.1. Originally server (Owin + WebApi) was buffering response before sending. This was causing huge memory usage overhead (serialized response size is > 1Gb). After I turned on response streaming on the server client literally stopped working. It turned out that reason was buffer re-allocation on the client when reading response from server. I checked HttpClient implementation and found this interesting part in HttpClient.SendAsync method:

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

因此,当completionOption不是ResponseHeadersRead时,响应总是被缓冲.根据 SendAsync文档 SendAsync的实现与意图一致.

So when completionOption is not ResponseHeadersRead response is always buffered. According to SendAsync documentation implementation of SendAsync is consistent with the intent.

现在,由于实现了发送ResponseContentReadPostAsync,因此响应流始终在POST上进行缓冲.那么问题是,为什么PostAsync必须等待(和缓冲)整个响应才能继续处理?

Now, as PostAsync is implemented sending ResponseContentRead, response stream is always buffered on POSTs. So question is why does PostAsync have to wait (and buffer) for whole response to arrive before processing continues?

推荐答案

有一个显而易见的部分-如果您未指定HttpCompletionOption.ResponseHeadersRead,则Task仅在读取整个响应后才会完成;您必须同时在某处中存储响应数据.

There's the obvious part - if you don't specify HttpCompletionOption.ResponseHeadersRead, the Task will only complete when the whole response is read; you have to store the response data somewhere in the meantime.

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

Why doesn't PostAsync allow you to specify HttpCompletionOption.ResponseHeadersRead? Probably because it's not really all that useful, most of the time. POST is for posting data, not for retrieving it - that's GET's job. HttpClient was designed around WebAPIs and "REST" services, with proper use of HTTP verbs.

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

If you need to use POST to retrieve such large amounts of data, you have two basic options:

  • 使用SendAsync
  • 不要使用HttpClient(HttpWebRequest稍微复杂一些,但可以给您更多的控制权)
  • Use SendAsync
  • Don't use HttpClient (HttpWebRequest is a bit more complicated, but gives you way more control)

这篇关于为什么HttpClient.PostAsync缓冲区响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆