Question Node.js sur les machines multi-core


Node.js semble intéressant, MAIS Je dois manquer quelque chose - Node.js n'est-il pas réglé pour fonctionner sur un seul processus et thread?

Alors, comment cela évolue-t-il pour les processeurs multi-cœurs et les serveurs multi-processeurs? Après tout, c'est génial de rendre le plus rapide possible un serveur monothread, 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 qu'aujourd'hui la méthode consiste à utiliser plusieurs processeurs et à paralléliser les tâches.

Comment Node.js s'intègre-t-il dans cette image? Est-ce son idée de distribuer en quelque sorte plusieurs instances ou quoi?


517
2018-03-05 15:13


origine


Réponses:


[Ce poste est à jour en date du 2012-09-02 (plus récent que ci-dessus).]

Node.js est vraiment évolutif sur les machines multi-core.

Oui, Node.js est un thread par processus. Ceci est une décision de conception très délibérée et élimine le besoin de traiter la sémantique de verrouillage. Si vous n'êtes pas d'accord avec cela, vous ne réalisez probablement pas à quel point il est extrêmement difficile de déboguer du code multi-thread. Pour une explication plus détaillée du modèle de processus Node.js et pourquoi cela fonctionne de cette façon (et pourquoi il ne prendra jamais en charge plusieurs threads), lisez mon autre poste.

Alors, comment puis-je profiter de ma boîte 16 core?

Deux façons:

  • Pour les grosses tâches de calcul lourdes comme le codage d'image, Node.js peut déclencher des processus enfants ou envoyer des messages à des processus de travail supplémentaires. Dans cette conception, vous auriez un thread gérant le flux des événements et N processus faisant de lourdes tâches de calcul et mâchant les 15 autres processeurs.
  • Pour mettre à l'échelle le débit sur un service Web, vous devez exécuter plusieurs serveurs Node.js sur une seule boîte, une par cœur et partager le trafic de demande entre eux. Cela fournit une excellente affinité pour le processeur et permet d'adapter le débit de façon presque linéaire avec le nombre de cœurs.

Scaling throughput sur un webservice

Depuis v6.0.X Node.js a inclus le module cluster tout droit sorti de la boîte, ce qui facilite la configuration de plusieurs nœuds pouvant écouter sur un seul port. Notez que ce n'est pas la même chose 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 plutôt bien et peut très bien augmenter le débit sur une boîte multi-cœurs.

Si vous avez assez de charge pour vous soucier de plusieurs cœurs, alors vous allez vouloir faire encore quelques choses:

  1. Exécutez votre service Node.js derrière un proxy Web comme Nginx ou Apache - Quelque chose qui peut faire une limitation de connexion (à moins que vous ne vouliez que les conditions de surcharge abaissent complètement la boîte), réécrire les URL, servir du contenu statique et d'autres sous-services de proxy.

  2. Recycler 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.

  3. Configuration de la collecte / surveillance du journal


PS: Il y a une discussion entre Aaron et Christopher dans les commentaires d'un autre post (à ce jour, c'est le top post). 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 rivaliser pour accepter de nouvelles connexions. D'un point de vue conceptuel, vous pourriez penser à Apache préforcé en faisant cela avec la mise en garde importante que chaque processus n'acceptera qu'une seule connexion et mourra. La perte d'efficacité pour Apache est dans la surcharge des 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 site comme Nginx et à disposer d'un trafic proxy pour chaque travailleur, en alternant entre les travailleurs pour attribuer de nouvelles connexions. Les deux solutions ont des caractéristiques de performance très similaires. Et comme, comme je l'ai mentionné ci-dessus, vous voudrez probablement avoir Nginx (ou une alternative) devant votre service de noeud, le choix 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 quelques avantages à la configuration des ports individuels (possibilité d'avoir moins de couplage entre les processus, décisions plus sophistiquées en matière d'équilibrage de la charge, etc.), -complexité alternative qui fonctionne pour la plupart des gens.


638
2017-12-31 02:48



Une méthode consisterait à exécuter plusieurs instances de node.js sur le serveur, puis à placer un équilibreur de charge (de préférence non bloquant comme nginx) devant eux.


40
2018-03-10 05:47



Ryan Dahl répond à cette question dans le discours technique qu'il a donné à Google l'été dernier. Pour paraphraser, "il suffit d'exécuter plusieurs processus de noeud et d'utiliser quelque chose de raisonnable pour leur permettre de communiquer.

Si vous voulez vous salir les mains tout de suite, consultez le spark2  Pour toujours module. Il rend trivialement la création de processus de nœuds multiples. Il gère la configuration du partage de port, afin que chacun puisse accepter les connexions vers le même port, ainsi que la réactivation automatique si vous voulez vous assurer qu'un processus est redémarré s'il / quand il meurt.

MISE À JOUR - 10/11/11: Le consensus dans la communauté des nœuds semble être celui Grappe est maintenant le module préféré pour gérer plusieurs instances de nœuds par machine. Pour toujours vaut également le coup d'oeil.


31
2017-12-09 12:46



Multi-nœuds exploite tous les cœurs que vous pourriez avoir.
Jettes un coup d'oeil à http://github.com/kriszyp/multi-node.

Pour des besoins plus simples, vous pouvez démarrer plusieurs copies de noeud sur différents numéros de port et placer un équilibreur de charge devant eux.


13
2017-07-20 10:04



Comme mentionné ci-dessus, Grappe mettra à l'échelle 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.

Ces jours-ci, beaucoup de gens préfèrent aussi PM2, qui gère le clustering pour vous et fournit également quelques fonctionnalités de surveillance cool.

Ensuite, ajoutez Nginx ou HAProxy devant plusieurs machines fonctionnant avec le clustering et vous avez plusieurs niveaux de basculement et une capacité de charge beaucoup plus élevée.


10
2018-02-05 15:52



Vous pouvez utiliser grappe module. Vérifier ce.

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);
}

9
2018-04-27 20:23



La version future du nœud vous permettra de fourrer un processus et de lui passer des messages et 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 directe.

Pour l'instant, il n'y a pas de solution facile, mais c'est encore très tôt et node est l'un des projets open source les plus rapides que j'ai jamais vu, alors attendez-vous à quelque chose de génial dans un proche avenir.


7
2018-03-13 18:51



Spark2 est basé sur Spark qui n'est plus maintenu. Grappe est son successeur, et il a quelques fonctionnalités intéressantes, comme la génération d'un processus de travail par cœur de processeur et la réapparition des travailleurs morts.


7
2018-03-08 13:02



j'utilise Travailleur de nœud pour exécuter les processus d'une manière simple à partir de mon processus principal. Cela semble fonctionner bien pendant que nous attendons la façon officielle de venir.


5
2018-05-24 17:23



Le nouveau gamin sur le bloc est celui de LearnBoost "Up".

Il fournit des "rechargements à zéro temps d'arrêt" et crée en plus plusieurs travailleurs (par défaut le nombre de processeurs, mais il est configurable) pour fournir le meilleur de tous les mondes.

C'est nouveau, mais il semble assez stable, et je l'utilise avec bonheur dans l'un de mes projets actuels.


5
2018-02-03 19:14



Node Js prend en charge le clustering pour tirer pleinement parti de votre CPU. Si vous ne l'utilisez 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 s'exécutant sur un thread unique sur un seul cœur de processeur.

Le code ci-dessous vous permet de regrouper votre application. Ce code est un 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 Didacticiel


5
2017-10-02 14:53