Pregunta Node.js en máquinas multi-core


Node.js parece interesante, PERO Debo perderme algo. ¿No está Node.js sintonizado solo para ejecutar en un solo proceso e hilo?

Entonces, ¿cómo se escala para CPU multi-core y servidores multi-CPU? Después de todo, es genial hacer un servidor de un solo hilo lo más rápido posible, pero para cargas altas, me gustaría usar varias CPU. Y lo mismo ocurre con las aplicaciones más rápidas: parece que hoy en día se usan varias CPU y paralelizan las tareas.

¿Cómo encaja Node.js en esta imagen? ¿Es su idea distribuir de alguna manera varias instancias o qué?


517
2018-03-05 15:13


origen


Respuestas:


[Esta publicación está actualizada desde 2012-09-02 (más reciente que la anterior).]

Node.js escala completamente en máquinas multi-core.

Sí, Node.js es de un hilo por proceso. Esta es una decisión de diseño muy deliberada y elimina la necesidad de lidiar con la semántica de bloqueo. Si no está de acuerdo con esto, probablemente todavía no se da cuenta de lo terriblemente difícil que es depurar el código de subprocesos múltiples. Para una explicación más profunda del modelo de proceso Node.js y por qué funciona de esta manera (y por qué NUNCA admitirá múltiples hilos), lea mi otra publicación.

Entonces, ¿cómo aprovecho mi caja de 16 núcleos?

Dos caminos:

  • Para grandes tareas informáticas, como la codificación de imágenes, Node.js puede iniciar procesos secundarios o enviar mensajes a procesos de trabajo adicionales. En este diseño, tendrías un hilo administrando el flujo de eventos y N procesos haciendo tareas pesadas de cálculo y masticando las otras 15 CPU.
  • Para escalar el rendimiento en un servicio web, debe ejecutar varios servidores Node.js en un solo cuadro, uno por núcleo y dividir el tráfico de solicitudes entre ellos. Esto proporciona una excelente afinidad de la CPU y escalará el rendimiento casi linealmente con el recuento de núcleos.

Escalado de rendimiento en un servicio web

Desde v6.0.X Node.js ha incluido el módulo de clúster recién salido de la caja, lo que facilita la configuración de múltiples trabajadores de nodo que pueden escuchar en un solo puerto. Tenga en cuenta que esto NO es lo mismo que el módulo "cluster" de learnboost más antiguo disponible a través de npm.

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  http.Server(function(req, res) { ... }).listen(8000);
}

Los trabajadores competirán para aceptar nuevas conexiones, y el proceso menos cargado es más probable que gane. Funciona bastante bien y puede ampliar el rendimiento bastante bien en una caja de varios núcleos.

Si tiene suficiente carga para preocuparse por múltiples núcleos, entonces también querrá hacer algunas cosas más:

  1. Ejecute su servicio Node.js detrás de un proxy web como Nginx o apache - algo que puede acelerar la conexión (a menos que desee que las condiciones de sobrecarga cierren la caja por completo), reescribir las URL, ofrecer contenido estático y proxy de otros subservicios.

  2. Recicle periódicamente sus procesos de trabajo. Para un proceso de larga duración, incluso una pequeña pérdida de memoria eventualmente se acumulará.

  3. Configurar la recopilación / supervisión de registros


PD: Hay una discusión entre Aaron y Christopher en los comentarios de otra publicación (al momento de escribir esto, es la publicación principal). Algunos comentarios sobre eso:

  • Un modelo de socket compartido es muy conveniente para permitir que múltiples procesos escuchen en un solo puerto y compitan para aceptar nuevas conexiones. Conceptualmente, podría pensar en Apache preformado haciendo esto con la importante advertencia de que cada proceso solo aceptará una conexión única y luego morirá. La pérdida de eficiencia para Apache está en la parte superior de bifurcar nuevos procesos y no tiene nada que ver con las operaciones de socket.
  • Para Node.js, tener N trabajadores compiten en un único socket es una solución extremadamente razonable. La alternativa es configurar un front-end on-box como Nginx y tener ese tráfico proxy para los trabajadores individuales, alternando entre los trabajadores para asignar nuevas conexiones. Las dos soluciones tienen características de rendimiento muy similares. Y dado que, como mencioné anteriormente, es probable que desee tener Nginx (o una alternativa) frente a su servicio de nodo de todos modos, la elección aquí es realmente entre:

Puertos Compartidos: nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)

vs

Puertos individuales: nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}

Podría decirse que hay algunos beneficios para la configuración de puertos individuales (posibilidad de tener menos acoplamiento entre procesos, tener decisiones de equilibrio de carga más sofisticadas, etc.), pero definitivamente es más trabajo de configurar y el módulo de clúster incorporado es muy bajo -complejidad alternativa que funciona para la mayoría de las personas.


638
2017-12-31 02:48



Un método sería ejecutar varias instancias de node.js en el servidor y luego colocar un equilibrador de carga (preferiblemente uno no bloqueante como nginx) delante de ellos.


40
2018-03-10 05:47



Ryan Dahl responde esta pregunta en la charla técnica que dio en Google el verano pasado. Parafraseando, "simplemente ejecute procesos de múltiples nodos y use algo sensible para permitirles comunicarse. Por ejemplo, sendmsg () - estilo IPC o RPC tradicional".

Si quieres ensuciarte las manos de inmediato, echa un vistazo a chispa2  Siempre módulo. Hace que el desove de procesos de nodos múltiples sea trivialmente fácil. Se encarga de configurar el uso compartido de puertos, de modo que cada uno de ellos pueda aceptar conexiones al mismo puerto, y también la reaparición automática si desea asegurarse de que un proceso se reinicie si / cuando muere.

ACTUALIZACIÓN - 10/11/11: El consenso en la comunidad de nodos parece ser que Racimo ahora es el módulo preferido para administrar múltiples instancias de nodos por máquina. Siempre también vale la pena echarle un vistazo.


31
2017-12-09 12:46



El nodo múltiple aprovecha todos los núcleos que pueda tener.
Mira esto http://github.com/kriszyp/multi-node.

Para necesidades más simples, puede iniciar múltiples copias de nodo en diferentes números de puerto y poner un equilibrador de carga en frente de ellos.


13
2017-07-20 10:04



Como se ha mencionado más arriba, Racimo Escalará y equilibrará la carga de su aplicación en todos los núcleos.

agregando algo así como

cluster.on('exit', function () {
  cluster.fork();
});

Reiniciará a cualquier trabajador que falle.

En estos días, mucha gente también prefiere PM2, que maneja la agrupación por usted y también proporciona algunas funciones de monitoreo geniales.

Luego, agregue Nginx o HAProxy frente a varias máquinas que se ejecutan con clústeres y tiene múltiples niveles de conmutación por error y una capacidad de carga mucho más alta.


10
2018-02-05 15:52



Puedes usar racimo módulo. Comprobar esta.

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 versión futura del nodo le permitirá copiar un proceso y pasarle mensajes, y Ryan ha declarado que quiere encontrar la manera de compartir los manejadores de archivos, por lo que no será una implementación directa del Trabajador Web.

En este momento no hay una solución fácil para esto, pero aún es muy temprano y node es uno de los proyectos de código abierto más rápidos que he visto, así que espere algo asombroso en el futuro cercano.


7
2018-03-13 18:51