Node.js semble intéressant, MAIS Je dois rater quelque chose - Node.js n'est pas à l'écoute pour fonctionner uniquement un seul processus et thread?
Alors, comment évolue-t-il pour les CPU multi-core et les serveurs multi-CPU? Après tout, il est bon de rendre aussi rapide que possible le serveur mono-thread, mais pour des charges élevées, je voudrais utiliser plusieurs processeurs. Et il en va de même pour rendre les applications plus rapides - il semble aujourd'hui que l'on utilise plusieurs processeurs et parallélise les tâches.
Comment Node.js s'intègre-t-il dans cette image? Son idée est-elle de distribuer en quelque sorte plusieurs instances ou quoi?
Node.js s'adapte parfaitement aux machines multicœurs.
Oui, Node.js est un thread par processus. C'est une décision de conception très délibérée qui élimine la nécessité de traiter avec la sémantique de verrouillage. Si vous n'êtes pas d'accord avec cela, vous ne réalisez probablement pas encore à quel point il est incroyablement difficile de déboguer du code multi-thread. Pour une explication plus détaillée du modèle de processus Node.js et de la raison pour laquelle il fonctionne de cette façon (et pourquoi il ne supportera JAMAIS plusieurs threads), lisez mon autre message .
Deux façons:
Depuis la v6.0.X, Node.js a inclus le module de cluster directement, ce qui facilite la configuration de plusieurs opérateurs de nœuds pouvant écouter sur un seul port. Notez que ce n'est pas la même chose que l'ancien module "cluster" de learnboost disponible via npm .
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
http.Server(function(req, res) { ... }).listen(8000);
}
Les travailleurs se feront concurrence pour accepter de nouvelles connexions et le processus le moins chargé gagnera probablement. Cela fonctionne plutôt bien et peut très bien augmenter le débit sur une boîte multicœur.
Si vous avez suffisamment de charge pour vous préoccuper de plusieurs cœurs, vous voudrez également faire quelques tâches supplémentaires:
Exécutez votre service Node.js derrière un proxy Web tel que Nginx ou Apache - quelque chose qui peut limiter la connexion (sauf si vous souhaitez que les conditions de surcharge réduisent complètement la boîte), réécrire les URL, servir le contenu statique et proxy d'autres sous-services.
Recyclez périodiquement vos processus de travail. Pour un processus de longue durée, même une petite fuite de mémoire finira par s’additionner.
Configuration du journal de collecte/surveillance
PS: Il y a une discussion entre Aaron et Christopher dans les commentaires d'un autre post (au moment d'écrire ces lignes, c'est le post le plus haut). Quelques commentaires à ce sujet:
Ports partagés: nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)
contre
Ports individuels: nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}
Il existe certes des avantages pour la configuration des ports individuels (possibilité d’avoir moins de couplage entre les processus, des décisions plus complexes en matière d’équilibrage de la charge, etc.), mais il est nettement plus fastidieux de le configurer et le module de cluster intégré est faible. -complexité alternative qui fonctionne pour la plupart des gens.
Une méthode consiste à exécuter plusieurs instances de node.js sur le serveur, puis à leur placer un équilibreur de charge (de préférence non bloquant, tel que nginx).
Ryan Dahl répond à cette question dans la conférence technique qu'il a donnée à Google l'été dernier. Pour paraphraser, "exécutez simplement plusieurs processus de noeud et utilisez quelque chose de sensé pour leur permettre de communiquer. Par exemple, sendmsg () - style IPC ou un RPC traditionnel".
Si vous voulez vous salir les mains immédiatement, consultez le spark2 Pour toujours module. Cela facilite trivialement la création de processus à plusieurs nœuds. Il gère la configuration du partage de port, afin qu'ils puissent chacun accepter les connexions au même port, ainsi que la création automatique si vous voulez vous assurer qu'un processus est redémarré si/quand il meurt.
UPDATE - 10/11/11 : Le consensus dans la communauté des nœuds semble être que Cluster est maintenant le module préféré pour la gestion plusieurs instances de nœud par machine. Forever vaut également le coup d'oeil.
Vous pouvez utiliser le module cluster . Vérifiez this .
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection
// In this case its a HTTP server
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}
Multi-nœud exploite tous les cœurs que vous pourriez avoir.
Regardez http://github.com/kriszyp/multi-node .
Pour des besoins plus simples, vous pouvez démarrer plusieurs copies de nœud sur différents numéros de port et placer un équilibreur de charge devant eux.
Comme mentionné ci-dessus, Cluster redimensionnera et équilibrera la charge de votre application sur tous les cœurs.
ajouter quelque chose comme
cluster.on('exit', function () {
cluster.fork();
});
Va redémarrer tous les travailleurs défaillants.
De nos jours, beaucoup de gens préfèrent également PM2 , qui gère la mise en cluster pour vous et fournit également quelques fonctionnalités de surveillance intéressantes .
Ajoutez ensuite Nginx ou HAProxy devant plusieurs machines fonctionnant en cluster. Vous disposez ainsi de plusieurs niveaux de basculement et d'une capacité de charge bien supérieure.
Node Js prend en charge la mise en cluster pour tirer pleinement parti de votre processeur. Si vous ne l'exécutez pas avec un cluster, vous gaspillez probablement vos capacités matérielles.
La mise en cluster dans Node.js vous permet de créer des processus distincts pouvant partager le même port de serveur. Par exemple, si nous exécutons un serveur HTTP sur le port 3000, il s’agit d’un serveur exécuté sur un seul thread sur un seul cœur de processeur.
Le code ci-dessous vous permet de regrouper votre application. Ce code est le code officiel représenté par Node.js.
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
Object.keys(cluster.workers).forEach(function(id) {
console.log("I am running with ID : " + cluster.workers[id].process.pid);
});
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
//Do further processing.
}
vérifier cet article pour le plein tutoriel
La prochaine version de node vous permettra de bifurquer un processus et de lui transmettre des messages. Ryan a déclaré qu'il souhaitait trouver un moyen de partager également les gestionnaires de fichiers. Il ne s'agira donc pas d'une implémentation Web Worker simple.
Pour le moment, il n’ya pas de solution facile à cela, mais il est encore très tôt et node est l’un des projets open source les plus rapides et les plus mobiles que je n’ai jamais vus.
Spark2 est basé sur Spark qui n'est plus maintenu. Cluster est son successeur et présente quelques fonctionnalités intéressantes, telles que la création d'un processus de travail par cœur de processeur et le rétablissement des travailleurs morts.
Le nouveau venu ici est LearnBoost "Up" .
Il fournit des "recharges zéro temps d'arrêt" et crée en outre plusieurs travailleurs (par défaut, le nombre de processeurs, mais il est configurable) pour fournir le meilleur des mondes.
C'est nouveau, mais semble être assez stable, et je l'utilise avec bonheur dans l'un de mes projets en cours.
J'utilise Node worker pour exécuter des processus de manière simple à partir de mon processus principal. Semble fonctionner très bien pendant que nous attendons la voie officielle.
Vous pouvez exécuter votre application node.js sur plusieurs cœurs en utilisant le module cluster en combinaison avec le module os , qui peut être utilisé pour détecter le nombre de CPU dont vous disposez.
Par exemple, imaginons que vous avez un module server
qui exécute un serveur http simple sur le backend et que vous voulez l'exécuter pour plusieurs processeurs:
// Dependencies.
const server = require('./lib/server'); // This is our custom server module.
const cluster = require('cluster');
const os = require('os');
// If we're on the master thread start the forks.
if (cluster.isMaster) {
// Fork the process.
for (let i = 0; i < os.cpus().length; i++) {
cluster.fork();
}
} else {
// If we're not on the master thread start the server.
server.init();
}
Il est possible de faire évoluer NodeJS vers plusieurs boîtes en utilisant un équilibreur de charge pur TCP (HAProxy) devant plusieurs boîtes exécutant un processus NodeJS chacune.
Si vous avez des connaissances communes à partager entre toutes les instances, vous pouvez utiliser un magasin Redis central ou similaire, accessible depuis toutes les instances de processus (par exemple, depuis toutes les boîtes).
Il est également possible de concevoir le service Web sous la forme de plusieurs serveurs autonomes écoutant des sockets Unix, de sorte que vous puissiez transférer des fonctions telles que le traitement des données dans des processus distincts.
Ceci est similaire à la plupart des architectures de serveur Web de scrpting/base de données dans lesquelles un processus cgi gère la logique métier, puis transfère et extrait les données via une socket Unix vers une base de données.
la différence étant que le traitement des données est écrit en tant que nœud de serveur Web à l'écoute sur un port.
c'est plus complexe, mais au final, c'est vers le développement multicœur. une architecture multiprocessus utilisant plusieurs composants pour chaque requête Web.