Maison >interface Web >js tutoriel >Comment créer un cluster Node.js pour accélérer vos applications
Points de base
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. 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: 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: 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 (): 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. 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: 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 . 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. 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. 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. (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. 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: 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: 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: De même, pour envoyer un message au processus principal, vous pouvez écrire: 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: 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. 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: et commencez une fermeture en toute sécurité dans le gestionnaire d'événements de message Worker: 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. 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 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 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. 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. 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: 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: 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. 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. 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. 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. 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: 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. Module de cluster Node.js: que fait-il et comment cela fonctionne
Le cluster <code class="language-javascript">var cluster = require('cluster');</code>
<code class="language-javascript">if(cluster.isMaster) { ... }</code>
<code class="language-javascript">cluster.fork();</code>
Comment utiliser le module de cluster dans l'application Node.js
<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>
Comment développer un serveur express très évolutif
<code class="language-javascript">var cluster = require('cluster');</code>
Comparaison des performances
并发连接
1
2
4
8
16
单进程
654
711
783
776
754
8个工作进程
594
1198
2110
3010
3024
Communication entre le processus principal et le processus de travail
<code class="language-javascript">var cluster = require('cluster');</code>
<code class="language-javascript">if(cluster.isMaster) { ... }</code>
Le message <code class="language-javascript">cluster.fork();</code>
<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>
<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>
zéro temps d'arrêt
<code class="language-javascript">worker.on('message', function(message) {
console.log(message);
});</code>
<code class="language-javascript">process.on('message', function(message) {
console.log(message);
});</code>
<code class="language-javascript">var cluster = require('cluster');</code>
Quels sont les principaux avantages de l'utilisation de clusters Node.js?
Comment fonctionne le cluster Node.js?
Comment créer un cluster Node.js?
<code class="language-javascript">var cluster = require('cluster');</code>
Comment gérer les accidents du processus de travail dans le cluster Node.js?
<code class="language-javascript">if(cluster.isMaster) { ... }</code>
Puis-je utiliser le cluster Node.js avec express.js?
Quelles sont les limites des clusters Node.js?
Comment charger les demandes d'équilibrage dans le cluster Node.js?
Puis-je utiliser le cluster Node.js en production?
Comment déboguer le cluster Node.js?
<code class="language-javascript">cluster.fork();</code>
Puis-je utiliser le cluster Node.js avec d'autres modules Node.js?
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!