为什么HttpClient.PostAsync缓冲区响应? [英] Why does HttpClient.PostAsync buffer response?
问题描述
最近,在.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.
现在,由于实现了发送ResponseContentRead
的PostAsync
,因此响应流始终在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屋!