Attention, cet article a plus d'une année d'ancienneté. Il est possible que les informations présentées ne soient plus à jour, spécialement dans le cadre d'un article technique.
Bonjour à tous,
Aujourd’hui, je vais vous parler d’une optimisation sympathique qui est apparue dans la version 1.7.1.1 de Nginx.
Cette nouvelle fonctionnalité porte le doux nom de Thread Pools.
L’explication sur les Thread Pools :
Si vous connaissez déjà un peu mon site, vous avez surement mangé du Nginx à toutes les sauces vu comment je suis devenu accro à ce serveur web qui peut aussi servir de reverse proxy.
Nginx fonctionne donc à l’aide de Worker, un ou plusieurs, selon sa configuration.
Chaque Worker va traiter de façon indépendante les connexions qu’il recevra.
Avec ce système multi-tâches Nginx jouis de la rapidité et de la robustesse qu’on lui connait maintenant, le blocage d’un Worker n’entraînera pas le blocage complet de Nginx.
Cependant, comme je viens de l’écrire un Worker peut bloquer, mettant en attente toutes les opérations de sa file d’attente et donc plusieurs visiteurs qui tentent de se connecter à votre site/service web.
Si vous utilisez par exemple quatre Workers et que l’un d’entre eux bloquent, c’est 25% des visiteurs en attente sur le Worker occupé qui pourraient avoir une mauvaise expérience de navigation.
Dans un exemple plus parlant, imaginez-vous dans un supermarché avec quatre caisses ouvertes.
A l’une de ces caisses, un client qui doit payer cherche sa monnaie depuis deux minutes dans son porte-monnaie.
C’est un évènement bloquant et tous les clients dans la file de cette caisse verront leur passage retardé de deux minutes (au minimum).
Si vous avez compris le problème avec la caisse dans un supermarché alors, vous avez compris le problème que rencontre Nginx.
Les thread pools permettent d’esquiver ce problème par un mécanisme simple.
Vous rajoutez plusieurs threads indépendants dans un même worker tout en sachant que vous pouvez rajouter des dizaines voir des centaines de thread pour chaque Worker.
Par exemple, si vous assignez 300 threads à un worker, il ne faudra plus 1, mais 300 événements bloquants pour bloquer ce worker et sa file d’attente.
Le système n’est pas infaillible, mais il est beaucoup plus compliqué d’obtenir une situation réellement bloquante et gênante pour les utilisateurs.
C’est plus facile de bloquer 4 Workers que 4 Workers * 32 Threads par exemple.
La mise en place :
Souvenez-vous qu’il faut au minimum la version 1.7.1.1 de Nginx, la version 1.8 (compatible donc) est disponible dans les dépôts de dotdeb.
La méthode bête et méchante :
Vous ouvrez votre fichier de configuration Nginx avec la commande suivante :
nano /etc/nginx/nginx.conf
Et vous rajoutez la ligne suivante juste après l’ouverture de la section HTTP :
aio threads;
Vous fermez et vous redémarrez Nginx :
systemctl restart nginx
La méthode propre :
Vous ouvrez chaque vhost et vous créez un pool différent pour chaque vhost :
# in the 'main' context thread_pool nom-du-pool threads=32 max_queue=65536; # in the 'http', 'server', or 'location' context aio threads=nom-du-pool;
Vous fermez et vous redémarrez Nginx :
systemctl restart nginx
Si vous voulez plus d’exemples, vous pouvez regarder le billet officiel de Nginx sur le sujet.
Yop!
Merci pour l’astuce 🙂