web-dev-qa-db-fra.com

HTTP2 avec node.js derrière le proxy nginx

J'ai un serveur node.js fonctionnant derrière un proxy nginx. node.js exécute un serveur HTTP 1.1 (sans SSL) sur le port 3000. Les deux s'exécutent sur le même serveur.

J'ai récemment configuré nginx pour utiliser HTTP2 avec SSL (h2). Il semble que HTTP2 soit effectivement activé et fonctionne.

Cependant, je veux savoir si le fait que la connexion proxy (nginx <--> node.js) utilise HTTP 1.1 affecte les performances. Autrement dit, est-ce que je manque les avantages HTTP2 en termes de vitesse parce que ma connexion interne est HTTP 1.1?

33
Shade

En général, le plus grand avantage immédiat de HTTP/2 est l'augmentation de vitesse offerte par multiplexage pour les connexions du navigateur qui sont souvent gênées par une latence élevée (c'est-à-dire une vitesse aller-retour lente). Celles-ci réduisent également le besoin (et les dépenses) de plusieurs connexions, ce qui est une solution de contournement pour essayer d'obtenir des avantages de performances similaires dans HTTP/1.1.

Pour les connexions internes (par exemple entre un serveur Web agissant en tant que proxy inverse et des serveurs d'applications d'arrière-plan), la latence est généralement très, très faible, de sorte que les avantages de vitesse de HTTP/2 sont négligeables. De plus, chaque serveur d'application sera généralement déjà une connexion distincte, donc là encore aucun gain ici.

Ainsi, vous obtiendrez la plupart de vos avantages en termes de performances en prenant simplement en charge HTTP/2 sur Edge. Il s'agit d'une configuration assez courante - similaire à la façon dont HTTPS est souvent terminé sur le proxy inverse/équilibreur de charge plutôt que de passer par tout le chemin.

Cependant, il existe des avantages potentiels à prendre en charge HTTP/2 tout au long. Par exemple, cela pourrait permettre au serveur de pousser complètement depuis l'application. Bénéfices potentiels d'une taille de paquet réduite pour ce dernier saut en raison de la nature binaire de HTTP/2 et de la compression d'en-tête. Bien que, comme la latence, la bande passante soit généralement moins problématique pour les connexions internes, son importance est donc discutable. Enfin, certains soutiennent qu'un proxy inverse fonctionne moins en connectant une connexion HTTP/2 à une connexion HTTP/2 qu'il ne le ferait à une connexion HTTP/1.1 car il n'est pas nécessaire de convertir un protocole en l'autre, bien que je sceptique si c'est même notable car ce sont des connexions distinctes (à moins qu'il agisse simplement comme un TCP passe par proxy). Donc, pour moi, la principale raison de HTTP/2 de bout en bout est de permettre à un serveur de bout en bout Push, mais même cela est probablement mieux géré avec les en-têtes de lien HTTP et les 103 premiers indices en raison des complications de la gestion de Push sur plusieurs connexions .

Pour l'instant, alors que les serveurs ajoutent toujours la prise en charge et que l'utilisation de Push serveur est faible (et encore en cours d'expérimentation pour définir les meilleures pratiques), je recommanderais uniquement d'avoir HTTP/2 au point final. Nginx ne prend pas non plus en charge, au moment de l'écriture, HTTP/2 pour les connexions ProxyPass (bien qu'Apache le fasse), et a pas de plan pour l'ajouter , et ils font un point intéressant sur la question de savoir si un La connexion HTTP/2 peut introduire de la lenteur (c'est moi qui souligne):

La prise en charge du proxy HTTP/2 est-elle prévue dans un avenir proche?

Réponse courte:

Non, il n'y a aucun plan.

Longue réponse:

Cela n'a presque aucun sens de l'implémenter, car le principal avantage de HTTP/2 est qu'il permet de multiplexer de nombreuses demandes au sein d'une même connexion, supprimant ainsi [presque] la limite du nombre de demandes simultanées - et il n'y a pas de telle limite lorsque vous parlez à vos propres backends. De plus, les choses peuvent même empirer lors de l'utilisation de HTTP/2 pour les backends, en raison de la connexion unique TCP utilisée au lieu de plusieurs .

D'un autre côté, la mise en œuvre du protocole HTTP/2 et la demande de multiplexage au sein d'une seule connexion dans le module amont nécessiteront des modifications majeures du module amont.

En raison de ce qui précède, il n'est pas prévu d'implémenter la prise en charge HTTP/2 dans le module en amont, au moins dans un avenir prévisible. Si vous pensez toujours que parler aux backends via HTTP/2 est quelque chose de nécessaire - n'hésitez pas à fournir des correctifs.

Enfin, il convient également de noter que, alors que les navigateurs nécessitent HTTPS pour HTTP/2 (h2), la plupart des serveurs ne le font pas et pourraient donc prendre en charge ce saut final sur HTTP (h2c). Il n'y aurait donc pas besoin de chiffrement de bout en bout s'il n'est pas présent sur la partie Node (comme ce n'est souvent pas le cas). Cependant, en fonction de l'emplacement du serveur principal par rapport à la serveur frontal, utiliser HTTPS même pour cette connexion est peut-être quelque chose qui devrait être pris en compte si le trafic circule sur un réseau non sécurisé (par exemple, CDN vers le serveur Origin sur Internet).

47
Barry Pollard

NGINX prend désormais en charge HTTP2/Push et c'est génial ...

Ici, je pousse favicon.ico, minified.css, minified.js, register.svg, Purchase_litecoin.svg à partir de mon sous-domaine statique également. Il m'a fallu un certain temps pour réaliser que je peux pousser à partir d'un sous-domaine.

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;
        }
6
indospace.io

NGINX ne prend pas en charge HTTP/2 en tant que client. Comme ils fonctionnent sur le même serveur et qu'il n'y a pas de latence ou de bande passante limitée, je ne pense pas que cela ferait une énorme différence dans les deux cas. Je m'assurerais que vous utilisez des keepalives entre nginx et node.js.

https://www.nginx.com/blog/tuning-nginx/#keepalive

6
Faisal Memon

Vous ne perdez pas les performances en général, car nginx correspond au multiplexage des requêtes que le navigateur fait sur HTTP/2 en créant plusieurs requêtes simultanées vers votre backend de nœud. (L'une des principales améliorations des performances de HTTP/2 est de permettre au navigateur d'effectuer plusieurs demandes simultanées sur la même connexion, alors que dans HTTP 1.1, une seule demande simultanée par connexion est possible. Et les navigateurs limitent également le nombre de connexions.)

3
Digitalkapitaen

Dans le cas où quelqu'un cherche une solution à ce sujet quand il n'est pas pratique de rendre vos services HTTP2 compatibles. Voici la configuration de base NGINX que vous pouvez utiliser pour convertir le service HTTP1 en service 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;
  }
}
2
Sheng