Marc Brooker, ingeniero de Amazon Web Services (AWS), ha abordado los conceptos erróneos relacionados con la mejora de la eficiencia en la transmisión de pequeños mensajes al utilizar el algoritmo de Nagle, que se aplica por defecto en la pila TCP/IP. Las recomendaciones se centran en desactivar el algoritmo de Nagle por defecto, lo cual se puede hacer en el contexto de aplicaciones específicas mediante la opción TCP_NODELAY para los sockets de red utilizando la llamada setsockopt, algo que ya se hace desde hace tiempo en proyectos como Node.js y curl.
El algoritmo de Nagle permite agregar pequeños mensajes para reducir el tráfico; retarda el envío de nuevos segmentos TCP hasta recibir la confirmación de la recepción de datos previamente enviados. Por ejemplo, sin la agregación, al enviar 1 byte, se envían 40 bytes adicionales con las cabeceras de los paquetes TCP e IP. En las condiciones actuales, el uso del algoritmo de Nagle lleva a un aumento notable en las demoras, inaceptables para aplicaciones interactivas y distribuidas.
Se presentan tres argumentos principales a favor del uso por defecto de la opción TCP_NODELAY, que desactiva el algoritmo de Nagle:
- Incompatibilidad del algoritmo de Nagle con la optimización 'delayed ACK', donde la respuesta ACK no se envía de inmediato, sino después de recibir datos de respuesta. El problema es que en el algoritmo de Nagle, la llegada del paquete ACK es una señal para enviar los datos agregados, y si no se recibe el paquete ACK, el envío se realiza al vencer el tiempo de espera. Así, se genera un círculo vicioso y el paquete ACK como señal no funciona, ya que la otra parte no recibe los datos debido a su acumulación en el lado del emisor, y el emisor no los envía hasta que vence el tiempo de espera, ya que no recibe el paquete ACK.
- El RFC para el algoritmo de Nagle fue aceptado en 1984 y no está diseñado para los parámetros de las modernas redes de alta velocidad y servidores en los centros de datos, lo que provoca problemas de capacidad de respuesta. La demora entre el envío de la solicitud y la recepción de la respuesta (RTT) en redes modernas es de 0.5 ms más varios milisegundos en la comunicación entre centros de datos en una misma región, y hasta cientos de milisegundos al enviar datos alrededor del mundo. En esos milisegundos, un servidor moderno puede realizar una enorme cantidad de trabajo.
- Las aplicaciones distribuidas modernas no envían unidades individuales de datos, y la agregación de pequeños datos generalmente se implementa a nivel de aplicación. Incluso si el tamaño de los datos útiles es de solo unos pocos bytes, generalmente el tamaño real de la información enviada aumenta significativamente después de aplicar la serialización, utilizar envoltorios de API en JSON y enviarla usando cifrado TLS. Ahorrar 40 bytes se vuelve menos relevante.
Fuente: opennet.ru
