以下方法(希望在本文中进行大幅简化的同时不会出现任何错误)正在正常工作,并且已通过net.tcp协议使用流传输模式进行设置。问题是,与通过IIS通过http下载同一文件相比,性能明显差。为什么会这样?我可以更改哪些内容以提高性能?
Stream WebSiteStreamedServiceContract.DownloadFile( string filePath ) {
return File.OpenRead( filePath );
}
最后,WCF是否负责正确处理我的数据流,并且在此方面做得很好吗?如果没有,我该怎么办?
谢谢。
最佳答案
在解决此问题8个月后,其中3个与Microsoft合作,这是解决方案。简短的答案是服务器端(发送大文件的那一侧)需要使用以下内容进行绑定:
<customBinding>
<binding name="custom_tcp">
<binaryMessageEncoding />
<tcpTransport connectionBufferSize="256192" maxOutputDelay="00:00:30" transferMode="Streamed">
</tcpTransport>
</binding>
</customBinding>
这里的关键是connectionBufferSize属性。可能需要设置其他几个属性(maxReceivedMessageSize等),但是元凶是connectionBufferSize。
无需在服务器端更改任何代码。
无需在客户端更改任何代码。
客户端无需更改任何配置。
这是一个很长的答案:
一直以来,我一直怀疑WCF上的net.tcp之所以缓慢,是因为它非常频繁地发送少量信息,而不是较少地发送较大信息,并且这使得它在高延迟网络(Internet)上的性能较差。事实证明这是对的,但要实现这一目标还很漫长。
netTcpBinding上有几个听起来很有希望的属性:maxBufferSize最明显,maxBytesPerRead和其他听起来也很有希望。除此之外,还可以在客户端和服务器端创建比原始问题中更复杂的流-您也可以在其中指定缓冲区大小。问题在于,这没有任何影响。一旦使用了netTcpBinding,就可以进行软管连接。
这样做的原因是,调整netTcpBinding上的maxBufferSize会调整协议层上的缓冲区。但是您对netTcpBinding所做的任何操作都将无法调整基础传输层。这就是为什么我们这么长时间未能取得进展。
定制绑定解决了该问题,因为在传输层上增加connectionBufferSize会增加一次发送的信息量,因此传输对延迟的敏感度要小得多。
在解决此问题时,我确实注意到maxBufferSize和maxBytesPerRead确实对低延迟网络(和本地网络)产生了性能影响。 Microsoft告诉我,maxBufferSize和connectionBufferSize是独立的,并且它们的值的所有组合(彼此相等,maxBufferSize大于connectionBufferSize,maxBufferSize小于connectionBufferSize)是有效的。我们成功实现了65536字节的maxBufferSize和maxBytesPerRead。同样,这对高延迟网络性能(原始问题)的影响很小。
如果您想知道maxOutputDelay的用途,那是在框架引发IO异常之前分配用于填充连接缓冲区的时间。因为我们增加了缓冲区的大小,所以也增加了分配给缓冲区的时间。
使用此解决方案,我们的性能提高了约400%,现在略优于IIS。还有其他一些因素会影响IIS和HTTP上的IIS的相对和绝对性能,而net.tcp上的WCF(和HTTP上的WCF)会影响相对和绝对性能,但这是我们的经验。