cluster
Все экспорты являются неработающими заглушками.
Кластеры процессов Node.js можно использовать для запуска нескольких экземпляров Node.js, распределяя рабочую нагрузку между их потоками приложения. Если изоляция процессов не требуется, используйте вместо этого модуль worker_threads, который позволяет запускать несколько потоков приложения в одном экземпляре Node.js.
Модуль cluster позволяет легко создавать дочерние процессы, совместно использующие порты сервера.
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`);
}
Теперь запущенные процессы Node.js будут совместно использовать порт 8000:
$ node server.js
Primary 3596 is running
Worker 4324 started
Worker 4520 started
Worker 6056 started
Worker 5644 started
В Windows пока невозможно настроить сервер именованного канала в рабочем процессе.
Использование в Deno
import * as mod from "node:cluster";
класс Worker
Использование в Deno
import { Worker } from "node:cluster";
Этот символ является неработающей заглушкой.
Объект Worker содержит общедоступную информацию и методы рабочего процесса. В главном процессе его можно получить с помощью cluster.workers. В рабочем процессе его можно получить с помощью cluster.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();
id: number Каждому новому рабочему процессу присваивается уникальный идентификатор; этот идентификатор хранится в id.
Пока рабочий процесс активен, этот ключ используется для его индексации в cluster.workers.
process: child.ChildProcess Все рабочие процессы создаются с помощью child_process.fork(); объект, возвращаемый этой функцией, сохраняется как .process. В рабочем процессе сохраняется глобальный объект process.
См. также: Модуль дочерних процессов.
Рабочие процессы вызовут process.exit(0), если в process произойдет событие 'disconnect' и .exitedAfterDisconnect не равно true. Это защищает от случайного отключения.
Методы
addListener(
event: string,
listener: (...args: any[]) => void,
): this events.EventEmitter
- disconnect
- error
- exit
- listening
- message
- online
addListener(
event: "disconnect",
listener: () => void,
): this addListener(
event: "error",
listener: (error: Error) => void,
): this addListener(
event: "exit",
listener: (
code: number,
signal: string,
) => void,
): this addListener(
event: "listening",
listener: (address: Address) => void,
): this addListener(
event: "message",
listener: (
message: any,
handle: net.Socket | net.Server,
) => void,
): this addListener(
event: "online",
listener: () => void,
): this destroy(signal?: string): void disconnect(): void В рабочем процессе эта функция закроет все серверы, дождется события 'close' на этих серверах, а затем отключит канал IPC.
В главном процессе рабочему процессу отправляется внутреннее сообщение, в результате чего он вызывает .disconnect() для самого себя.
В результате свойству .exitedAfterDisconnect присваивается значение.
После закрытия сервера он больше не будет принимать новые подключения, однако их могут принимать другие рабочие процессы, прослушивающие порт. Существующим подключениям будет разрешено закрыться обычным образом. Когда подключений больше не останется, см. server.close(), канал IPC к рабочему процессу закроется, что позволит ему корректно завершить работу.
Описанное выше относится только к подключениям сервера; клиентские подключения не закрываются рабочими процессами автоматически, а disconnect не дожидается их закрытия перед завершением работы.
В рабочем процессе process.disconnect существует, но это не данная функция, а disconnect().
Поскольку долгоживущие подключения сервера могут препятствовать отключению рабочих процессов, может быть полезно отправить сообщение, чтобы приложение могло выполнить необходимые действия для их закрытия. Также может быть полезно реализовать тайм-аут, завершающий рабочий процесс, если по истечении некоторого времени событие 'disconnect' не произошло.
import net from 'node:net';
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 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
}
});
}
emit(
event: string | symbol,
...args: any[],
): boolean emit(event: "disconnect"): boolean emit(
event: "error",
error: Error,
): boolean emit(
event: "exit",
code: number,
signal: string,
): boolean emit(
event: "message",
message: any,
handle: net.Socket | net.Server,
): boolean emit(event: "online"): boolean isConnected(): boolean Эта функция возвращает true, если рабочий процесс подключен к главному процессу через канал IPC, и false в противном случае. Рабочий процесс подключается к главному процессу после создания. Отключение происходит после генерации события 'disconnect'.
isDead(): boolean Эта функция возвращает true, если процесс рабочего процесса завершил работу (в результате выхода или получения сигнала). В противном случае она возвращает false.
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);
}
kill(signal?: string): void Эта функция завершает работу рабочего процесса. В главном процессе она делает это, отключая worker.process, а после отключения завершает процесс с помощью signal. В рабочем процессе она завершает процесс с помощью signal.
Функция kill() завершает процесс рабочего процесса, не дожидаясь корректного отключения; она работает так же, как worker.process.kill().
Для обратной совместимости этот метод имеет псевдоним worker.destroy().
В рабочем процессе process.kill() существует, но это не данная функция, а kill().
on(
event: string,
listener: (...args: any[]) => void,
): this on(
event: "disconnect",
listener: () => void,
): this on(
event: "error",
listener: (error: Error) => void,
): this on(
event: "exit",
listener: (
code: number,
signal: string,
) => void,
): this on(
event: "message",
listener: (
message: any,
handle: net.Socket | net.Server,
) => void,
): this on(
event: "online",
listener: () => void,
): this once(
event: string,
listener: (...args: any[]) => void,
): this once(
event: "disconnect",
listener: () => void,
): this once(
event: "error",
listener: (error: Error) => void,
): this once(
event: "exit",
listener: (
code: number,
signal: string,
) => void,
): this once(
event: "message",
listener: (
message: any,
handle: net.Socket | net.Server,
) => void,
): this once(
event: "online",
listener: () => void,
): this prependListener(
event: string,
listener: (...args: any[]) => void,
): this prependListener(
event: "disconnect",
listener: () => void,
): this prependListener(
event: "error",
listener: (error: Error) => void,
): this prependListener(
event: "exit",
listener: (
code: number,
signal: string,
) => void,
): this prependListener(
event: "listening",
listener: (address: Address) => void,
): this prependListener(
event: "message",
listener: (
message: any,
handle: net.Socket | net.Server,
) => void,
): this prependListener(
event: "online",
listener: () => void,
): this prependOnceListener(
event: string,
listener: (...args: any[]) => void,
): this prependOnceListener(
event: "disconnect",
listener: () => void,
): this prependOnceListener(
event: "error",
listener: (error: Error) => void,
): this prependOnceListener(
event: "exit",
listener: (
code: number,
signal: string,
) => void,
): this prependOnceListener(
event: "listening",
listener: (address: Address) => void,
): this prependOnceListener(
event: "message",
listener: (
message: any,
handle: net.Socket | net.Server,
) => void,
): this prependOnceListener(
event: "online",
listener: () => void,
): this send(
message: child.Serializable,
callback?: (error: Error | null) => void,
): 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);
});
}
send(
message: child.Serializable,
sendHandle: child.SendHandle,
callback?: (error: Error | null) => void,
): boolean send(
message: child.Serializable,
sendHandle: child.SendHandle,
options?: child.MessageOptions,
callback?: (error: Error | null) => void,
): boolean интерфейс Address
Использование в Deno
import { type Address } from "node:cluster";
Этот символ является неработающей заглушкой.
Свойства
address: string port: number addressType:
4
| 6
| -1
| "udp4"
| "udp6"
Значение addressType может быть одним из следующих:
-
4(TCPv4) -
6(TCPv6) -
-1(сокет домена Unix) -
'udp4'или'udp6'(UDPv4 или UDPv6)
интерфейс Cluster
Использование в Deno
import { type Cluster } from "node:cluster";
Этот символ представляет собой неработающую заглушку.
Свойства
isMaster: boolean isPrimary: boolean True, если процесс является основным. Это определяется с помощью process.env.NODE_UNIQUE_ID. Если process.env.NODE_UNIQUE_ID не определено, то isPrimary имеет значение true.
isWorker: boolean True, если процесс не является основным (это противоположное значение cluster.isPrimary).
schedulingPolicy: number Политика планирования: cluster.SCHED_RR для циклического распределения или cluster.SCHED_NONE, чтобы передать управление операционной системе. Это глобальная настройка, которая фактически фиксируется после запуска первого рабочего процесса или вызова .setupPrimary() — в зависимости от того, что произойдёт раньше.
SCHED_RR используется по умолчанию во всех операционных системах, кроме Windows. В Windows будет выбрано SCHED_RR, когда libuv сможет эффективно распределять дескрипторы IOCP без значительного снижения производительности.
cluster.schedulingPolicy также можно задать с помощью переменной среды NODE_CLUSTER_SCHED_POLICY. Допустимые значения: 'rr' и 'none'.
settings: ClusterSettings После вызова .setupPrimary() (или .fork()) этот объект настроек будет содержать настройки, в том числе значения по умолчанию.
Этот объект не предназначен для изменения или ручной установки.
Ссылка на текущий объект рабочего процесса. Недоступно в основном процессе.
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}`);
}
Хеш, в котором хранятся активные объекты рабочих процессов, индексированные по полю id. Это позволяет легко перебрать все рабочие процессы. Доступен только в основном процессе.
Рабочий процесс удаляется из cluster.workers после отключения и завершения. Заранее определить порядок этих двух событий невозможно. Однако гарантируется, что удаление из списка cluster.workers произойдёт до отправки последнего события 'disconnect' или 'exit'.
import cluster from 'node:cluster';
for (const worker of Object.values(cluster.workers)) {
worker.send('big announcement to all workers');
}
SCHED_NONE: number SCHED_RR: number Методы
disconnect(callback?: () => void): void Запускает новый рабочий процесс.
Вызывать этот метод можно только из основного процесса.
setupMaster(settings?: ClusterSettings): void setupPrimary(settings?: ClusterSettings): void setupPrimary используется для изменения поведения 'fork' по умолчанию. После вызова настройки будут доступны в cluster.settings.
Изменения настроек влияют только на будущие вызовы .fork() и не влияют на уже запущенные рабочие процессы.
Единственный атрибут рабочего процесса, который нельзя задать с помощью .setupPrimary(), — это env, передаваемый в .fork().
Указанные выше значения по умолчанию применяются только при первом вызове; при последующих вызовах значениями по умолчанию будут текущие значения на момент вызова cluster.setupPrimary().
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 worker
Вызывать этот метод можно только из основного процесса.
addListener(
event: string,
listener: (...args: any[]) => void,
): this events.EventEmitter
- disconnect
- exit
- fork
- listening
- message
- online
- setup
addListener(
event: "disconnect",
listener: (worker: Worker) => void,
): this addListener(
event: "exit",
listener: () => void,
): this addListener(
event: "fork",
listener: (worker: Worker) => void,
): this addListener(): this addListener(
event: "message",
listener: () => void,
): this addListener(
event: "online",
listener: (worker: Worker) => void,
): this addListener(
event: "setup",
listener: (settings: ClusterSettings) => void,
): this emit(
event: string | symbol,
...args: any[],
): boolean emit(
event: "setup",
settings: ClusterSettings,
): boolean on(
event: string,
listener: (...args: any[]) => void,
): this on(
event: "setup",
listener: (settings: ClusterSettings) => void,
): this once(
event: string,
listener: (...args: any[]) => void,
): this once(
event: "setup",
listener: (settings: ClusterSettings) => void,
): this prependListener(
event: string,
listener: (...args: any[]) => void,
): this prependListener(
event: "disconnect",
listener: (worker: Worker) => void,
): this prependListener(
event: "exit",
listener: () => void,
): this prependListener(
event: "fork",
listener: (worker: Worker) => void,
): this prependListener(): this prependListener(
event: "message",
listener: () => void,
): this prependListener(
event: "online",
listener: (worker: Worker) => void,
): this prependListener(
event: "setup",
listener: (settings: ClusterSettings) => void,
): this prependOnceListener(
event: string,
listener: (...args: any[]) => void,
): this prependOnceListener(
event: "disconnect",
listener: (worker: Worker) => void,
): this prependOnceListener(
event: "exit",
listener: () => void,
): this prependOnceListener(
event: "fork",
listener: (worker: Worker) => void,
): this prependOnceListener(): this prependOnceListener(
event: "message",
listener: () => void,
): this prependOnceListener(
event: "online",
listener: (worker: Worker) => void,
): this prependOnceListener(
event: "setup",
listener: (settings: ClusterSettings) => void,
): this интерфейс ClusterSettings
Использование в Deno
import { type ClusterSettings } from "node:cluster";
Этот символ представляет собой неработающую заглушку.
Свойства
execArgv: string[] | undefined Список строковых аргументов, передаваемых исполняемому файлу Node.js.
exec: string | undefined Путь к файлу рабочего процесса.
args: string[] | undefined Строковые аргументы, передаваемые рабочему процессу.
silent: boolean | undefined Определяет, следует ли отправлять вывод в стандартные потоки ввода-вывода родительского процесса.
stdio: any[] | undefined Настраивает стандартные потоки ввода-вывода разветвлённых процессов. Поскольку для работы модуля cluster требуется IPC, эта настройка должна содержать запись 'ipc'. Если задан этот параметр, он переопределяет silent. См. раздел child_prcess.spawn() stdio.
inspectPort:
number
| (() => number)
| undefined
Задаёт порт инспектора рабочего процесса. Значением может быть число или функция без аргументов, возвращающая число. По умолчанию каждый рабочий процесс получает собственный порт, увеличиваемый относительно process.debugPort основного процесса.
serialization: SerializationType | undefined Задаёт тип сериализации, используемой для отправки сообщений между процессами. Возможные значения: 'json' и 'advanced'. Подробнее см. раздел Расширенная сериализация для child_process.
cwd: string | undefined Текущий рабочий каталог рабочего процесса.
windowsHide: boolean | undefined Скрывает окно консоли разветвлённых процессов, которое обычно создаётся в Windows.
псевдоним типа SerializationType
Использование в Deno
import { type SerializationType } from "node:cluster";
Этот символ представляет собой неработающую заглушку.
Определение
"json" | "advanced"
© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/api/node/cluster