¿Los servidores proxy inversos HTTP suelen habilitar HTTP Keep-Alive en el lado del cliente de la conexión proxy y no en el lado del servidor?

30

HAProxy tiene la capacidad de habilitar HTTP keep-alive en el lado del cliente (cliente <-> HAProxy) pero deshabilitarlo en el lado del servidor (HAProxy <-> servidor).

Algunos de nuestros clientes se conectan a nuestro servicio web vía satélite, por lo que la latencia es de ~ 600 ms y creo que al permitir mantener vivo, acelerará un poco las cosas. Estoy en lo cierto?

¿Es compatible con Nginx? ¿Es esta una característica ampliamente implementada en otros equilibradores de carga de software y hardware? ¿Qué más además de HAProxy?

LostInComputer
fuente

Respuestas:

43

editar: Mi respuesta solo cubre la pregunta original sin editar, que era si este tipo de cosas es típico en equilibradores de carga / proxies inversos. No estoy seguro de si nginx / product X tiene soporte para esto, el 99.9% de mi experiencia de proxy inverso es con HAproxy.

Correcto. HTTP Keep-Alive en el lado del cliente, pero no en el lado del servidor.

¿Por qué?

Si desglosa algunos detalles, puede ver rápidamente por qué esto es un beneficio. Para este ejemplo, supongamos que estamos cargando una página www.example.com y esa página incluye 3 imágenes, img [1-3] .jpg.

Navegador cargando una página, sin Keep-Alive

  1. El cliente establece una conexión TCP a www.example.com en el puerto 80
  2. El cliente realiza una solicitud HTTP GET para "/"
  3. El servidor envía el contenido HTML del URI "/" (que incluye etiquetas HTML que hacen referencia a las 3 imágenes)
  4. El servidor cierra la conexión TCP
  5. El cliente establece una conexión TCP a www.example.com en el puerto 80
  6. El cliente realiza una solicitud HTTP GET para "/img1.jpg"
  7. El servidor envía la imagen.
  8. El servidor cierra la conexión TCP
  9. El cliente establece una conexión TCP a www.example.com en el puerto 80
  10. El cliente realiza una solicitud HTTP GET para "/img2.jpg"
  11. El servidor envía la imagen.
  12. El servidor cierra la conexión TCP
  13. El cliente establece una conexión TCP a www.example.com en el puerto 80
  14. El cliente realiza una solicitud HTTP GET para "/img3.jpg"
  15. El servidor envía la imagen.
  16. El servidor cierra la conexión TCP

Observe que hay 4 sesiones TCP separadas establecidas y luego cerradas.

Navegador cargando una página, con Keep-Alive

HTTP Keep-Alive permite una sola conexión TCP para atender múltiples solicitudes HTTP, una tras otra.

  1. El cliente establece una conexión TCP a www.example.com en el puerto 80
  2. El cliente realiza una solicitud HTTP GET para "/", y también le pide al servidor que haga de esta una sesión HTTP Keep-Alive.
  3. El servidor envía el contenido HTML del URI "/" (que incluye etiquetas HTML que hacen referencia a las 3 imágenes)
  4. El servidor no cierra la conexión TCP
  5. El cliente lo hace y la solicitud HTTP GET para "/img1.jpg"
  6. El servidor envía la imagen.
  7. El cliente lo hace y la solicitud HTTP GET para "/img2.jpg"
  8. El servidor envía la imagen.
  9. El cliente lo hace y la solicitud HTTP GET para "/img3.jpg"
  10. El servidor envía la imagen.
  11. El servidor cierra la conexión TCP si no se reciben más solicitudes HTTP dentro de su período de tiempo de espera HTTP Keep-Alive

Tenga en cuenta que con Keep-Alive, solo se establece 1 conexión TCP y finalmente se cierra.

¿Por qué es mejor Keep-Alive?

Para responder esto, debe comprender lo que se necesita para establecer una conexión TCP entre un cliente y un servidor. Esto se denomina protocolo de enlace TCP de 3 vías.

  1. El cliente envía un paquete SYN (cronisear)
  2. El servidor devuelve un SYN (cronisear) ACK (confirmación), SYN-ACK
  3. El cliente envía un paquete ACK (compromiso)
  4. La conexión TCP ahora se considera activa tanto por el cliente como por el servidor

Las redes tienen latencia, por lo que cada paso en el protocolo de enlace de 3 vías lleva una cierta cantidad de tiempo. Digamos que hay 30 ms entre el cliente y el servidor, el envío de paquetes IP necesarios para establecer la conexión TCP significa que se necesitan 3 x 30 ms = 90 ms para establecer una conexión TCP.

Puede que esto no parezca mucho, pero si consideramos que en nuestro ejemplo original, tenemos que establecer 4 conexiones TCP separadas, esto se convierte en 360 ms. ¿Qué sucede si la latencia entre el cliente y el servidor es de 100 ms en lugar de 30 ms? Entonces nuestras 4 conexiones tardan 1200ms en establecerse.

Peor aún, una página web típica puede requerir mucho más que solo 3 imágenes para cargar, puede haber múltiples CSS, JavaScript, imágenes u otros archivos que el cliente necesita solicitar. Si la página carga otros 30 archivos y la latencia cliente-servidor es de 100 ms, ¿cuánto tiempo pasamos estableciendo conexiones TCP?

  1. Para establecer 1 conexión TCP se necesitan 3 x latencia, es decir, 3 x 100 ms = 300 ms.
  2. Debemos hacer esto 31 veces, una vez para la página y otras 30 veces para cada otro archivo al que hace referencia la página. 31 x 300 ms = 9,3 segundos.

Pasaron 9,3 segundos estableciendo conexiones TCP para cargar una página web que hace referencia a otros 30 archivos. Y eso ni siquiera cuenta el tiempo empleado en enviar solicitudes HTTP y recibir respuestas.

Con HTTP Keep-Alive, solo necesitamos establecer 1 conexión TCP, que tarda 300 ms.

Si HTTP Keep-Alive es tan bueno, ¿por qué no usarlo también en el lado del servidor?

Los proxys inversos HTTP (como HAproxy) generalmente se implementan muy cerca de los servidores de back-end para los que realizan proxys. En la mayoría de los casos, la latencia entre el proxy inverso y sus servidores de fondo será inferior a 1 ms, por lo que establecer una conexión TCP es mucho más rápido que entre un cliente.

Sin embargo, esa es solo la mitad de la razón. Un servidor HTTP asigna una cierta cantidad de memoria para cada conexión de cliente. Con Keep-Alive, mantendrá viva la conexión y, por extensión, mantendrá una cierta cantidad de memoria en uso en el servidor, hasta que se alcance el tiempo de espera de Keep-Alive, que puede ser de hasta 15 segundos, dependiendo de la configuración del servidor .

Entonces, si consideramos los efectos del uso de Keep-Alive en el lado del servidor de un proxy inverso HTTP, estamos aumentando la necesidad de memoria, pero debido a que la latencia entre el proxy y el servidor es muy baja, no obtenemos un beneficio real del reducción del tiempo necesario para el protocolo de enlace de 3 vías de TCP, por lo que generalmente es mejor deshabilitar Keep-Alive entre el proxy y el servidor web en este escenario.

Descargo de responsabilidad: sí, esta explicación no tiene en cuenta el hecho de que los navegadores suelen establecer múltiples conexiones HTTP a un servidor en paralelo. Sin embargo, existe un límite para la cantidad de conexiones paralelas que un navegador realizará con el mismo host, y generalmente esto es lo suficientemente pequeño como para que sea deseable mantener vivo.

ThatGraemeGuy
fuente
55
Felicitaciones por la excelente explicación, Graeme, nunca dediqué suficiente tiempo para responder a quien me preguntó esto, y seguro que mantendré un enlace a esta publicación para que sirva como una respuesta muy clara ahora :-)
Willy Tarreau
2
¿Habría una ventaja para keepAlive en el lado del servidor si la conexión entre proxy y backend fuera https?
avmohan
"Un servidor HTTP asigna una cierta cantidad de memoria para cada conexión de cliente" sí, pero habrá pocas de esas conexiones (?) ¿Solo una por equilibrador de carga? No uno por cliente en Internet (?)
Raedwald
@Raedwald, si su equilibrador de carga se limita a hacer una única conexión HTTP a cada servidor respaldado, lo pasará muy mal. :-)
ThatGraemeGuy
7

Nginx admite mantener vivo en ambos lados.

VBart
fuente
¿Diría que Keep Live es útil para backends si hubiera latencia entre el proxy y los backends? Además, ¿cuál sería el número óptimo de conexiones activas para mantener?
CMCDragonkai
@CMCDragonkai Si sus servidores están ubicados en servidores dedicados, puede ser útil evitar la latencia de conexión que depende de su red. No hay una media de oro, el número óptimo depende principalmente de su configuración, su entorno, su aplicación y patrón de solicitud.
VBart
¡Espero encontrar una ecuación para resolver esto!
CMCDragonkai
2
La pregunta, tal como la leí, no es si nginx admite mantener vivo en el flujo ascendente, sino si nginx admite deshabilitar mantener vivo en el lado ascendente.
user45793