javascript - nodejs - Paralelizar tareas en Node.js
threads node js (5)
Tengo algunas tareas que quiero hacer en JS que requieren muchos recursos. Para esta pregunta, supongamos que son algunos cálculos pesados, en lugar de acceso al sistema. Ahora quiero ejecutar las tareas A, B y C al mismo tiempo y ejecutar alguna función D cuando haya terminado.
La biblioteca asíncrona proporciona un buen andamio para esto:
async.parallel([A, B, C], D);
Si lo que estoy haciendo son solo cálculos, entonces esto seguirá ejecutándose sincrónicamente (a menos que la biblioteca esté colocando las tareas en diferentes hilos, lo que espero que no sea el caso). ¿Cómo hago que esto sea realmente paralelo? ¿Qué se hace normalmente con el código asincrónico para no bloquear a la persona que llama (cuando se trabaja con NodeJS)? ¿Está comenzando un proceso secundario ?
Recientemente me encontré con parallel.js, pero parece que está usando multi-core y también tiene características de tipo de reducción de mapa. http://adambom.github.io/parallel.js/
Tenga en cuenta que la E / S está paralelizada por Node.js; solo sus devoluciones de llamada de JavaScript tienen un solo hilo.
Suponiendo que está escribiendo un servidor, una alternativa para agregar la complejidad de los procesos de desove o bifurcación es simplemente construir servidores de nodo sin estado y ejecutar una instancia por núcleo, o mejor aún, ejecutar muchas instancias en su propio servidor virtual virtualizado. Coordine las solicitudes entrantes utilizando un proxy inverso o balanceador de carga.
También puede descargar computación a otro servidor, tal vez MongoDB (usando MapReduce) o Hadoop.
Para ser verdaderamente hardcore, podría escribir un complemento Nodo en C ++ y tener un control detallado de paralelizar el código de cálculo. La velocidad de C ++ podría negar la necesidad de paralelización de todos modos.
Siempre puede escribir código para realizar tareas computacionalmente intensivas en otro idioma más adecuado para el cálculo numérico y, por ejemplo, exponerlos a través de una API REST.
Finalmente, quizás podría ejecutar el código en la GPU usando node-cuda
o algo similar, dependiendo del tipo de cálculo (no todos pueden optimizarse para la GPU).
Sí, puede bifurcar y generar otros procesos, pero me parece que una de las principales ventajas del nodo es no tener que preocuparse mucho por la paralelización y el enhebrado, y por lo tanto, eludir una gran cantidad de complejidad por completo.
Asincrónico y paralelo no son lo mismo. Asíncrono significa que no tiene que esperar a la sincronización. Paralelo significa que puedes estar haciendo muchas cosas al mismo tiempo. Node.js solo es asincrónico, pero su único 1 hilo. Solo puede funcionar en 1 cosa a la vez. Si tiene un cálculo de ejecución prolongada, debe iniciar otro proceso y luego hacer que su proceso node.js espere resultados de manera asíncrona.
Para hacer esto, puede usar child_process.spawn y luego leer datos de stdin.
http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
var spawn = require(''child_process'').spawn;
var process2 = spawn(''sh'', [''./computationProgram'', ''parameter''] );
process2.stderr.on(''data'', function (data) {
//handle error input
});
process2.stdout.on(''data'', function (data) {
//handle data results
});
Dependiendo de su caso de uso, puede usar algo como
task.js Interfaz simplificada para hacer que el código intensivo de la CPU se ejecute en todos los núcleos (node.js y web)
Un ejemplo sería
function blocking (exampleArgument) {
// block thread
}
// turn blocking pure function into a worker task
const blockingAsync = task.wrap(blocking);
// run task on a autoscaling worker pool
blockingAsync(''exampleArgumentValue'').then(result => {
// do something with result
});
¿Cómo hago que esto sea realmente paralelo?
En primer lugar, no se ejecutará en paralelo en una aplicación de nodo único. Una aplicación de nodo se ejecuta en un único subproceso y el bucle de eventos del nodo procesa solo un evento a la vez. Incluso cuando se ejecuta en un cuadro de varios núcleos, no obtendrá el paralelismo del procesamiento dentro de una aplicación de nodo.
Dicho esto, puede obtener el paralelismo de procesamiento en la máquina multinúcleo mediante la bifurcación del código en procesos de nodo separados o al generar el proceso hijo . Esto, en efecto, le permite crear múltiples instancias del nodo en sí mismo y comunicarse con esos procesos de diferentes maneras (por ej., Stdout, proceso del mecanismo de fork IPC). Además, puede optar por separar las funciones (por responsabilidad) en su propia aplicación / servidor nodo y llamarlo a través de RPC.
¿Qué se hace normalmente con el código asincrónico para no bloquear a la persona que llama (cuando se trabaja con NodeJS)? ¿Está comenzando un proceso secundario?
No está comenzando un nuevo proceso. Debajo, cuando async.parallel se usa en node.js , está usando process.nextTick()
. Y nextTick () le permite evitar bloquear a la persona que llama posponiendo el trabajo a una nueva pila para que pueda intercalar tareas intensivas de la CPU, etc.
Larga historia corta
El nodo no hace que sea fácil "out of the box" para lograr concurrencia multiprocesador. Nodo en cambio le ofrece un diseño sin bloqueo y un bucle de evento que aprovecha un hilo sin compartir la memoria. Múltiples hilos no pueden compartir datos / memoria, por lo tanto, no se necesitan bloqueos. El nodo está libre de bloqueo . Un proceso de nodo aprovecha un hilo, y esto hace que el nodo sea seguro y poderoso.
Cuando necesite dividir el trabajo entre múltiples procesos, utilice algún tipo de mensaje que pase para comunicarse con los otros procesos / servidores. por ejemplo, IPC / RPC.
Para más ver:
Respuesta impresionante de SO en Qué es Node.js ... con toneladas de bondad.