Поддерживает ли Node.js parallelism?

Я больше искал разницу между concurrency и parallelism. Я наткнулся на беседу на YouTube, которую дал Роб Пайк, говоря о различиях между concurrency и parallelism. Его разговор был в контексте языка Google Go. Из того, что я понимаю, concurrency - это способ управления несколькими вещами, но parallelism - это физическое выполнение нескольких вещей одновременно.

Из того, что я также понимаю, Node.js работает как процесс с одним потоком. Итак, хотя Node поддерживает concurrency с тем, как он реализует обратные вызовы и т.д., Обладает ли он способностью выполнять параллельное выполнение задач? Можно ли настроить несколько потоков на отдельных процессорах?

Ответ 1

Узел может поддерживать "Параллелизм" через модули Cluster или child_process, упакованные в Core API Nodejs. Оба эти модуля создают дополнительные процессы, а не дополнительные потоки.

Потоки создаются и управляются, иногда в пуле, "под капотом" с помощью libuv, который node реализует и использует для выполнения асинхронных операций, таких как чтение из файла. Вы не можете явно создать поток из своего исполняемого Javascript. Вы можете прочитать больше о libuv на следующих ресурсах

Кроме того, это отличный вопрос о потоках и пуле, в котором много деталей.

Cluster используется для распределения рабочей нагрузки Сервера по нескольким ядрам и при этом позволяет им совместно использовать порт. Однако Cluster использует child_process.fork() под капотом и обменивается данными через межпроцессное взаимодействие. Подробнее о Cluster вы можете прочитать в Документах по API ядра Nodejs.

child_process предлагает несколько различных способов распараллеливания работы через exec(), spawn() или fork(). Родительский процесс может взаимодействовать с дочерним процессом, используя межпроцессное взаимодействие через каналы.

По сути, Node хочет, чтобы вы использовали цикл обработки событий и оставили управление потоками libuv. Вот почему так легко создать код, который обычно требует мер блокировки и безопасности потоков. Если вы должны выполнять работу, требующую тяжелой работы или значительного количества блокирующих (синхронных) работ, то вы можете использовать child_process, чтобы снять эту работу. Если вам нужно масштабировать веб-приложение по ядрам, используйте Cluster.

Ответ 2

Если я не ошибаюсь, вы ищете нечто вроде многопоточности и/или вычисления нескольких вещей одновременно.

Несколько выполнения сразу
SIMD начинает искать свой путь в браузерах, а реализация Node не отстает. Посмотрите node-simd или MDN SIMD (браузеры). SIMD по-прежнему экспериментальна и работает только на поддерживаемых процессорах на данный момент (очевидно, поскольку не все процессоры имеют эту функциональность). Он выполняет сразу несколько действий, примером сравнения обычного JS с SIMD JS будет:

// Normal addition, 4 actions are executed.
var a = [1, 2, 3, 4];
var b = [5, 6, 7, 8];
var c = [];

c[0] = a[0] + b[0];
c[1] = a[1] + b[1];
c[2] = a[2] + b[2];
c[3] = a[3] + b[3];
c; // Array[6, 8, 10, 12]

// SIMD execution - all additions are processed simultaenously through the CPU
var a = SIMD.Float32x4(1, 2, 3, 4);
var b = SIMD.Float32x4(5, 6, 7, 8);
var c = SIMD.Float32x4.add(a,b);
c; // Float32x4[6, 8, 10, 12]

Многопоточность
Что касается многопоточности, то webworkers уже существует в среде браузера. Это портировано до Node полностью в соответствии с спецификацией HTML, как показано в этом репозитории.
Здесь хорошее объяснение относительно того, почему webworkers было даже перенесено на Node, в первую очередь, поскольку вы уже можете запускать дочерние процессы в других потоков и других процессоров с модулем child_process. node-webworker - отличный модуль, так как каждый процесс запускается внутри его контекста и в своем собственном процессе node, поэтому он действительно многопоточен с node.

Итак, чтобы запускать разные процессы на разных процессорах, вы должны либо принять node-webworker, либо использовать child_process для создания других потоков для одновременного выполнения отдельных действий с разными ядрами ЦП. node-webworker может прослушивать события, используя знакомый API postMessage, а child_process будет связываться через stdin / stdout / stderr.

Надеюсь, что ответит на ваш вопрос:)

Ответ 3

Выполнение нескольких потоков в отдельных процессорах на одном хост-компьютере может быть достигнуто путем использования собственных модулей Node os и cluster. Ниже приведен простой надуманный пример

const cluster = require('cluster');
const os = require('os');

((port) => {
    if (cluster.isMaster) {
        // fork the process
        os.cpus().forEach((cpu) => {
            cluster.fork();
        });

    } else {
        // if we're not in the master thread, start the HTTP server
        http.createServer((req, res) => {
            // Handle request
        }).listen(port, () => {
            console.log('The server is listening on port ${port}');
        });
    }
})(3000)