Кластер
Исходный код: lib/cluster.js
Кластеры процессов Node.js можно использовать для запуска нескольких экземпляров Node.js, распределяющих рабочую нагрузку между потоками приложений. Если изоляция процессов не требуется, используйте вместо этого модуль worker_threads, который позволяет запускать несколько потоков приложения в одном экземпляре Node.js.
Модуль cluster позволяет легко создавать дочерние процессы, совместно использующие серверные порты.
Модули JavaScript
import cluster from 'node:cluster';
import http from 'node:http';
import { availableParallelism } from 'node:os';
import process from 'node:process';
const numCPUs = availableParallelism();
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}CommonJS
const cluster = require('node:cluster');
const http = require('node:http');
const numCPUs = require('node:os').availableParallelism();
const process = require('node:process');
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}Теперь запущенные процессы Node.js будут совместно использовать порт 8000 между рабочими процессами:
$ node server.js Primary 3596 is running Worker 4324 started Worker 4520 started Worker 6056 started Worker 5644 started copy
В Windows пока невозможно настроить сервер именованных каналов в рабочем процессе.
Как это работает
Рабочие процессы запускаются с помощью метода child_process.fork(), чтобы они могли взаимодействовать с родительским процессом через IPC и передавать дескрипторы серверов в обоих направлениях.
Модуль cluster поддерживает два способа распределения входящих подключений.
Первый (и используемый по умолчанию на всех платформах, кроме Windows) — это циклическое распределение: основной процесс прослушивает порт, принимает новые подключения и распределяет их между рабочими процессами по очереди, используя встроенные механизмы предотвращения перегрузки рабочего процесса.
Второй способ заключается в том, что основной процесс создает сокет прослушивания и отправляет его заинтересованным рабочим процессам. Затем рабочие процессы принимают входящие подключения напрямую.
Теоретически второй способ должен обеспечивать наилучшую производительность. Однако на практике распределение часто оказывается очень неравномерным из-за особенностей планировщика операционной системы. Наблюдались случаи, когда более 70% всех подключений приходилось всего на два процесса из восьми.
Поскольку server.listen() передает большую часть работы основному процессу, есть три случая, когда поведение обычного процесса Node.js и рабочего процесса кластера различается:
-
server.listen({fd: 7})Поскольку сообщение передается основному процессу, прослушиваться будет файловый дескриптор 7 в родительском процессе, а дескриптор будет передан рабочему процессу, вместо того чтобы прослушивать то, на что, по мнению рабочего процесса, ссылается файловый дескриптор 7. -
server.listen(handle)Явное прослушивание дескрипторов приведет к тому, что рабочий процесс будет использовать переданный дескриптор, а не обращаться к основному процессу. -
server.listen(0)Обычно это приводит к тому, что серверы начинают прослушивать случайный порт. Однако в кластере каждый рабочий процесс будет получать один и тот же «случайный» порт при каждом вызовеlisten(0). По сути, порт является случайным при первом вызове, но впоследствии его можно предсказать. Чтобы прослушивать уникальный порт, сгенерируйте номер порта на основе идентификатора рабочего процесса кластера.
Node.js не предоставляет логику маршрутизации. Поэтому важно проектировать приложение так, чтобы оно не слишком полагалось на объекты данных в памяти для таких задач, как управление сеансами и вход в систему.
Поскольку рабочие процессы являются отдельными процессами, их можно завершать или перезапускать в зависимости от потребностей программы, не затрагивая другие рабочие процессы. Пока остаются работающие рабочие процессы, сервер продолжит принимать подключения. Если работающих рабочих процессов не останется, существующие подключения будут разорваны, а новые — отклонены. Однако Node.js автоматически не управляет количеством рабочих процессов. Приложение должно самостоятельно управлять пулом рабочих процессов в соответствии со своими потребностями.
Хотя основным сценарием использования модуля node:cluster является работа с сетью, его также можно применять и в других случаях, требующих рабочих процессов.
Класс: Worker
- Наследует: <EventEmitter>
Объект Worker содержит всю общедоступную информацию и методы рабочего процесса. В основном процессе его можно получить с помощью cluster.workers. В рабочем процессе его можно получить с помощью cluster.worker.
Событие: 'disconnect'
Подобно событию cluster.on('disconnect'), но относится только к этому рабочему процессу.
cluster.fork().on('disconnect', () => {
// Worker has disconnected
}); copy Событие: 'error'
Это событие совпадает с событием, предоставляемым child_process.fork().
В рабочем процессе также можно использовать process.on('error').
Событие: 'exit'
-
code<number> Код завершения, если процесс завершился штатно. -
signal<string> Название сигнала (например,'SIGHUP'), из-за которого процесс был завершен.
Подобно событию cluster.on('exit'), но относится только к этому рабочему процессу.
Модули JavaScript
import cluster from 'node:cluster';
if (cluster.isPrimary) {
const worker = cluster.fork();
worker.on('exit', (code, signal) => {
if (signal) {
console.log(`worker was killed by signal: ${signal}`);
} else if (code !== 0) {
console.log(`worker exited with error code: ${code}`);
} else {
console.log('worker success!');
}
});
}CommonJS
const cluster = require('node:cluster');
if (cluster.isPrimary) {
const worker = cluster.fork();
worker.on('exit', (code, signal) => {
if (signal) {
console.log(`worker was killed by signal: ${signal}`);
} else if (code !== 0) {
console.log(`worker exited with error code: ${code}`);
} else {
console.log('worker success!');
}
});
}Событие: 'listening'
-
address<Object>
Подобно событию cluster.on('listening'), но относится только к этому рабочему процессу.
Модули JavaScript
cluster.fork().on('listening', (address) => {
// Worker is listening
});CommonJS
cluster.fork().on('listening', (address) => {
// Worker is listening
});В рабочем процессе это событие не генерируется.
Событие: 'message'
-
message<Object> -
handle<undefined> | <Object>
Подобно событию 'message' объекта cluster, но относится только к этому рабочему процессу.
В рабочем процессе также можно использовать process.on('message').
См. событие process: 'message'.
Ниже приведен пример использования системы сообщений. В нем в основном процессе ведется подсчет количества HTTP-запросов, полученных рабочими процессами:
Модули JavaScript
import cluster from 'node:cluster';
import http from 'node:http';
import { availableParallelism } from 'node:os';
import process from 'node:process';
if (cluster.isPrimary) {
// Keep track of http requests
let numReqs = 0;
setInterval(() => {
console.log(`numReqs = ${numReqs}`);
}, 1000);
// Count requests
function messageHandler(msg) {
if (msg.cmd && msg.cmd === 'notifyRequest') {
numReqs += 1;
}
}
// Start workers and listen for messages containing notifyRequest
const numCPUs = availableParallelism();
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
for (const id in cluster.workers) {
cluster.workers[id].on('message', messageHandler);
}
} else {
// Worker processes have a http server.
http.Server((req, res) => {
res.writeHead(200);
res.end('hello world\n');
// Notify primary about the request
process.send({ cmd: 'notifyRequest' });
}).listen(8000);
}CommonJS
const cluster = require('node:cluster');
const http = require('node:http');
const numCPUs = require('node:os').availableParallelism();
const process = require('node:process');
if (cluster.isPrimary) {
// Keep track of http requests
let numReqs = 0;
setInterval(() => {
console.log(`numReqs = ${numReqs}`);
}, 1000);
// Count requests
function messageHandler(msg) {
if (msg.cmd && msg.cmd === 'notifyRequest') {
numReqs += 1;
}
}
// Start workers and listen for messages containing notifyRequest
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
for (const id in cluster.workers) {
cluster.workers[id].on('message', messageHandler);
}
} else {
// Worker processes have a http server.
http.Server((req, res) => {
res.writeHead(200);
res.end('hello world\n');
// Notify primary about the request
process.send({ cmd: 'notifyRequest' });
}).listen(8000);
}Событие: 'online'
Подобно событию cluster.on('online'), но относится только к этому рабочему процессу.
cluster.fork().on('online', () => {
// Worker is online
}); copy В рабочем процессе это событие не генерируется.
worker.disconnect()
- Возвращает: <cluster.Worker> Ссылку на
worker.
В рабочем процессе эта функция закроет все серверы, дождется события 'close' на этих серверах, а затем отключит канал IPC.
В основном процессе рабочему процессу отправляется внутреннее сообщение, которое вызывает .disconnect() в самом рабочем процессе.
Устанавливает значение .exitedAfterDisconnect.
После закрытия сервера он перестает принимать новые подключения, но подключения могут принимать другие рабочие процессы, которые продолжают прослушивание. Существующим подключениям будет позволено закрыться обычным образом. Когда подключений больше не останется (см. server.close()), канал IPC с рабочим процессом закроется, позволяя ему корректно завершить работу.
Описанное выше относится только к подключениям к серверу: рабочие процессы автоматически не закрывают клиентские подключения, а отключение не дожидается их закрытия перед завершением работы.
В рабочем процессе process.disconnect существует, но это не данная функция, а disconnect().
Поскольку длительные подключения к серверу могут помешать отключению рабочих процессов, может быть полезно отправить сообщение, чтобы приложение выполнило специальные действия для их закрытия. Также может быть полезно установить тайм-аут и завершить рабочий процесс, если по истечении некоторого времени событие 'disconnect' не было сгенерировано.
if (cluster.isPrimary) {
const worker = cluster.fork();
let timeout;
worker.on('listening', (address) => {
worker.send('shutdown');
worker.disconnect();
timeout = setTimeout(() => {
worker.kill();
}, 2000);
});
worker.on('disconnect', () => {
clearTimeout(timeout);
});
} else if (cluster.isWorker) {
const net = require('node:net');
const server = net.createServer((socket) => {
// Connections never end
});
server.listen(8000);
process.on('message', (msg) => {
if (msg === 'shutdown') {
// Initiate graceful close of any connections to server
}
});
} copy
worker.exitedAfterDisconnect
- Тип: <boolean>
Это свойство имеет значение true, если рабочий процесс завершился из-за .disconnect(). Если рабочий процесс завершился по любой другой причине, оно имеет значение false. Если рабочий процесс еще не завершился, оно имеет значение undefined.
Логическое свойство worker.exitedAfterDisconnect позволяет отличать добровольное завершение от случайного; основной процесс может решить не перезапускать рабочий процесс, основываясь на этом значении.
cluster.on('exit', (worker, code, signal) => {
if (worker.exitedAfterDisconnect === true) {
console.log('Oh, it was just voluntary – no need to worry');
}
});
// kill worker
worker.kill(); copy
worker.id
- Тип: <integer>
Каждому новому рабочему процессу присваивается уникальный идентификатор, который хранится в id.
Пока рабочий процесс работает, этот идентификатор используется как ключ для доступа к нему в cluster.workers.
worker.isConnected()
Эта функция возвращает true, если рабочий процесс подключен к основному процессу через канал IPC, и false в противном случае. Рабочий процесс подключается к основному процессу после создания. Он отключается после генерации события 'disconnect'.
worker.isDead()
Эта функция возвращает true, если процесс рабочего процесса завершился (в результате выхода или получения сигнала). В противном случае она возвращает false.
Модули JavaScript
import cluster from 'node:cluster';
import http from 'node:http';
import { availableParallelism } from 'node:os';
import process from 'node:process';
const numCPUs = availableParallelism();
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('fork', (worker) => {
console.log('worker is dead:', worker.isDead());
});
cluster.on('exit', (worker, code, signal) => {
console.log('worker is dead:', worker.isDead());
});
} else {
// Workers can share any TCP connection. In this case, it is an HTTP server.
http.createServer((req, res) => {
res.writeHead(200);
res.end(`Current process\n ${process.pid}`);
process.kill(process.pid);
}).listen(8000);
}CommonJS
const cluster = require('node:cluster');
const http = require('node:http');
const numCPUs = require('node:os').availableParallelism();
const process = require('node:process');
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('fork', (worker) => {
console.log('worker is dead:', worker.isDead());
});
cluster.on('exit', (worker, code, signal) => {
console.log('worker is dead:', worker.isDead());
});
} else {
// Workers can share any TCP connection. In this case, it is an HTTP server.
http.createServer((req, res) => {
res.writeHead(200);
res.end(`Current process\n ${process.pid}`);
process.kill(process.pid);
}).listen(8000);
}
worker.kill([signal])
-
signal<string> Название сигнала завершения, отправляемого процессу рабочего процесса. По умолчанию:'SIGTERM'
Эта функция завершит рабочий процесс. В основном процессе она отключает worker.process, а после отключения завершает процесс с помощью signal. В рабочем процессе она завершает процесс с помощью signal.
Функция kill() завершает процесс рабочего процесса, не дожидаясь корректного отключения; ее поведение совпадает с поведением worker.process.kill().
Для обратной совместимости этот метод также доступен под именем worker.destroy().
В рабочем процессе process.kill() существует, но это не данная функция, а kill().
worker.process
- Тип: <ChildProcess>
Все рабочие процессы создаются с помощью child_process.fork(); возвращенный этой функцией объект сохраняется в .process. В рабочем процессе сохраняется глобальный объект process.
См.: Модуль дочерних процессов.
Рабочие процессы вызовут process.exit(0), если в process произойдет событие 'disconnect', а .exitedAfterDisconnect не равно true. Это защищает от случайного отключения.
worker.send(message[, sendHandle[, options]][, callback])
-
message<Object> -
sendHandle<Handle> -
options<Object> Аргументoptions, если он указан, представляет собой объект, используемый для настройки отправки определенных типов дескрипторов.optionsподдерживает следующие свойства:-
keepOpen<boolean> Значение, которое можно использовать при передаче экземпляровnet.Socket. Если значениеtrue, сокет остается открытым в процессе-отправителе. По умолчанию:false.
-
-
callback<Function> - Возвращает: <boolean>
Отправляет сообщение рабочему или основному процессу, при необходимости передавая дескриптор.
В основном процессе эта функция отправляет сообщение определенному рабочему процессу. Она идентична функции ChildProcess.send().
В рабочем процессе эта функция отправляет сообщение основному процессу. Она идентична функции process.send().
В этом примере все сообщения от основного процесса отправляются обратно ему:
if (cluster.isPrimary) {
const worker = cluster.fork();
worker.send('hi there');
} else if (cluster.isWorker) {
process.on('message', (msg) => {
process.send(msg);
});
} copy Событие: 'disconnect'
-
worker<cluster.Worker>
Генерируется после отключения канала IPC рабочего процесса. Это может произойти, когда рабочий процесс корректно завершается, принудительно останавливается или отключается вручную (например, с помощью worker.disconnect()).
Между событиями 'disconnect' и 'exit' может пройти некоторое время. Эти события можно использовать, чтобы определить, завис ли процесс во время очистки или существуют длительные подключения.
cluster.on('disconnect', (worker) => {
console.log(`The worker #${worker.id} has disconnected`);
}); copy Событие: 'exit'
-
worker<cluster.Worker> -
code<number> Код завершения, если процесс завершился штатно. -
signal<string> Название сигнала (например,'SIGHUP'), из-за которого процесс был завершен.
Когда любой из рабочих процессов завершает работу, модуль cluster генерирует событие 'exit'.
Это событие можно использовать для перезапуска рабочего процесса, повторно вызвав .fork().
cluster.on('exit', (worker, code, signal) => {
console.log('worker %d died (%s). restarting...',
worker.process.pid, signal || code);
cluster.fork();
}); copy Событие: 'fork'
-
worker<cluster.Worker>
При запуске нового рабочего процесса модуль cluster генерирует событие 'fork'. Его можно использовать для регистрации активности рабочих процессов и создания пользовательского тайм-аута.
const timeouts = [];
function errorMsg() {
console.error('Something must be wrong with the connection ...');
}
cluster.on('fork', (worker) => {
timeouts[worker.id] = setTimeout(errorMsg, 2000);
});
cluster.on('listening', (worker, address) => {
clearTimeout(timeouts[worker.id]);
});
cluster.on('exit', (worker, code, signal) => {
clearTimeout(timeouts[worker.id]);
errorMsg();
}); copy Событие: 'listening'
-
worker<cluster.Worker> -
address<Object>
После вызова listen() из рабочего процесса, когда на сервере генерируется событие 'listening', в основном процессе для cluster также генерируется событие 'listening'.
Обработчик события вызывается с двумя аргументами: worker содержит объект рабочего процесса, а объект address — следующие свойства подключения: address, port и addressType. Это особенно полезно, если рабочий процесс прослушивает несколько адресов.
cluster.on('listening', (worker, address) => {
console.log(
`A worker is now connected to ${address.address}:${address.port}`);
}); copy Значение addressType может быть одним из следующих:
-
4(TCPv4) -
6(TCPv6) -
-1(сокет домена Unix) -
'udp4'или'udp6'(UDPv4 или UDPv6)
Событие: 'message'
-
worker<cluster.Worker> -
message<Object> -
handle<undefined> | <Object>
Генерируется, когда основной процесс кластера получает сообщение от любого рабочего процесса.
Событие: 'online'
-
worker<cluster.Worker>
После запуска нового рабочего процесса он должен отправить сообщение о переходе в состояние онлайн. Когда основной процесс получает такое сообщение, он генерирует это событие. Разница между 'fork' и 'online' заключается в том, что событие fork генерируется, когда основной процесс запускает рабочий процесс, а 'online' — когда рабочий процесс начинает работу.
cluster.on('online', (worker) => {
console.log('Yay, the worker responded after it was forked');
}); copy Событие: 'setup'
-
settings<Object>
Генерируется при каждом вызове .setupPrimary().
Объект settings — это объект cluster.settings на момент вызова .setupPrimary(); он носит только рекомендательный характер, поскольку несколько вызовов .setupPrimary() могут произойти в течение одного тика.
Если важна точность, используйте cluster.settings.
cluster.disconnect([callback])
-
callback<Function> Вызывается, когда все рабочие процессы отключены, а дескрипторы закрыты.
Вызывает .disconnect() для каждого рабочего процесса в cluster.workers.
После их отключения все внутренние дескрипторы будут закрыты, что позволит основному процессу корректно завершить работу, если нет других ожидающих событий.
Метод принимает необязательный аргумент обратного вызова, который будет вызван по завершении.
Этот метод можно вызвать только из основного процесса.
cluster.fork([env])
-
env<Object> Пары ключ/значение для добавления в окружение процесса рабочего процесса. - Возвращает: <cluster.Worker>
Запускает новый рабочий процесс.
Этот метод можно вызвать только из основного процесса.
cluster.isMaster
Устаревший псевдоним для cluster.isPrimary.
cluster.isPrimary
- Тип: <boolean>
Имеет значение true, если процесс является основным. Это определяется значением process.env.NODE_UNIQUE_ID. Если process.env.NODE_UNIQUE_ID не определено, то isPrimary имеет значение true.
cluster.isWorker
- Тип: <boolean>
Имеет значение true, если процесс не является основным (то есть является отрицанием cluster.isPrimary).
cluster.schedulingPolicy
Политика планирования: cluster.SCHED_RR для циклического распределения или cluster.SCHED_NONE, чтобы оставить выбор операционной системе. Это глобальный параметр, который фактически становится неизменяемым после запуска первого рабочего процесса или вызова .setupPrimary() — в зависимости от того, что произойдет раньше.
SCHED_RR используется по умолчанию во всех операционных системах, кроме Windows. В Windows будет использоваться SCHED_RR, когда libuv сможет эффективно распределять дескрипторы IOCP без существенного снижения производительности.
Значение cluster.schedulingPolicy также можно задать с помощью переменной окружения NODE_CLUSTER_SCHED_POLICY. Допустимые значения: 'rr' и 'none'.
cluster.settings
- Тип: <Object>
-
execArgv<string[]> Список строковых аргументов, передаваемых исполняемому файлу Node.js. По умолчанию:process.execArgv. -
exec<string> Путь к файлу рабочего процесса. По умолчанию:process.argv[1]. -
args<string[]> Строковые аргументы, передаваемые рабочему процессу. По умолчанию:process.argv.slice(2). -
cwd<string> Текущий рабочий каталог процесса рабочего процесса. По умолчанию:undefined(наследуется от родительского процесса). -
serialization<string> Задает тип сериализации, используемый для отправки сообщений между процессами. Возможные значения:'json'и'advanced'. Подробнее см. в разделе Расширенная сериализация дляchild_process. По умолчанию:false. -
silent<boolean> Определяет, следует ли передавать вывод в стандартные потоки ввода-вывода родительского процесса. По умолчанию:false. -
stdio<Array> Настраивает стандартные потоки ввода-вывода для запускаемых процессов. Поскольку для работы модулю cluster требуется IPC, эта конфигурация должна содержать запись'ipc'. Если этот параметр указан, он переопределяетsilent. См. параметрstdioметодаchild_process.spawn(). -
uid<number> Задает идентификатор пользователя процесса. (См.setuid(2).) -
gid<number> Задает идентификатор группы процесса. (См.setgid(2).) -
inspectPort<number> | <Function> Задает порт инспектора рабочего процесса. Это может быть число или функция без аргументов, возвращающая число. По умолчанию каждому рабочему процессу назначается собственный порт, начиная сprocess.debugPortосновного процесса и увеличивая его. -
windowsHide<boolean> Скрывает окно консоли запускаемых процессов, которое обычно создается в системах Windows. По умолчанию:false.
-
После вызова .setupPrimary() (или .fork()) этот объект настроек будет содержать параметры, включая значения по умолчанию.
Этот объект не предназначен для изменения или установки вручную.
cluster.setupMaster([settings])
Устаревший псевдоним для .setupPrimary().
cluster.setupPrimary([settings])
-
settings<Object> См.cluster.settings.
setupPrimary используется для изменения поведения 'fork' по умолчанию. После вызова параметры будут доступны в cluster.settings.
Изменения параметров влияют только на последующие вызовы .fork() и не влияют на уже работающие рабочие процессы.
Единственный атрибут рабочего процесса, который нельзя задать через .setupPrimary(), — это env, передаваемый в .fork().
Указанные выше значения по умолчанию применяются только при первом вызове; при последующих вызовах значениями по умолчанию будут текущие значения на момент вызова cluster.setupPrimary().
Модули JavaScript
import cluster from 'node:cluster';
cluster.setupPrimary({
exec: 'worker.js',
args: ['--use', 'https'],
silent: true,
});
cluster.fork(); // https worker
cluster.setupPrimary({
exec: 'worker.js',
args: ['--use', 'http'],
});
cluster.fork(); // http workerCommonJS
const cluster = require('node:cluster');
cluster.setupPrimary({
exec: 'worker.js',
args: ['--use', 'https'],
silent: true,
});
cluster.fork(); // https worker
cluster.setupPrimary({
exec: 'worker.js',
args: ['--use', 'http'],
});
cluster.fork(); // http workerВызывать это можно только из основного процесса.
cluster.worker
- Тип: <Object>
Ссылка на объект текущего рабочего процесса. Недоступно в основном процессе.
Модули JavaScript
import cluster from 'node:cluster';
if (cluster.isPrimary) {
console.log('I am primary');
cluster.fork();
cluster.fork();
} else if (cluster.isWorker) {
console.log(`I am worker #${cluster.worker.id}`);
}CommonJS
const cluster = require('node:cluster');
if (cluster.isPrimary) {
console.log('I am primary');
cluster.fork();
cluster.fork();
} else if (cluster.isWorker) {
console.log(`I am worker #${cluster.worker.id}`);
}
cluster.workers
- Тип: <Object>
Хеш-таблица, в которой хранятся активные объекты рабочих процессов с ключами, соответствующими полю id. Это упрощает перебор всех рабочих процессов. Она доступна только в основном процессе.
Рабочий процесс удаляется из cluster.workers после отключения и завершения. Заранее определить порядок этих двух событий невозможно. Однако гарантируется, что удаление из списка cluster.workers происходит до отправки последнего события 'disconnect' или 'exit'.
Модули JavaScript
import cluster from 'node:cluster';
for (const worker of Object.values(cluster.workers)) {
worker.send('big announcement to all workers');
}CommonJS
const cluster = require('node:cluster');
for (const worker of Object.values(cluster.workers)) {
worker.send('big announcement to all workers');
}
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v22.x/docs/api/cluster.html