通过 WCF 下载文件比通过 IIS 下载慢 [英] File download through WCF slower than through IIS

查看:34
本文介绍了通过 WCF 下载文件比通过 IIS 下载慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的方法(我希望在为这篇文章大大简化它的同时没有犯任何错误)工作正常,并使用基于 net.tcp 协议的流式传输模式进行设置.问题是性能比通过 IIS 通过 http 下载相同的文件要差很多.为什么会这样,我可以更改哪些内容来提高性能?

The following method (in which I hopefully did not make any mistakes while dramatically simplifying it for this post) is working properly and set up using the Streamed transfer mode over the net.tcp protocol. The problem is that the performance is significantly worse than downloading the same file through IIS over http. Why would this be, and what things can I change to improve the performance?

Stream WebSiteStreamedServiceContract.DownloadFile( string filePath ) {
    return File.OpenRead( filePath );
}

最后,WCF 是否负责正确处理我的流,它在这方面做得很好吗?如果没有,我该怎么办?

Finally, is WCF taking responsibility for properly disposing my stream, and does it do a good job at this? If not, what am I supposed to do instead?

谢谢.

推荐答案

经过 8 个月的工作解决这个问题,其中 3 个月与微软合作,这里是解决方案.简短的回答是服务器端(发送大文件的一方)需要使用以下内容进行绑定:

After 8 months of working on this problem, 3 of them with Microsoft, here is the solution. The short answer is that the server side (the side sending the large file) needed to use the following for a binding:

 <customBinding>
  <binding name="custom_tcp">
   <binaryMessageEncoding />
   <tcpTransport connectionBufferSize="256192" maxOutputDelay="00:00:30" transferMode="Streamed">
   </tcpTransport>
  </binding>
 </customBinding>

这里的关键是 connectionBufferSize 属性.可能需要设置其他几个属性(maxReceivedMessageSize 等),但 connectionBufferSize 是罪魁祸首.

The key here being the connectionBufferSize attribute. Several other attributes may need to be set (maxReceivedMessageSize, etc.), but connectionBufferSize was the culprit.

无需在服务器端更改代码.

No code had to be changed on the server side.

无需在客户端更改代码.

No code had to be changed on the client side.

客户端无需更改任何配置.

No configuration had to be changed on the client side.

这是一个长答案:

我一直怀疑 WCF 上的 net.tcp 很慢的原因是因为它非常频繁地发送小块信息而不是不经常发送大块信息,这使得它在高延迟网络上表现不佳(互联网).事实证明这是真的,但要实现这一目标还有很长的路要走.

I suspected all along that the reason net.tcp over WCF was slow was because it was sending small chunks of information very frequently rather than larger chunks of information less often, and that this made it perform poorly over high latency networks (the internet). This turned out to be true, but it was a long road to get there.

netTcpBinding 上有几个听起来很有希望的属性:maxBufferSize 是最明显的,而 maxBytesPerRead 和其他听起来也很有希望.除此之外,还可以创建比原始问题中的流更复杂的流 - 您也可以在那里指定缓冲区大小 - 在客户端和服务器端.问题是这些都没有任何影响.一旦你使用了 netTcpBinding,你就完蛋了.

There are several attributes on the netTcpBinding that sound promising: maxBufferSize being the most obvious, and maxBytesPerRead and others sounding hopeful as well. In addition to those, it is possible to create more complicated streams than the one in the original question - you can specify the buffer size there as well - on both the client and the server side. The problem is that none of this has any impact. Once you use a netTcpBinding, you are hosed.

这样做的原因是在 netTcpBinding 上调整 maxBufferSize 会调整协议层上的缓冲区.但是您对 netTcpBinding 所做的任何事情都不会调整底层传输层.这就是我们长期未能取得进展的原因.

The reason for this is that adjusting maxBufferSize on a netTcpBinding adjusts the buffer on the protocol layer. But nothing you can do to a netTcpBinding will ever adjust the underlying transport layer. This is why we failed for so long to make headway.

自定义绑定解决了这个问题,因为在传输层增加 connectionBufferSize 会增加一次发送的信息量,因此传输更不容易受到延迟的影响.

The custom binding solves the problem because increasing the connectionBufferSize on the transport layer increases the amount of information sent at once, and thus the transfer is much less susceptible to latency.

在解决这个问题时,我确实注意到 maxBufferSize 和 maxBytesPerRead 确实对低延迟网络(和本地)有性能影响.Microsoft 告诉我 maxBufferSize 和 connectionBufferSize 是独立的,并且它们值的所有组合(彼此相等,maxBufferSize 大于 connectionBufferSize,maxBufferSize 小于 connectionBufferSize)都是有效的.我们成功使用了 65536 字节的 maxBufferSize 和 maxBytesPerRead.不过,这对高延迟网络性能(最初的问题)的影响也很小.

In solving this problem, I did notice that maxBufferSize and maxBytesPerRead did have a performance impact over low latency networks (and locally). Microsoft tells me that maxBufferSize and connectionBufferSize are independent and that all combinations of their values (equal to one another, maxBufferSize larger than connectionBufferSize, maxBufferSize smaller than connectionBufferSize) are valid. We are having success with a maxBufferSize and maxBytesPerRead of 65536 bytes. Again, though, this had very little impact on high-latency network performance (the original problem).

如果您想知道 maxOutputDelay 的用途,它是在框架抛出 IO 异常之前分配给连接缓冲区的时间量.因为我们增加了缓冲区大小,所以我们也增加了分配给填充缓冲区的时间.

If you are wondering what maxOutputDelay is for, it is the amount of time that is allotted to fill the connection buffer before the framework throws an IO exception. Because we increased the buffer size, we also increased the amount of time allotted to fill the buffer.

使用此解决方案,我们的性能提高了约 400%,现在略好于 IIS.还有其他几个因素会影响 IIS over HTTP 和 WCF over net.tcp(以及 WCF over http)的相对和绝对性能,但这是我们的经验.

With this solution, our performance increased about 400% and is now slightly better than IIS. There are several other factors that affect the relative and absolute performance over IIS over HTTP and WCF over net.tcp (and WCF over http, for that matter), but this was our experience.

这篇关于通过 WCF 下载文件比通过 IIS 下载慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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