nodejs - node.js production server
HTTP2 con node.js detrĂ¡s del proxy nginx (5)
Tengo un servidor node.js ejecutándose detrás de un proxy nginx. node.js ejecuta un servidor HTTP 1.1 (sin SSL) en el puerto 3000. Ambos se ejecutan en el mismo servidor.
Recientemente configuré nginx para usar HTTP2 con SSL (h2). Parece que HTTP2 está habilitado y funciona.
Sin embargo, quiero saber si el hecho de que la conexión proxy (nginx <--> node.js) esté utilizando HTTP 1.1 afecta el rendimiento. Es decir, ¿me estoy perdiendo los beneficios de HTTP2 en términos de velocidad porque mi conexión interna es HTTP 1.1?
En caso de que alguien esté buscando una solución para esto cuando no sea conveniente hacer que sus servicios sean compatibles con HTTP2. Aquí está la configuración básica de NGINX que puede usar para convertir el servicio HTTP1 en el servicio HTTP2.
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name localhost;
ssl on;
ssl_certificate /Users/xxx/ssl/myssl.crt;
ssl_certificate_key /Users/xxx/ssl/myssl.key;
location / {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
En general, el mayor beneficio inmediato de HTTP / 2 es el aumento de velocidad que ofrece la multiplexing para las conexiones del navegador, que a menudo se ven obstaculizadas por una alta latencia (es decir, una lenta velocidad de ida y vuelta). Esto también reduce la necesidad (y el gasto) de múltiples conexiones, lo cual es una solución para tratar de lograr beneficios de rendimiento similares en HTTP / 1.1.
Para las conexiones internas (p. Ej., Entre el servidor web que actúa como un proxy inverso y los servidores de aplicaciones back-end), la latencia suele ser muy, muy baja, por lo que los beneficios de velocidad de HTTP / 2 son insignificantes. Además, cada servidor de aplicaciones generalmente ya será una conexión separada, por lo que nuevamente no habrá ganancias aquí.
Por lo tanto, obtendrá la mayor parte de su beneficio de rendimiento si solo admite HTTP / 2 en el borde. Esta es una configuración bastante común, similar a la forma en que HTTPS a menudo termina en el proxy inverso / equilibrador de carga en lugar de pasar por completo.
Sin embargo, existen beneficios potenciales para soportar HTTP / 2 en todo momento. Por ejemplo, podría permitir la inserción del servidor desde la aplicación. También beneficios potenciales de un tamaño de paquete reducido para ese último salto debido a la naturaleza binaria de HTTP / 2 y la compresión de encabezado. Sin embargo, al igual que la latencia, el ancho de banda suele ser un problema menor para las conexiones internas, por lo que la importancia de esto es discutible. Finalmente, algunos sostienen que un proxy inverso funciona menos conectando una conexión HTTP / 2 a una conexión HTTP / 2 que a una conexión HTTP / 1.1, ya que no es necesario convertir un protocolo a otro, aunque soy escéptico si eso es así notable ya que son conexiones separadas (a menos que esté actuando simplemente como un paso TCP a través del proxy). Entonces, para mí, la razón principal para HTTP / 2 de extremo a extremo es permitir la inserción de servidor de extremo a extremo, pero incluso eso probablemente se maneja mejor con encabezados de enlace HTTP y 103-Early Hints debido a las complicaciones en la administración de la inserción a través de múltiples conexiones .
Por ahora, aunque los servidores siguen agregando soporte y el uso de inserción del servidor es bajo (y todavía se está experimentando para definir las mejores prácticas), recomendaría solo tener HTTP / 2 en el punto final. Nginx tampoco admite, en el momento de la escritura, HTTP / 2 para conexiones ProxyPass (aunque Apache lo hace), y no tiene planes de agregar esto , y hacen un punto interesante sobre si una sola conexión HTTP / 2 podría introducir lentitud (énfasis mío):
¿Está previsto el soporte de proxy HTTP / 2 para el futuro cercano?
Respuesta corta:
No, no hay planes.
Respuesta larga:
Casi no tiene sentido implementarlo, ya que el principal beneficio de HTTP / 2 es que permite multiplexar muchas solicitudes dentro de una sola conexión, eliminando así [casi] el límite en el número de solicitudes simultáneas, y no existe tal límite cuando se habla con tus propios backends Además, las cosas pueden empeorar cuando se usa HTTP / 2 para backends, debido a que se usa una conexión TCP única en lugar de múltiples .
Por otro lado, la implementación del protocolo HTTP / 2 y la multiplexación de solicitudes dentro de una sola conexión en el módulo ascendente requerirá cambios importantes en el módulo ascendente.
Debido a lo anterior, no hay planes para implementar el soporte HTTP / 2 en el módulo ascendente, al menos en el futuro previsible. Si aún cree que hablar con backends a través de HTTP / 2 es algo necesario, no dude en proporcionar parches.
Finalmente, también se debe tener en cuenta que, si bien los navegadores requieren HTTPS para HTTP / 2 (h2), la mayoría de los servidores no lo hacen y, por lo tanto, podrían soportar este salto final sobre HTTP (h2c). Por lo tanto, no habría necesidad de cifrado de extremo a extremo si eso no está presente en la parte Nodo (como a menudo no lo está). Sin embargo, dependiendo de dónde se encuentre el servidor back-end en relación con el servidor front-end, el uso de HTTPS incluso para esta conexión es quizás algo que debería considerarse si el tráfico viajará a través de una red no segura (por ejemplo, CDN al servidor de origen a través de Internet).
NGINX ahora es compatible con HTTP2 / Push y es increíble ...
Aquí estoy empujando favicon.ico, minified.css, minified.js, register.svg, buy_litecoin.svg de mi subdominio estático también. Me tomó un tiempo darme cuenta de que puedo empujar desde un subdominio.
location / {
http2_push_preload on;
add_header Link "<//static.yourdomain.io/css/minified.css>; as=style; rel=preload";
add_header Link "<//static.yourdomain.io/js/minified.js>; as=script; rel=preload";
add_header Link "<//static.yourdomain.io/favicon.ico>; as=image; rel=preload";
add_header Link "<//static.yourdomain.io/images/register.svg>; as=image; rel=preload";
add_header Link "<//static.yourdomain.io/images/purchase_litecoin.svg>; as=image; rel=preload";
proxy_hide_header X-Frame-Options;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://app_service;
}
NGINX no es compatible con HTTP / 2 como cliente. Como se están ejecutando en el mismo servidor y no hay latencia o ancho de banda limitado, no creo que haga una gran diferencia de ninguna manera. Me aseguraría de que esté utilizando keepalives entre nginx y node.js.
No está perdiendo rendimiento en general, porque nginx coincide con la multiplexación de solicitudes que hace el navegador a través de HTTP / 2 al crear múltiples solicitudes simultáneas en el backend de su nodo. (Una de las principales mejoras de rendimiento de HTTP / 2 es permitir que el navegador realice múltiples solicitudes simultáneas a través de la misma conexión, mientras que en HTTP 1.1 solo es posible una solicitud simultánea por conexión. Y los navegadores también limitan el número de conexiones).