我们已经将一个项目从WCF移植到Web API(SelfHost),并且在此过程中,我们发现在提供Web应用程序时出现了巨大的速度下降。现在是40-50秒,而之前是3秒。

我已经通过使用以下 Controller 为AspNet.WebApi和OwinSelfHost添加了各种Nuget包在一个简单的控制台应用程序中重现了该问题:

var stream = new MemoryStream();
using (var file = File.OpenRead(filename))
{
    file.CopyTo(stream);
}
stream.Position = 0;

var response = Request.CreateResponse(System.Net.HttpStatusCode.OK);

/// THIS IS FAST
response.Content = new ByteArrayContent(stream.ToArray());
/// THIS IS SLOW
response.Content = new StreamContent(stream);

response.Content.Headers.ContentType = new MediaTypeHeaderValue(System.Web.MimeMapping.GetMimeMapping(filename));
response.Content.Headers.ContentLength = stream.Length;

从代码中可以看到,唯一的区别是StreamContent(slooooow)与ByteArrayContent的用法。

该应用程序托管在Win10计算机上,可从我的笔记本电脑访问。
Fiddler显示,使用ByteArrayContent小于1s时,使用StreamContent从服务器将单个1MB文件获取到笔记本电脑需要14秒。

还要注意,将完整的文件读入内存以表明唯一的区别是所使用的Content类。

奇怪的是,它似乎传输本身很慢。服务器快速/立即响应 header ,但是数据要花很长时间才能到达,如Fiddler计时信息所示:
GotResponseHeaders: 07:50:52.800
ServerDoneResponse: 07:51:08.471

完整的时序信息:
== TIMING INFO ============
ClientConnected:    07:50:52.238
ClientBeginRequest: 07:50:52.238
GotRequestHeaders:  07:50:52.238
ClientDoneRequest:  07:50:52.238
Determine Gateway:  0ms
DNS Lookup:         0ms
TCP/IP Connect:     15ms
HTTPS Handshake:    0ms
ServerConnected:    07:50:52.253
FiddlerBeginRequest:07:50:52.253
ServerGotRequest:   07:50:52.253
ServerBeginResponse:07:50:52.800
GotResponseHeaders: 07:50:52.800
ServerDoneResponse: 07:51:08.471
ClientBeginResponse:07:51:08.471
ClientDoneResponse: 07:51:08.471

Overall Elapsed:    0:00:16.233

有谁知道引擎盖下发生的事情可以解释行为上的差异?

最佳答案

我的OWIN自托管问题的解决方案是StreamContent缓冲区大小。 StreamContent的默认构造函数使用默认值0x1000、4Kb。在千兆网络上,以〜60Kb/s的速度完成大约26分钟的26Mb文件传输。

 const int BufferSize = 1024 * 1024;
 responseMessage = new HttpResponseMessage();
 responseMessage.Content = new StreamContent(fileStream, BufferSize);

现在将bufferSize修改为1Mb只需几秒钟即可完成下载。

[编辑]在StreamContent SerializeToStreamAsync中执行StreamToStreamCopy,根据this link,性能会有所不同。合适的值可能是80K。

关于c# - ASP.NET Web API 2-StreamContent非常慢,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32992081/

10-09 17:36