Después de 8 meses de trabajar en este problema, 3 de ellos con Microsoft, esta es la solución. La respuesta corta es que el lado del servidor (el lado que envía el archivo grande) necesarios para utilizar el siguiente para una unión:
<customBinding>
<binding name="custom_tcp">
<binaryMessageEncoding />
<tcpTransport connectionBufferSize="256192" maxOutputDelay="00:00:30" transferMode="Streamed">
</tcpTransport>
</binding>
</customBinding>
La clave aquí es el atributo connectionBufferSize. Es posible que se necesiten varios otros atributos (maxReceivedMessageSize, etc.), pero connectionBufferSize fue el culpable.
No se tuvo que cambiar el código en el lado del servidor.
No se tuvo que cambiar el código en el lado del cliente.
No se tuvo que cambiar la configuración en el lado del cliente.
Aquí está la respuesta larga:
sospeché desde el principio que la razón net.tcp sobre WCF fue lento era porque estaba enviando pequeños trozos de información con mucha frecuencia en lugar de grandes trozos de información con menos frecuencia, y que esto hizo que funcionara mal en redes de alta latencia (Internet). Esto resultó ser cierto, pero fue un largo camino para llegar allí.
Hay varios atributos en netTcpBinding que suenan prometedores: maxBufferSize es el más obvio, y maxBytesPerRead y otros suenan esperanzados también. Además de estos, es posible crear flujos más complicados que el de la pregunta original; también puede especificar el tamaño del búfer allí, tanto en el lado del cliente como del servidor. El problema es que nada de esto tiene ningún impacto. Una vez que utilizas un NetTcpBinding, te dan una manguera.
El motivo es que al ajustar maxBufferSize en un netTcpBinding se ajusta el búfer en la capa de protocolo. Pero nada de lo que pueda hacer con un NetTcpBinding ajustará la capa de transporte subyacente. Es por eso que hemos fallado por tanto tiempo para avanzar.
El enlace personalizado resuelve el problema porque aumentar el connectionBufferSize en la capa de transporte aumenta la cantidad de información enviada a la vez, y por lo tanto, la transferencia es mucho menos susceptible a la latencia.
Al resolver este problema, me di cuenta de que maxBufferSize y maxBytesPerRead tuvieron un impacto en el rendimiento sobre redes de baja latencia (y localmente). Microsoft me dice que maxBufferSize y connectionBufferSize son independientes y que todas las combinaciones de sus valores (iguales entre sí, maxBufferSize mayor que connectionBufferSize, maxBufferSize menor que connectionBufferSize) son válidas. Estamos teniendo éxito con maxBufferSize y maxBytesPerRead de 65536 bytes. De nuevo, sin embargo, esto tuvo muy poco impacto en el rendimiento de la red de alta latencia (el problema original).
Si se está preguntando para qué es maxOutputDelay, es la cantidad de tiempo que se asigna para llenar el búfer de conexión antes de que el marco genere una excepción de IO. Debido a que aumentamos el tamaño del búfer, también aumentamos la cantidad de tiempo asignada para llenar el búfer.
Con esta solución, nuestro rendimiento aumentó alrededor del 400% y ahora es ligeramente mejor que IIS. Hay varios otros factores que afectan el rendimiento relativo y absoluto sobre IIS sobre HTTP y WCF sobre net.tcp (y WCF sobre http, para el caso), pero esta fue nuestra experiencia.
Hi Greg! Estoy luchando por configurar un canal transmitido a través de netTcp. Con tu pregunta, parece que has tenido éxito en hacer lo mismo. ¿Puedes compartir información sobre las configuraciones del servidor y del cliente? Muchas gracias de antemano! – Nayan
@Nayan Creo que deberías hacer una nueva pregunta y señalarme. La respuesta probablemente terminará siendo demasiado grande para los comentarios. –