在解决此问题 8 个月后,其中 3 个月与 Microsoft 合作,这是解决方案。简短的回答是服务器端(发送大文件的端)需要使用以下内容进行绑定:
<customBinding>
<binding name="custom_tcp">
<binaryMessageEncoding />
<tcpTransport connectionBufferSize="256192" maxOutputDelay="00:00:30" transferMode="Streamed">
</tcpTransport>
</binding>
</customBinding>
这里的关键是 connectionBufferSize 属性。可能需要设置其他几个属性(maxReceivedMessageSize 等),但 connectionBufferSize 是罪魁祸首。
无需在服务器端更改任何代码。
无需在客户端更改任何代码。
无需在客户端更改任何配置。
这是长答案:
我一直怀疑 net.tcp over WCF 速度慢的原因是因为它非常频繁地发送小块信息而不是不经常发送大块信息,这使得它在高延迟网络(互联网)上表现不佳。事实证明这是真的,但要到达那里还有很长的路要走。
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 over HTTP 和 WCF over net.tcp(以及 WCF over http,就此而言)的相对和绝对性能,但这是我们的经验。