Node.js est l'outil leader pour la création d'applications serveur en JavaScript, le langage de programmation le plus populaire au monde. Offrant les fonctionnalités d’un serveur Web et d’un serveur d’applications, Node.js est désormais considéré comme un outil clé pour tous les types de développement et de livraison basés sur des microservices. (Téléchargez un rapport Forrester gratuit sur Node.js et NGINX .)
Node.js peut remplacer ou augmenter Java ou .NET pour le développement d'applications backend.
Node.js est monothread et utilise des E/S non bloquantes, ce qui lui permet de s'adapter et de prendre en charge des dizaines de milliers d'opérations simultanées. Il partage ces caractéristiques architecturales avec NGINX et résout le problème C10K – prenant en charge plus de 10 000 connexions simultanées – pour lequel NGINX a également été inventé . Node.js est réputé pour ses hautes performances et la productivité des développeurs.
Alors, qu’est-ce qui pourrait mal se passer ?
Node.js présente quelques points faibles et vulnérabilités qui peuvent rendre les systèmes basés sur Node.js sujets à des performances inférieures à la moyenne, voire à des pannes. Les problèmes surviennent plus fréquemment lorsqu’une application Web basée sur Node.js connaît une croissance rapide du trafic.
Node.js est également un excellent outil pour créer et exécuter une logique d’application qui produit le contenu principal et variable de votre page Web. Mais ce n’est pas idéal pour diffuser du contenu statique (des images et des fichiers JavaScript, par exemple) ou pour équilibrer la charge sur plusieurs serveurs.
Pour tirer le meilleur parti de Node.js, vous devez mettre en cache le contenu statique, assurer le proxy et l'équilibrage de charge entre plusieurs serveurs d'applications et gérer les conflits de ports entre les clients, Node.js et les assistants, tels que les serveurs exécutant Socket.IO. NGINX peut être utilisé à toutes ces fins, ce qui en fait un excellent outil pour le réglage des performances de Node.js.
Utilisez ces conseils pour améliorer les performances de l’application Node.js :
Note: Une solution rapide pour améliorer les performances des applications Node.js consiste à modifier votre configuration Node.js pour tirer parti des serveurs multicœurs modernes. Consultez la documentation Node.js pour savoir comment faire en sorte que Node.js génère des processus enfants distincts, égaux au nombre de processeurs sur votre serveur Web. Chaque processus trouve alors, de manière quelque peu magique, sa place sur un seul et unique processeur, ce qui vous offre un gain de performances considérable.
Chez NGINX, Inc., nous sommes toujours un peu horrifiés lorsque nous voyons des serveurs d’applications directement exposés au trafic Internet entrant, utilisés au cœur de sites hautes performances. Cela inclut de nombreux sites basés sur WordPress , par exemple, ainsi que des sites Node.js.
Node.js, dans une plus large mesure que la plupart des serveurs d'applications, est conçu pour l'évolutivité, et son côté serveur Web peut gérer assez bien une grande quantité de trafic Internet. Mais le service Web n’est pas la raison d’être de Node.js ; ce n’est pas vraiment ce pour quoi il a été conçu.
Si vous avez un site à fort trafic, la première étape pour augmenter les performances de l’application consiste à placer un serveur proxy inverse devant votre serveur Node.js. Cela protège le serveur Node.js de l'exposition directe au trafic Internet et vous permet une grande flexibilité dans l'utilisation de plusieurs serveurs d'applications, dans l'équilibrage de la charge sur les serveurs et dans la mise en cache du contenu.
Placer NGINX devant une configuration de serveur existante en tant que serveur proxy inverse , suivi d'utilisations supplémentaires, est un cas d'utilisation principal pour NGINX, mis en œuvre par des dizaines de millions de sites Web dans le monde entier.
L'utilisation de NGINX comme serveur proxy inverse Node.js présente des avantages spécifiques, notamment :
Note : Ces tutoriels expliquent comment utiliser NGINX comme serveur proxy inverse dans les environnements Ubuntu 14.04 ou CentOS , et ils constituent un aperçu utile pour quiconque place NGINX devant Node.js.
À mesure que l’utilisation d’un site basé sur Node.js augmente, le serveur commencera à montrer des signes de pression. Il y a deux choses que vous souhaitez faire à ce stade :
C'est en fait facile à faire. Commencez par implémenter NGINX comme serveur proxy inverse, comme décrit dans l’ astuce précédente . Cela facilite la mise en œuvre de la mise en cache, de l'équilibrage de charge (lorsque vous avez plusieurs serveurs Node.js) et bien plus encore.
Le site Web de Modulus, une plateforme de conteneurs d'applications, propose un article utile sur l'optimisation des performances des applications Node.js avec NGINX. Node.js effectuant tout le travail tout seul, le site de l'auteur a pu traiter en moyenne près de 900 requêtes par seconde. Avec NGINX comme serveur proxy inverse, diffusant du contenu statique, le même site a traité plus de 1 600 requêtes par seconde, soit une amélioration des performances de près de 2 fois.
En doublant vos performances, vous gagnez du temps pour prendre des mesures supplémentaires afin de répondre à une croissance future, telles que la révision (et éventuellement l'amélioration) de la conception de votre site, l'optimisation du code de votre application et le déploiement de serveurs d'applications supplémentaires.
Voici le code de configuration qui fonctionne pour un site Web exécuté sur Modulus :
serveur { écouter 80 ;
nom_serveur static-test-47242.onmodulus.net ;
racine /mnt/app ;
index index.html index.htm ;
emplacement /static/ {
try_files $uri $uri/ =404 ;
}
emplacement /api/ {
proxy_pass http://node-test-45750.onmodulus.net ;
}
}
Cet article détaillé de Patrick Nommensen de NGINX, Inc. explique comment il met en cache le contenu statique de son blog personnel, qui fonctionne sur la plateforme de blogs open source Ghost, une application Node.js. Bien que certains détails soient spécifiques à Ghost, vous pouvez réutiliser une grande partie du code pour d’autres applications Node.js.
Par exemple, dans le bloc d'emplacement
NGINX, vous souhaiterez probablement exempter certains contenus de la mise en cache. En général, vous ne souhaitez pas mettre en cache l'interface d'administration d'une plateforme de blogs, par exemple. Voici le code de configuration qui désactive (ou exempte) la mise en cache de l'interface d'administration Ghost :
emplacement ~ ^/(?:ghost|signout) { proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Hôte $http_host;
proxy_pass http://ghost_upstream;
add_header Cache-Control "no-cache, privé, pas de stockage,
doit être revalidé, max-stale=0, post-check=0, pre-check=0";
}
Pour obtenir des informations générales sur la diffusion de contenu statique, consultez le Guide d'administration NGINX Plus . Le guide d'administration comprend des instructions de configuration, plusieurs options pour répondre aux tentatives réussies ou infructueuses de recherche d'un fichier et des approches d'optimisation pour obtenir des performances encore plus rapides.
La mise en cache des fichiers statiques sur le serveur NGINX décharge considérablement le travail du serveur d'applications Node.js, lui permettant d'atteindre des performances bien supérieures.
La véritable clé pour obtenir des performances élevées, c’est-à-dire presque illimitées, pour les applications Node.js est d’exécuter plusieurs serveurs d’applications et d’équilibrer les charges entre chacun d’eux.
L'équilibrage de charge de Node.js peut être particulièrement délicat car Node.js permet un niveau élevé d'interaction entre le code JavaScript exécuté dans le navigateur Web et le code JavaScript exécuté sur le serveur d'applications Node.js, avec des objets JSON comme support d'échange de données. Cela implique qu'une session client donnée s'exécute en continu sur un serveur d'applications spécifique, et la persistance de session est intrinsèquement difficile à obtenir avec plusieurs serveurs d'applications.
L’un des principaux avantages d’Internet et du Web est leur degré élevé d’apatridie, qui inclut la possibilité pour les demandes des clients d’être satisfaites par n’importe quel serveur ayant accès à un fichier demandé. Node.js subvertit l'absence d'état et fonctionne mieux dans un environnement avec état, où le même serveur répond systématiquement aux demandes de clients spécifiques.
Cette exigence peut être mieux satisfaite par NGINX Plus , plutôt que par NGINX Open Source. Les deux versions de NGINX sont assez similaires, mais une différence majeure est leur prise en charge de différents algorithmes d'équilibrage de charge.
NGINX prend en charge les méthodes d’équilibrage de charge sans état :
Une seule de ces méthodes, IP Hash, envoie de manière fiable les requêtes d'un client donné au même serveur, ce qui profite aux applications Node.js. Cependant, le hachage IP peut facilement conduire à ce qu'un serveur reçoive un nombre disproportionné de requêtes, au détriment des autres serveurs, comme décrit dans cet article de blog sur les techniques d'équilibrage de charge. Cette méthode prend en charge l'état au détriment d'une allocation potentiellement sous-optimale des requêtes entre les ressources du serveur.
Contrairement à NGINX, NGINX Plus prend en charge la persistance des sessions . Avec la persistance de session utilisée, le même serveur reçoit de manière fiable toutes les demandes d'un client donné. Les avantages de Node.js, avec sa communication avec état entre le client et le serveur, et de NGINX Plus, avec sa capacité avancée d'équilibrage de charge, sont tous deux maximisés.
Vous pouvez donc utiliser NGINX ou NGINX Plus pour prendre en charge l'équilibrage de charge sur plusieurs serveurs Node.js. Toutefois, seul NGINX Plus vous permettra d'obtenir à la fois des performances d'équilibrage de charge maximales et un état compatible avec Node.js. Les contrôles de santé des applications et les capacités de surveillance intégrés à NGINX Plus sont également utiles ici.
NGINX Plus prend également en charge le drainage de session , qui permet à un serveur d'applications de terminer correctement les sessions en cours après une demande de mise hors service du serveur.
HTTP, dans toutes ses versions, est conçu pour les communications « pull », où le client demande des fichiers au serveur. WebSocket est un outil permettant les communications « push » et « push/pull », où le serveur peut envoyer de manière proactive des fichiers que le client n'a pas demandés.
Le protocole WebSocket facilite la prise en charge d'interactions plus robustes entre le client et le serveur tout en réduisant la quantité de données transférées et en minimisant la latence. En cas de besoin, une connexion en duplex intégral, avec le client et le serveur initiant et recevant les requêtes selon les besoins, est réalisable.
Le protocole WebSocket dispose d'une interface JavaScript robuste et convient donc parfaitement à Node.js en tant que serveur d'applications - et, pour les applications Web avec des volumes de transactions modérés, également en tant que serveur Web. Lorsque les volumes de transactions augmentent, il est judicieux d'insérer NGINX entre les clients et le serveur Web Node.js, en utilisant NGINX ou NGINX Plus pour mettre en cache les fichiers statiques et équilibrer la charge entre plusieurs serveurs d'applications.
Node.js est souvent utilisé en conjonction avec Socket.IO – une API WebSocket qui est devenue très populaire pour une utilisation avec les applications Node.js. Cela peut entraîner un encombrement important du port 80 (pour HTTP) ou du port 443 (pour HTTPS), et la solution consiste à utiliser un proxy vers le serveur Socket.IO. Vous pouvez utiliser NGINX pour le serveur proxy , comme décrit ci-dessus, et également bénéficier de fonctionnalités supplémentaires telles que la mise en cache de fichiers statiques, l'équilibrage de charge, etc.
Voici le code d’un fichier d’application de nœud server.js qui écoute sur le port 5000. Il agit comme un serveur proxy (pas un serveur Web) et achemine les requêtes vers le port approprié :
var io = require('socket.io').listen(5000);
io.sockets.on('connection', function (socket) {
socket.on('set nickname', function (name) {
socket.set('nickname', name, function () {
socket.emit('ready');
});
});
socket.on('msg', function () {
socket.get('nickname', function (err, name) {
console.log('Message de discussion par ', name);
});
});
});
Dans votre fichier index.html , ajoutez le code suivant pour vous connecter à votre application serveur et instancier un WebSocket entre l'application et le navigateur de l'utilisateur :
<script src="/socket.io/socket.io.js"></script><script>// <![CDATA[
var socket = io(); // votre code d'initialisation ici.
// ]]>
</script>
Pour obtenir des instructions complètes, y compris la configuration de NGINX, consultez notre article de blog sur l'utilisation de NGINX et NGINX Plus avec Node.js et Socket.IO . Pour plus de détails sur les problèmes potentiels d’architecture et d’infrastructure pour les applications Web de ce type, consultez notre article de blog sur les applications Web en temps réel et WebSocket.
De plus en plus de sites utilisent SSL/TLS pour sécuriser toutes les interactions des utilisateurs sur le site. C'est à vous de décider si et quand effectuer cette transition, mais si et quand vous le faites, NGINX prend en charge la transition de deux manières :
Parmi les étapes d'implémentation que vous devez suivre figurent la mise à jour de l'URL dans le fichier de configuration Node.js, l'établissement et l'optimisation de connexions sécurisées dans votre configuration NGINX et l'utilisation de SPDY ou HTTP/2 si vous le souhaitez. L'ajout de la prise en charge HTTP/2 signifie que les versions de navigateur qui prennent en charge HTTP/2 communiquent avec votre application à l'aide du nouveau protocole ; les anciennes versions de navigateur continuent d'utiliser HTTP/1.x.
Le code de configuration suivant est destiné à un blog Ghost utilisant SPDY, comme décrit ici . Il comprend des fonctionnalités avancées telles que l'agrafage OCSP. Pour des considérations sur l'utilisation de NGINX pour la terminaison SSL, y compris l'option d'agrafage OCSP, voir ici . Pour un aperçu général des mêmes sujets, voir ici .
Vous n'avez besoin que de modifications mineures pour configurer votre application Node.js et effectuer la mise à niveau de SPDY vers HTTP/2, maintenant ou lorsque le support SPDY disparaîtra début 2016.
serveur { nom_serveur domaine.com;
écoute 443 ssl spdy;
spdy_headers_comp 6;
spdy_keepalive_timeout 300;
keepalive_timeout 300;
clé_certificat_ssl /etc/nginx/ssl/domain.key;
certificat_ssl /etc/nginx/ssl/domain.crt;
cache_session_ssl partagé : SSL : 10 m;
délai_session_ssl 24 h;
taille_tampon_ssl 1 400;
agrafage_ssl activé ;
vérification_agrafage_ssl activée ;
certificat_confiance_ssl /etc/nginx/ssl/trust.crt;
résolveur 8.8.8.8 8.8.4.4 valide=300s;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains';
add_header X-Cache $upstream_cache_status;
emplacement / {
proxy_cache STATIC;
proxy_cache_valid 200 30m;
proxy_cache_valid 404 1m;
proxy_pass http://ghost_upstream;
proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
proxy_hide_header X-powered-by;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Hôte $http_host;
expire 10m;
}
emplacement /content/images {
alias /path/to/ghost/content/images;
access_log off;
expire max;
}
emplacement /assets {
alias /path/to/ghost/themes/uno-master/assets;
access_log off;
expire max;
}
emplacement /public {
alias /path/to/ghost/built/public;
access_log off;
expire max;
}
emplacement /ghost/scripts {
alias /path/to/ghost/core/built/scripts;
access_log off;
expire max;
}
emplacement ~ ^/(?:ghost|signout) {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Hôte $http_host;
proxy_pass http://ghost_upstream;
add_header Cache-Control "no-cache, privé, pas de stockage,
doit être revalidé, max-stale=0, post-check=0, pre-check=0";
proxy_set_header X-Forwarded-Proto https;
}
}
Cet article de blog décrit certaines des améliorations de performances les plus importantes que vous pouvez apporter à vos applications Node.js. Il se concentre sur l'ajout de NGINX à votre mix d'applications aux côtés de Node.js – en utilisant NGINX comme serveur proxy inverse, pour mettre en cache des fichiers statiques, pour équilibrer la charge, pour proxyer les connexions WebSocket et pour mettre fin aux protocoles SSL/TLS et HTTP/2.
La combinaison de NGINX et Node.js est largement reconnue comme un moyen de créer de nouvelles applications compatibles avec les microservices ou d’ajouter de la flexibilité et des capacités aux applications SOA existantes qui utilisent Java ou Microsoft .NET. Cet article vous aide à optimiser vos applications Node.js et, si vous le souhaitez, à donner vie au partenariat entre Node.js et NGINX.
« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."