Équilibrage de charge avec NGINX et NGINX Plus, partie 2

NGINX | 17 mars 2014

Dans « Répartition de charge avec NGINX et NGINX Plus, partie 1 », nous avons configuré un proxy HTTP simple afin de répartir la charge du trafic entre plusieurs serveurs web. Dans cet article, nous examinerons des fonctionnalités supplémentaires, dont certaines sont disponibles dans NGINX Plus : l’optimisation des performances grâce aux connexions persistantes, les contrôles d’intégrité, la persistance de session, les redirections et la réécriture de contenu.

Pour en savoir plus sur les fonctionnalités d’équilibrage de charge de NGINX et NGINX Plus, consultez le Guide d’administration de NGINX Plus.

Note de l’éditeur – NGINX Plus version 5 et les versions ultérieures peuvent également répartir la charge des applications basées sur TCP. Les fonctionnalités de répartition de charge TCP ont été considérablement étendues dans la version 6 avec l’ajout des contrôles d’intégrité, de la reconfiguration dynamique, de la terminaison SSL, entre autres. Dans NGINX Plus version 7 et les versions ultérieures, le répartiteur de charge TCP offre les mêmes fonctionnalités que le répartiteur de charge HTTP. La prise en charge de la répartition de charge UDP a été introduite dans la version 9.

Vous configurez l’équilibrage de charge TCP et UDP dans le contexte stream plutôt que dans le contexte http. Les directives et paramètres disponibles diffèrent quelque peu en raison des différences intrinsèques entre HTTP et TCP/UDP. Pour plus de détails, consultez la documentation des modules Upstream HTTP et TCP/UDP.

Petit rappel

Pour rappel, voici la configuration que nous avons créée dans l’article précédent :

server {    listen 80;

    location / {
        proxy_pass http://backend;

        # Rewrite the 'Host' header to the value in the client request,
        # or primary server name
        proxy_set_header Host $host;

        # Alternatively, put the value in the config:
        # proxy_set_header Host www.example.com;
    } 
}

upstream backend {
    zone backend 64k;  # Use NGINX Plus' shared memory
    least_conn;

    server webserver1 weight=1;
    server webserver2 weight=4;
}

Dans cet article, nous allons examiner quelques méthodes simples pour configurer NGINX et NGINX Plus afin d’améliorer l’efficacité de la répartition de charge.

Connexions HTTP persistantes

L’activation des connexions HTTP persistantes entre NGINX ou NGINX Plus et les serveurs en amont améliore les performances (en réduisant la latence) et diminue le risque que NGINX épuise les ports éphémères.

Le protocole HTTP utilise des connexions TCP sous-jacentes pour transmettre les requêtes HTTP et recevoir les réponses HTTP. Les connexions HTTP persistantes permettent de réutiliser ces connexions TCP, évitant ainsi le coût lié à la création et à la fermeture d’une connexion pour chaque requête :

NGINX est un proxy complet qui gère indépendamment les connexions des clients (connexions persistantes côté frontal) et les connexions aux serveurs (connexions persistantes en amont) :

NGINX maintient un « cache » de connexions persistantes — un ensemble de connexions persistantes inactives vers les serveurs en amont — et, lorsqu’il doit transmettre une requête à un serveur en amont, il utilise une connexion persistante déjà établie provenant du cache plutôt que de créer une nouvelle connexion TCP. Cela réduit la latence des échanges entre NGINX et les serveurs en amont, ainsi que la fréquence d’utilisation des ports éphémères, ce qui permet à NGINX d’absorber et de répartir de gros volumes de trafic. En cas de forte hausse du trafic, le cache peut être vidé ; NGINX établit alors de nouvelles connexions HTTP vers les serveurs en amont.

Avec d’autres outils de répartition de charge, cette technique est parfois appelée « multiplexage », « regroupement de connexions », « réutilisation des connexions » ou « OneConnect ».

Vous configurez le cache des connexions persistantes en incluant les directives « proxy_http_version », « proxy_set_header » et « keepalive » dans la configuration :

server {    listen 80;
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
     }
}

upstream backend {
    server webserver1;
    server webserver2;

    # maintain up to 20 idle connections to the group of upstream servers
    keepalive 20;
}

Bilans de santé

L’activation des contrôles d’intégrité améliore la fiabilité de votre service avec répartition de charge, réduit le risque que les utilisateurs finaux voient des messages d’erreur et peut également faciliter les opérations de maintenance courantes.

La fonctionnalité de « contrôle d’intégrité » de NGINX Plus permet de détecter les défaillances des serveurs en amont. NGINX Plus sonde chaque serveur à l’aide de « transactions synthétiques » et vérifie la réponse en fonction des paramètres configurés dans la directive health_check (et, lorsque vous incluez le paramètre match, dans le bloc de configuration match associé) :

server {    listen 80;

    location / {
        proxy_pass http://backend;

        health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;

        # The health checks inherit other proxy settings
        proxy_set_header Host www.foo.com;
    }
}

match statusok {
    # Used for /test.php health check
    status 200;
    header Content-Type = text/html;
    body ~ "Server[0-9]+ is alive";
}

Le contrôle d’intégrité hérite de certains paramètres de son bloc location parent. Cela peut poser problème si vous utilisez des variables d’exécution dans votre configuration. Par exemple, la configuration suivante fonctionne pour le trafic HTTP réel, car elle extrait la valeur de l’en-tête Host de la requête du client. Elle ne fonctionne probablement pas pour les transactions synthétiques utilisées par le contrôle d’intégrité, car l’en-tête Host n’est pas défini pour celles-ci, ce qui signifie qu’aucun en-tête Host n’est utilisé dans la transaction synthétique.

location / {    proxy_pass http://backend;

    # This health check might not work...
    health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;

    # Extract the 'Host' header from the request
    proxy_set_header Host $host;
}

Une bonne solution consiste à créer un bloc location factice qui définit de manière statique tous les paramètres utilisés par la transaction de contrôle d’intégrité :

location /internal-health-check1 {    internal; # Prevent external requests from matching this location block

    proxy_pass http://backend;

    health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;

    # Explicitly set request parameters; don't use run-time variables
    proxy_set_header Host www.example.com;
}

Pour plus d’informations, consultez le Guide d’administration de NGINX Plus.

Persistance de session

Grâce à la persistance des sessions, les applications qui ne peuvent pas être déployées dans un cluster peuvent bénéficier d’un équilibrage de charge et être mises à l’échelle de manière fiable. Les applications qui stockent et répliquent l’état des sessions fonctionnent plus efficacement, et les performances pour l’utilisateur final s’améliorent.

Certaines applications stockent parfois des informations d’état sur les serveurs en amont, par exemple lorsqu’un utilisateur ajoute un article à un panier virtuel ou modifie une image téléversée. Dans ce cas, vous pouvez souhaiter rediriger toutes les requêtes ultérieures de cet utilisateur vers le même serveur.

La persistance de session indique vers quel serveur une requête doit être acheminée, tandis que l’équilibrage de charge laisse à NGINX la liberté de sélectionner le serveur en amont optimal. Ces deux mécanismes peuvent coexister grâce à la fonctionnalité de persistance de session de NGINX Plus :

Si la requête correspond à une règle de persistance de session
alors utiliser le serveur en amont cible
sinon appliquer l’algorithme d’équilibrage de charge pour sélectionner le serveur en amont

Si la décision de persistance de session échoue parce que le serveur cible n’est pas disponible, NGINX Plus prend alors une décision d’équilibrage de charge.

La méthode de persistance de session la plus simple est l’approche dite du « cookie persistant », dans laquelle NGINX Plus insère dans la première réponse un cookie qui identifie le serveur en amont auquel la session est associée :

sticky cookie srv_id expires=1h domain=.example.com path=/;

Avec l’autre méthode, dite « sticky route », NGINX sélectionne le serveur en amont en fonction de paramètres de la requête, tels que le cookie JSESSIONID :

upstream backend {
   server backend1.example.com route=a;
   server backend2.example.com route=b;

    # select first non-empty variable; it should contain either 'a' or 'b'
    sticky route $route_cookie $route_uri;
}

Pour plus d’informations, consultez le guide d’administration de NGINX Plus.

Réécriture des redirections HTTP

Réécrivez les redirections HTTP si certaines ne fonctionnent pas, en particulier si vous constatez que vous êtes redirigé du proxy vers le véritable serveur en amont.

Lorsque vous utilisez un proxy vers un serveur en amont, celui-ci publie l’application sur une adresse locale, mais vous y accédez via une autre adresse : celle du proxy. Ces adresses correspondent généralement à des noms de domaine, et des problèmes peuvent survenir si le serveur et le proxy utilisent des domaines différents.

Par exemple, dans un environnement de test, vous pouvez accéder directement à votre proxy (par son adresse IP) ou via localhost. Cependant, le serveur en amont peut être à l’écoute sur un véritable nom de domaine (tel que www.nginx.com). Lorsque le serveur en amont émet un message de redirection (à l’aide d’un code d’état 3xx et d’un en-tête Location, ou d’un en-tête Refresh), le message peut inclure le véritable domaine du serveur.

NGINX tente d’intercepter et de corriger les cas les plus courants de ce problème. Si vous avez besoin d’un contrôle total pour imposer des réécritures particulières, utilisez la directive proxy_redirect comme suit :

proxy_redirect http://staging.mysite.com/ http://$host/;

Réécriture des réponses HTTP

Il est parfois nécessaire de réécrire le contenu d’une réponse HTTP. Comme dans l’exemple ci-dessus, la réponse contient peut-être des liens absolus qui renvoient vers un serveur autre que le proxy.

Vous pouvez utiliser la directive « sub_filter » pour définir la réécriture à appliquer :

sub_filter /blog/ /blog-staging/;
sub_filter_once off;

Un piège très courant concerne l’utilisation de la compression HTTP. Si le client indique qu’il peut accepter des données compressées et que le serveur compresse alors la réponse, NGINX ne peut ni inspecter ni modifier celle-ci. La solution la plus simple consiste à supprimer l’en-tête Accept-Encoding de la requête du client en lui attribuant une chaîne vide ("") :

proxy_set_header Accept-Encoding "";

Un exemple complet

Voici un modèle de configuration d’équilibrage de charge qui met en œuvre toutes les techniques abordées dans cet article. Les fonctionnalités avancées disponibles dans NGINX Plus sont surlignées en orange.

[Note de la rédaction – La configuration suivante a été mise à jour afin d’utiliser l’API de NGINX Plus pour la surveillance de l’activité en temps réel et la configuration dynamique des groupes de serveurs en amont, en remplacement des modules distincts utilisés à l’origine.]

server {
    listen 80;

    location / {
        proxy_pass http://backend;

        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Accept-Encoding "";
        proxy_redirect http://staging.example.com/ http://$host/;

        # Rewrite the Host header to the value in the client request
        proxy_set_header Host $host;

        # Replace any references inline to staging.example.com
        sub_filter http://staging.example.com/ /;
        sub_filter_once off;
    }

    location /internal-health-check1 {
        internal; # Prevent external requests from matching this location block
        proxy_pass http://backend;
        health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
        # Explicitly set request parameters; don't use runtime variables
        proxy_set_header Host www.example.com;
    }
 
upstream backend {
    zone backend 64k; # Use NGINX Plus' shared memory
    least_conn;
    keepalive 20;

    # Apply session persistence for this upstream group
    sticky cookie srv_id expires=1h domain=.example.com path=/servlet;

    server webserver1 weight=1; 
    server webserver2 weight=4; 
}

match statusok {
    # Used for /test.php health check
    status 200;
    header Content-Type = text/html;
    body ~ "Server[0-9]+ is alive";
}

server {
    listen 8080;
    root /usr/share/nginx/html;

    location = /api {
        api write=on; # Live activity monitoring and
                      # dynamic configuration of upstream groups

        allow 127.0.0.1; # permit access from localhost
        deny all;        # deny access from everywhere else
    }
}

Testez par vous-même toutes les excellentes fonctionnalités d’équilibrage de charge de NGINX Plus : commencez dès aujourd’hui votre essai gratuit de 30 jours ou contactez-nous pour discuter de vos cas d’utilisation.


Partager

À propos de l’auteur

Owen Garrett
Owen GarrettDirecteur senior de la gestion des produits

Autres articles de Owen Garrett

Articles de blog associés

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA
NGINX | 13/10/2025

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA

Découvrez les principaux enseignements tirés des réponses à l’enquête annuelle F5 NGINX sur les dernières tendances en matière de technologies cloud natives, de sécurité, d’ingénierie de plateforme et d’IA.

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?
NGINX | 03/11/2023

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?

Lorsque de nouvelles CVE sont signalées, il est facile de ne plus savoir si elles concernent un outil de contrôleur Ingress NGINX particulier, car il existe plusieurs projets. Cet article présente les CVE et explique comment distinguer les différents projets de contrôleurs Ingress afin de dissiper toute confusion.

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX
NGINX | 11/03/2020

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX

Votre API répond-elle aux requêtes en moins de 30 ms ? Si ce n’est pas le cas, il ne s’agit pas d’une API en temps réel offrant la faible latence exigée par la grande majorité des organisations. Mesurez la latence de votre API avec l’outil rtapi de NGINX et découvrez comment NGINX peut l’aider à offrir une réactivité en temps réel.

Un testeur d’expressions régulières pour NGINX et NGINX Plus
NGINX | 11/06/2019

Un testeur d’expressions régulières pour NGINX et NGINX Plus

Le testeur d’expressions régulières (regex) pour NGINX et NGINX Plus vous évite de tâtonner en vous indiquant si une expression régulière utilisée dans un bloc location ou map correspond aux valeurs comme prévu. Il génère la configuration appropriée et affiche les valeurs des groupes de capture.

Caches partagés avec les clusters de cache NGINX Plus, partie 1
NGINX | 24/01/2017

Caches partagés avec les clusters de cache NGINX Plus, partie 1

Optimisez la capacité de votre cache web en le répartissant entre plusieurs serveurs de cache web NGINX ou NGINX Plus. Découvrez comment procéder dans cet article.

Introduction aux microservices
NGINX | 19/05/2015

Introduction aux microservices

Les microservices suscitent actuellement beaucoup d’intérêt. Cet article de blog est le premier d’une série de sept consacrée à la conception, au développement et au déploiement de microservices.