2011-04-02 7 views
5

Antecedentes

Tengo una implementación de un servidor HTTP en C#. Utilizando ab descubrí un problema de rendimiento extraño. ¡Cada solicitud tomó 5 ms con Keep-Alive Off pero 40 ms con Keep-Alive activado!Enchufe "Flush" al habilitar temporalmente NoDelay

La página de prueba se genera en un solo byte [] que se envía como respuesta con un solo socket. Enviar llamada.

La causa es, por lo que puedo decir, el algoritmo de Nagle utilizado en la pila TCP.

TCP Flush?

Hasta ahora estoy usando la propiedad NoDelay al final de cada solicitud HTTP que se sirve.

socket.NoDelay = true; 
socket.NoDelay = false; 

Lo que soluciona el problema por el momento. Pero no tengo documentación para respaldar mi descubrimiento.

Esto se probó en un sistema de linux/mono.

¿Hay una forma estándar de enjuagar la conexión TCP?

relacionada

This answer es abordar la misma cuestión. La diferencia aquí es que estoy buscando solo deshabilitar temporalmente el algoritmo.

Respuesta

6

He probado esto con Wireshark. Desafortunadamente,

socket.NoDelay = true; 
socket.NoDelay = false; 

no tiene ningún efecto. Del mismo modo,

socket.NoDelay = true; 
socket.Send(new byte[0]); 
socket.NoDelay = false; 

tampoco tiene ningún efecto.Según el comportamiento observado, parece que la propiedad NoDelay solo afecta a la siguiente llamada al Send con un búfer no vacío. En otras palabras, debe enviar algunos datos reales antes de que NoDelay tenga algún efecto.

Por lo tanto, llego a la conclusión de que no hay forma de purgar explícitamente el socket si no desea enviar datos adicionales.

Sin embargo, puesto que usted está escribiendo un servidor HTTP, es posible que pueda utilizar algunos trucos:

  • Para las solicitudes que se sirven usando Transfer-Encoding: chunked, puede enviar el marcador de fin de flujo (la "\r\n0\r\n\r\n") con NoDelay = true.
  • Si está sirviendo un archivo del sistema de archivos local, sabrá cuándo finaliza el archivo, por lo que podría establecer NoDelay = true justo antes de enviar el último fragmento.
  • Para las solicitudes que se sirven utilizando Content-Encoding: gzip, puede establecer NoDelay = true justo antes de cerrar la secuencia de gzip; la corriente gzip enviará algunos últimos bits antes de terminar y cerrar.

estoy seguro que va a agregar a lo anterior a mi servidor HTTP ahora :)

+2

Si solo tuviéramos un [TCP Nagle flush] (http://stackoverflow.com/questions/6726832/what-happened-to-the-tcp-nagle-flush) ... –

+0

Podría ser que esté ejecutando Windows que tiene una implementación diferente? – hultqvist

-3

No hay tal cosa como el enjuague en TCP. TCP es un protocolo basado en secuencias que agrupa/desagrupa/divide/une sus datos. Al desactivar Nagle solo lo hará con menos frecuencia.

No desactive nagle.

El Nagle TCP/IP algoritmo fue diseñados para evitar problemas con los pequeños paquetes, llamados tinygrams, en redes lentas. El algoritmo indica que una conexión TCP/IP solo puede tener segmento pequeño sobresaliente que no tiene reconocido. La definición de "pequeño" varía, pero por lo general es definida como "menor que el segmento tamaño" que en ethernet es aproximadamente 1500 bytes.

Tome un vistazo a aquí: Disabling TCP/IP Nagle Algorithm Improves Speed on Slow Nets

+3

Exactamente por qué no debería deshabilitar el algoritmo de Nagle por un período corto? Al parecer, me dio una mejora de 8 veces en el tiempo de respuesta. – hultqvist

+0

Relacionado: [qué pasó con la descarga TCP Nagle] (http://stackoverflow.com/questions/6726832/what-happened-to-the-tcp-nagle-flush). Me pregunto de dónde viene esta idea de que el lavado TCP no tiene sentido y/o no existe. –

+0

Flushing tiene sentido en las transmisiones. Y decir que TCP no es compatible con el enjuague es engañoso. La mayoría de las implementaciones de TCP no admiten el vaciado explícito de sus buffers de envío, pero eso no es una limitación de TCP, eso es una limitación de estas implementaciones. Y hay escenarios en los que un enrojecimiento para evitar el nagle en los puntos seleccionados sería muy útil. – CodesInChaos

1

haber escrito un servidor web muy popular yo no creo que Nagle algortihm es su verdadero problema.

¿Cómo construyes tus respuestas y cómo las envías?

+0

He actualizado mi pregunta, los datos se envían en una sola llamada a Socket.Send (Byte [] ,,), aunque el contenido es bastante pequeño 400 bytes. – hultqvist