Maison >interface Web >js tutoriel >Comment créer un cluster Node.js pour accélérer vos applications

Comment créer un cluster Node.js pour accélérer vos applications

Joseph Gordon-Levitt
Joseph Gordon-Levittoriginal
2025-02-19 12:01:10198parcourir

How to Create a Node.js Cluster for Speeding Up Your Apps

Points de base

  • Node.js est devenu un environnement de fonctionnement côté serveur populaire pour gérer les sites Web à haut trafic avec son architecture axée sur les événements et son API d'E / S non bloquante, permettant un traitement de demande asynchrone.
  • L'évolutivité de Node.js est une caractéristique clé qu'elle adopte par les grandes entreprises. Bien que l'exécution dans un seul thread par défaut et possède des limites de mémoire, Node.js peut étendre une application via un module de cluster pour diviser un seul processus en plusieurs processus ou processus de travail.
  • Le module de cluster Node.js fonctionne en exécutant le même processus Node.js plusieurs fois. Il permet d'identifier le processus principal et de créer des processus de travail qui peuvent partager des poignées de serveur et communiquer avec le processus de nœud parent.
  • L'application
  • Node.js peut être parallélisée à l'aide de modules de cluster, permettant à plusieurs processus d'exécuter simultanément. Cela améliore l'efficacité du système, améliore les performances des applications et améliore la fiabilité et la disponibilité.
  • Bien que le module de cluster Node.js soit principalement recommandé pour les serveurs Web, il peut également être utilisé pour d'autres applications lors de l'allocation de tâches entre soigneusement les processus de travail et une communication efficace entre les processus de travail et les principaux processus.

Node.js devient de plus en plus populaire en tant qu'environnement de fonctionnement côté serveur, en particulier dans les sites Web à haut trafic, et les statistiques le prouvent également. De plus, la disponibilité de nombreux cadres en fait un bon environnement pour le prototypage rapide. Node.js a une architecture motivée par des événements qui utilise une API d'E / S non bloquante pour permettre le traitement asynchrone des demandes. Une caractéristique importante et souvent négligée de Node.js est son évolutivité. En fait, c'est la principale raison pour laquelle certaines grandes entreprises intègrent Node.js (comme Microsoft, Yahoo, Uber et Walmart) dans leurs plates-formes et même migrent complètement leurs opérations côté serveur vers Node.js (comme PayPal, eBay et Groupon). Chaque processus Node.js s'exécute dans un seul thread, par défaut, la limite de mémoire pour les systèmes 32 bits est de 512 Mo et la limite de mémoire pour les systèmes 64 bits est de 1 Go. Bien que la limite de mémoire puisse être augmentée à environ 1 Go sur des systèmes 32 bits et à environ 1,7 Go sur des systèmes 64 bits, la mémoire et la puissance de traitement peuvent toujours être un goulot d'étranglement pour divers processus. La solution élégante que Node.js fournit pour des applications étendues est de diviser un seul processus en plusieurs processus ou processus de travail dans la terminologie Node.js. Cela peut être réalisé via le module de cluster. Le module de cluster vous permet de créer des processus enfants (processus de travail) qui partagent tous les ports du serveur avec le processus de nœud principal (processus principal). Dans cet article, vous apprendrez à créer un cluster Node.js pour accélérer votre application.

Module de cluster Node.js: que fait-il et comment cela fonctionne

Le cluster

est un pool de processus de travailleurs similaires exécutés sous le processus de nœud parent. Les processus de travail sont générés à l'aide de la méthode Fork () du module Child_Processs. Cela signifie que le processus de travailleur peut partager la poignée du serveur et communiquer avec le processus de nœud parent à l'aide de l'IPC (communication interprocess). Le processus principal est responsable du démarrage et du contrôle du processus de travail. Vous pouvez créer autant de processus de travail que vous le souhaitez dans le processus principal. N'oubliez pas non plus que par défaut, les connexions entrantes sont allouées par le scrutin entre les processus de travail (sauf Windows). En fait, il existe un autre moyen d'allouer des connexions entrantes, dont je ne discuterai pas ici, en remettant l'affectation au système d'exploitation (le paramètre par défaut sous Windows). La documentation Node.js recommande d'utiliser le style de sondage par défaut comme stratégie de planification. Bien que l'utilisation d'un module de cluster semble compliqué en théorie, son implémentation est très simple. Pour commencer à l'utiliser, vous devez l'inclure dans votre application Node.js:

<code class="language-javascript">var cluster = require('cluster');</code>

Le module de cluster exécute le même processus Node.js plusieurs fois. Ainsi, la première chose que vous devez faire est de déterminer quelle partie du code est utilisée pour le processus principal et quelle partie du code est utilisée pour le processus de travail. Le module de cluster vous permet d'identifier le processus principal comme suit:

<code class="language-javascript">if(cluster.isMaster) { ... }</code>

Le processus principal est le processus que vous avez commencé, qui à son tour initialise le processus de travail. Pour démarrer le processus des travailleurs dans le processus principal, nous utiliserons la méthode Fork ():

<code class="language-javascript">cluster.fork();</code>

Cette méthode renvoie un objet de travailleur contenant certaines méthodes et propriétés concernant le travailleur dérivé. Nous verrons quelques exemples dans la section suivante. Le module de cluster contient plusieurs événements. Deux événements communs liés au démarrage et aux moments de résiliation du processus des travailleurs sont les événements en ligne et de sortie. Lorsque le processus des travailleurs dérive et envoie un message en ligne, un événement en ligne est émis. Lorsque le processus de travailleur décède, un événement de sortie est émis. Plus tard, nous apprendrons à utiliser ces deux événements pour contrôler le cycle de vie d'un processus de travailleur. Maintenant, assemblons tout ce que nous avons vu jusqu'à présent et montrons un exemple complet.

Exemple

Cette section contient deux exemples. Le premier exemple est une application simple montrant comment utiliser les modules de cluster dans une application Node.js. Le deuxième exemple est un serveur express qui tire parti du module de cluster Node.js, qui fait partie du code de production que j'utilise habituellement dans des projets à grande échelle. Les deux exemples sont disponibles en téléchargement depuis GitHub.

Comment utiliser le module de cluster dans l'application Node.js

Dans ce premier exemple, nous avons configuré un serveur simple qui répond à toutes les demandes entrantes à l'aide d'un message contenant l'ID de processus de travail qui gère la demande. Le processus principal tire quatre processus de travailleurs. Dans chaque processus de travailleur, nous commençons à écouter le port 8000 pour recevoir des demandes entrantes. Le code qui implémente ce que je viens de décrire est comme suit:

<code class="language-javascript">var cluster = require('cluster');
var http = require('http');
var numCPUs = 4;

if (cluster.isMaster) {
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end('process ' + process.pid + ' says hello!');
    }).listen(8000);
}</code>

Vous pouvez accéder à l'URL en démarrant le serveur (exécutant le nœud de commande simple.js) et en accédant à l'URL https://www.php.cn/link/7d2d180c45c41870f36e747816456190 .

Comment développer un serveur express très évolutif

Express est l'un des cadres d'applications Web les plus populaires pour Node.js (sinon le plus populaire). Nous l'avons couvert plusieurs fois sur ce site. Si vous êtes intéressé à en savoir plus, je vous recommande de lire les articles "Création d'une API RESTFul avec Express 4" et "Construire une application Web de salle de discussion axée sur Node.js: Express et Azure". Le deuxième exemple montre comment développer un serveur express hautement évolutif. Il montre également comment migrer un seul serveur de processus pour profiter d'un module de cluster avec une petite quantité de code.

<code class="language-javascript">var cluster = require('cluster');</code>

Le premier ajout à cet exemple consiste à utiliser le module Node.js OS pour obtenir le nombre de cœurs CPU. Le module OS contient une fonction CPU () qui renvoie un tableau de cœurs CPU. En utilisant cette approche, nous pouvons déterminer dynamiquement le nombre de processus de travail à dériver en fonction des spécifications du serveur pour maximiser l'utilisation des ressources. Le deuxième ajout plus important est de faire face à la mort du processus de travail. Lorsque le processus de travailleur décède, le module de cluster publiera un événement de sortie. Il peut être traité en écoutant l'événement et en exécutant une fonction de rappel lorsqu'il est émis. Vous pouvez le faire en écrivant des instructions comme cluster.on ('exit', rappel); Dans la fonction de rappel, nous dérivons un nouveau processus de travail pour maintenir le nombre attendu de processus de travail. Cela nous permet de maintenir l'application en cours d'exécution même avec des exceptions non perdues. Dans cet exemple, j'ai également mis en place un auditeur pour l'événement en ligne, qui est émis chaque fois que le processus de travail est dérivé et prêt à recevoir des demandes entrantes. Cela peut être utilisé pour l'exploitation forestière ou d'autres opérations.

Comparaison des performances

Il existe plusieurs outils pour comparer l'API, mais ici j'utilise l'outil de référence Apache pour analyser comment l'utilisation des modules de cluster affecte les performances de l'application. Pour configurer les tests, j'ai développé un serveur express qui a un itinéraire et une fonction de rappel pour cette route. Dans la fonction de rappel, effectuez une opération virtuelle et renvoyez un court message. Il existe deux versions du serveur: l'une n'a pas de processus de travail, où toutes les opérations se produisent dans le processus principal, et l'autre a 8 processus de travail (car ma machine a 8 cœurs). Le tableau suivant montre comment le module de cluster de fusion augmente le nombre de demandes traitées par seconde.

并发连接 1 2 4 8 16
单进程 654 711 783 776 754
8个工作进程 594 1198 2110 3010 3024

(nombre de demandes traitées par seconde)

Fonctionnement avancé

Bien que l'utilisation de modules de cluster soit relativement simple, vous pouvez utiliser des processus de travail pour effectuer d'autres opérations. Par exemple, vous pouvez utiliser des modules de cluster pour réaliser (presque!) Des temps d'arrêt zéro pour votre application. Nous apprendrons à faire certaines de ces opérations depuis un certain temps.

Communication entre le processus principal et le processus de travail

Parfois, vous devrez peut-être envoyer un message du processus principal au processus du travailleur pour attribuer des tâches ou effectuer d'autres actions. En retour, le processus des travailleurs peut avoir besoin de notifier le processus principal que la tâche a été terminée. Pour écouter les messages, vous devez définir l'écouteur d'événements pour l'événement de message dans le processus principal et le processus du travailleur:

<code class="language-javascript">var cluster = require('cluster');</code>

L'objet Worker est une référence renvoyée par la méthode Fork (). Pour écouter les messages du processus principal du processus de travail:

<code class="language-javascript">if(cluster.isMaster) { ... }</code>
Le message

peut être une chaîne ou un objet JSON. Pour envoyer des messages à un processus de travailleur spécifique, vous pouvez écrire du code comme ceci:

<code class="language-javascript">cluster.fork();</code>

De même, pour envoyer un message au processus principal, vous pouvez écrire:

<code class="language-javascript">var cluster = require('cluster');
var http = require('http');
var numCPUs = 4;

if (cluster.isMaster) {
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end('process ' + process.pid + ' says hello!');
    }).listen(8000);
}</code>

Dans Node.js, les messages sont génériques et n'ont pas de type spécifique. Par conséquent, il est préférable d'envoyer un message en tant qu'objet JSON qui contient des informations sur le type de message, l'expéditeur et le contenu lui-même. Par exemple:

<code class="language-javascript">var cluster = require('cluster');

if(cluster.isMaster) {
    var numWorkers = require('os').cpus().length;

    console.log('Master cluster setting up ' + numWorkers + ' workers...');

    for(var i = 0; i < numWorkers; i++) {
        cluster.fork();
    }

    cluster.on('online', function(worker) {
        console.log('Worker ' + worker.process.pid + ' is online');
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
        console.log('Starting a new worker');
        cluster.fork();
    });
} else {
    var app = require('express')();
    app.all('/*', function(req, res) {res.send('process ' + process.pid + ' says hello!').end();})

    var server = app.listen(8000, function() {
        console.log('Process ' + process.pid + ' is listening to all incoming requests');
    });
}</code>

Une chose à noter ici est que le rappel des événements de message est traité de manière asynchrone. Il n'y a pas d'ordre d'exécution défini. Vous pouvez trouver un exemple complet de communication entre le processus principal et le processus de travail sur GitHub.

zéro temps d'arrêt

Un résultat important qui peut être obtenu en utilisant les processus de travail est le (presque) serveur de temps d'arrêt zéro. Dans le processus principal, vous pouvez résilier et redémarrer le processus des travailleurs un à la fois après avoir apporté des modifications à l'application. Cela vous permet d'exécuter l'ancienne version tout en chargeant la nouvelle version. Afin de pouvoir redémarrer votre application au moment de l'exécution, vous devez vous souvenir de deux choses. Premièrement, le processus principal est de s'exécuter tout le temps, et seul le processus de travail est terminé et redémarré. Par conséquent, il est important de maintenir le processus principal court et de gérer uniquement le processus de travail. Deuxièmement, vous devez en quelque sorte informer le processus principal que le processus des travailleurs doit être redémarré. Il existe plusieurs façons de le faire, y compris les modifications des fichiers d'entrée ou de surveillance des utilisateurs. Ce dernier est plus efficace, mais vous devez identifier les fichiers à surveiller dans le processus principal. La façon dont je recommande de redémarrer le processus des travailleurs est d'abord d'essayer de les fermer en toute sécurité; Vous pouvez exécuter le premier en envoyant un message d'arrêt au processus du travailleur, comme indiqué ci-dessous:

<code class="language-javascript">worker.on('message', function(message) {
    console.log(message);
});</code>

et commencez une fermeture en toute sécurité dans le gestionnaire d'événements de message Worker:

<code class="language-javascript">process.on('message', function(message) {
    console.log(message);
});</code>

Pour ce faire pour tous les processus de travail, vous pouvez utiliser la propriété des travailleurs du module de cluster, qui détient une référence à tous les processus de travailleurs en cours d'exécution. Nous pouvons également envelopper toutes les tâches dans une fonction dans le processus principal qui peut être appelé lorsque nous voulons redémarrer tous les processus de travail.

<code class="language-javascript">var cluster = require('cluster');</code>

Nous pouvons obtenir les ID de tous les processus de travail en cours d'exécution de l'objet Workers dans le module de cluster. Cet objet détient une référence à tous les processus de travailleurs en cours d'exécution et met à jour dynamiquement lorsque les processus de travail sont terminés et redémarrés. Tout d'abord, nous stockons les identifiants de tous les processus de travailleurs en cours d'exécution dans le tableau des travailleurs. De cette façon, nous évitons de redémarrer le processus de travailleur nouvellement dérivé. Nous demandons ensuite à chaque processus de travailleur soit fermé en toute sécurité. Si le processus de travailleur est toujours en cours d'exécution après 5 secondes et existe toujours dans l'objet des travailleurs, nous appelons la fonction de mise à mort sur le processus des travailleurs pour le forcer à fermer. Vous pouvez trouver un exemple pratique sur GitHub.

Conclusion

Les applications

Node.js peuvent être parallélisées à l'aide du module de cluster pour permettre une utilisation plus efficace du système. Plusieurs processus peuvent être exécutés simultanément avec plusieurs lignes de code, ce qui rend la migration relativement facile car Node.js gère les pièces difficiles. Comme je l'ai démontré dans la comparaison des performances, il est possible d'obtenir une amélioration significative des performances des applications en tirant parti des ressources système plus efficacement. En plus des performances, vous pouvez améliorer la fiabilité et la disponibilité des applications en redémarrant les processus des travailleurs pendant l'exécution de l'application. Autrement dit, vous devez être prudent lorsque vous envisagez d'utiliser des modules de cluster dans votre application. La principale utilisation recommandée des modules de cluster est pour les serveurs Web. Dans d'autres cas, vous devez examiner de plus près comment allouer des tâches entre les processus des travailleurs et comment communiquer efficacement les progrès entre les processus de travailleurs et les principaux processus. Même pour les serveurs Web, assurez-vous qu'un seul processus Node.js est un goulot d'étranglement (mémoire ou CPU) avant d'apporter des modifications à votre application, car vos modifications peuvent introduire des erreurs. Enfin et surtout, le site Web de Node.js fournit une bonne documentation pour les modules de cluster. Assurez-vous donc de le vérifier!

FAQ sur Node.js Clusters

Quels sont les principaux avantages de l'utilisation de clusters Node.js?

Le principal avantage de l'utilisation du cluster Node.js est d'améliorer les performances de l'application. Node.js s'exécute sur un fil, ce qui signifie qu'il ne peut utiliser qu'un seul noyau CPU à la fois. Cependant, les serveurs modernes ont généralement plusieurs cœurs. En utilisant le cluster Node.js, vous pouvez créer un processus principal qui dérive plusieurs processus de travail, chacun fonctionnant sur un autre noyau de processeur. Cela permet à votre application de traiter plus de demandes en même temps, ce qui améliore considérablement sa vitesse et ses performances.

Comment fonctionne le cluster Node.js?

Le cluster Node.js fonctionne en créant un processus principal qui dérive plusieurs processus de travailleurs. Le processus principal écoute les demandes entrantes et les distribue au processus des travailleurs d'une manière de sonder. Chaque processus de travailleur s'exécute sur un noyau CPU séparé et gère les demandes indépendamment. Cela permet à votre application de profiter de tous les cœurs CPU disponibles et de traiter plus de demandes en même temps.

Comment créer un cluster Node.js?

La création d'un cluster Node.js implique l'utilisation du module "Cluster" fourni par Node.js. Tout d'abord, vous devez importer les modules "cluster" et "OS". Vous pouvez ensuite utiliser la méthode "Cluster.Fork ()" pour créer le processus de travail. "OS.CPUS (). Longueur" vous donne le nombre de cœurs CPU disponibles, que vous pouvez utiliser pour déterminer le nombre de processus de travail à créer. Voici un exemple simple:

<code class="language-javascript">var cluster = require('cluster');</code>

Comment gérer les accidents du processus de travail dans le cluster Node.js?

Vous pouvez gérer les accidents du processus de travail dans le cluster Node.js en écoutant les événements "quitter" sur le processus principal. Lorsque le processus de travail se bloque, il envoie un événement "de sortie" au processus principal. Vous pouvez ensuite utiliser la méthode "Cluster.Fork ()" pour créer un nouveau processus de travail pour remplacer le processus de travailleur écrasé. Voici un exemple:

<code class="language-javascript">if(cluster.isMaster) { ... }</code>

Puis-je utiliser le cluster Node.js avec express.js?

Oui, vous pouvez utiliser le cluster Node.js avec express.js. En fait, l'utilisation de clustering Node.js peut améliorer considérablement les performances des applications express.js. Il vous suffit de mettre le code d'application Express.js dans le bloc de code de processus de travail dans le script de cluster.

Quelles sont les limites des clusters Node.js?

Bien que le cluster Node.js puisse améliorer considérablement les performances de l'application, il a également certaines limites. Par exemple, un processus de travailleur ne partage pas l'état ou la mémoire. Cela signifie que vous ne pouvez pas stocker des données de session en mémoire car il est inaccessible dans tous les processus de travail. Au lieu de cela, vous devez utiliser un stockage de session partagé, comme une base de données ou un serveur Redis.

Comment charger les demandes d'équilibrage dans le cluster Node.js?

Par défaut, le processus principal du cluster Node.js distribue des demandes entrantes au processus de travail de manière de sonder. Cela fournit une forme de base d'équilibrage de charge. Cependant, si vous avez besoin d'équilibrage de charge plus avancé, vous devrez peut-être utiliser un serveur proxy inversé, tel que Nginx.

Puis-je utiliser le cluster Node.js en production?

Oui, vous pouvez utiliser le cluster Node.js dans un environnement de production. En fait, il est fortement recommandé d'utiliser des clusters Node.js dans des environnements de production pour tirer le meilleur parti du noyau CPU du serveur et améliorer les performances de votre application.

Comment déboguer le cluster Node.js?

Les clusters Node.js de débogage peuvent être un peu délicats car vous avez plusieurs processus de travailleurs en même temps. Cependant, vous pouvez joindre le débogueur à chaque processus en utilisant l'indicateur "Inspecter" avec un port unique pour chaque processus de travailleur. Voici un exemple:

<code class="language-javascript">cluster.fork();</code>

Puis-je utiliser le cluster Node.js avec d'autres modules Node.js?

Oui, vous pouvez utiliser le cluster Node.js avec d'autres modules Node.js. Cependant, vous devez noter que le processus du travailleur ne partage pas l'état ou la mémoire. Cela signifie que si le module dépend de l'état partagé, il peut ne pas fonctionner correctement dans l'environnement de cluster.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn