[ Ce message est à jour en date du 2012-09-02 (plus récent que ci-dessus). ]
Node.js évolue absolument sur les machines multicœurs.
Oui, Node.js est un thread par processus. Il s'agit d'une décision de conception très délibérée et élimine la nécessité de gérer 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 multithread. Pour une explication plus approfondie du modèle de processus Node.js et pourquoi il fonctionne de cette façon (et pourquoi il ne prendra JAMAIS en charge plusieurs threads), lisez mon autre article .
Alors, comment puis-je profiter de ma boîte à 16 cœurs?
Deux façons:
- Pour les tâches de calcul lourdes comme le codage d'image, Node.js peut lancer des processus enfants ou envoyer des messages à des processus de travail supplémentaires. Dans cette conception, vous auriez un thread gérant le flux d'événements et N processus effectuant des tâches de calcul lourdes et mâchant les 15 autres CPU.
- Pour faire évoluer le débit sur un service Web, vous devez exécuter plusieurs serveurs Node.js sur une seule boîte, un par cœur et répartir le trafic de demande entre eux. Cela offre une excellente affinité CPU et augmentera le débit de manière presque linéaire avec le nombre de cœurs.
Mise à l'échelle du débit sur un service Web
Depuis v6.0.X Node.js a inclus le module de cluster directement, ce qui facilite la configuration de plusieurs nœuds de travail pouvant écouter sur un seul port. Notez que ce n'est PAS le même que l'ancien module "cluster" 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 seront en concurrence pour accepter de nouvelles connexions, et le processus le moins chargé est le plus susceptible de gagner. Cela fonctionne assez bien et peut augmenter le débit assez bien sur une boîte multicœur.
Si vous avez suffisamment de charge pour vous soucier de plusieurs cœurs, vous voudrez également faire quelques choses:
Exécutez votre service Node.js derrière un proxy Web comme Nginx ou Apache - quelque chose qui peut limiter la connexion (sauf si vous voulez que les conditions de surcharge réduisent complètement la boîte), réécrire les URL, servir du contenu statique et proxy d'autres sous-services.
Recyclez régulièrement vos processus de travail. Pour un processus de longue durée, même une petite fuite de mémoire finira par s'additionner.
Configuration de la collecte / surveillance des journaux
PS: Il y a une discussion entre Aaron et Christopher dans les commentaires d'un autre article (à ce jour, c'est le premier article). Quelques commentaires à ce sujet:
- Un modèle de socket partagé est très pratique pour permettre à plusieurs processus d'écouter sur un seul port et de concurrencer pour accepter de nouvelles connexions. Sur le plan conceptuel, vous pourriez penser à Apache préfork faisant cela avec la mise en garde importante que chaque processus n'acceptera qu'une seule connexion, puis mourra. La perte d'efficacité pour Apache est dans la surcharge de forking de nouveaux processus et n'a rien à voir avec les opérations de socket.
- Pour Node.js, avoir N travailleurs en concurrence sur un seul socket est une solution extrêmement raisonnable. L'alternative consiste à configurer un frontal sur boîte comme Nginx et à disposer de ce trafic proxy vers les différents travailleurs, en alternant entre les travailleurs pour attribuer de nouvelles connexions. Les deux solutions ont des caractéristiques de performances très similaires. Et comme, comme je l'ai mentionné ci-dessus, vous voudrez probablement que Nginx (ou une alternative) gère votre service de nœud de toute façon, le choix ici est vraiment entre:
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 y a sans doute certains avantages à la configuration des ports individuels (potentiel d'avoir moins de couplage entre les processus, d'avoir des décisions d'équilibrage de charge plus sophistiquées, etc.), mais c'est certainement plus de travail à configurer et le module de cluster intégré est un faible -alternative de complexité qui fonctionne pour la plupart des gens.