Spec-Zone.ru › Deno 2

cluster

Совместимость с Deno

Все экспорты являются неработающими заглушками.

Кластеры процессов 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

наследует EventEmitter

Использование в Deno

import { Worker } from "node:cluster";
Совместимость с Deno

Этот символ является неработающей заглушкой.

Объект 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

  1. disconnect
  2. error
  3. exit
  4. listening
  5. message
  6. 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: "listening",
address: Address,
): 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: "listening",
listener: (address: Address) => 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: "listening",
listener: (address: Address) => 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";
Совместимость с Deno

Этот символ является неработающей заглушкой.

Свойства

address: string
port: number
addressType:
4
| 6
| -1
| "udp4"
| "udp6"

Значение addressType может быть одним из следующих:

  • 4 (TCPv4)
  • 6 (TCPv6)
  • -1 (сокет домена Unix)
  • 'udp4' или 'udp6' (UDPv4 или UDPv6)

интерфейс Cluster

расширяет EventEmitter

Использование в Deno

import { type Cluster } from "node:cluster";
Совместимость с Deno

Этот символ представляет собой неработающую заглушку.

Свойства

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()) этот объект настроек будет содержать настройки, в том числе значения по умолчанию.

Этот объект не предназначен для изменения или ручной установки.

worker: Worker | undefined
только для чтения
необязательный

Ссылка на текущий объект рабочего процесса. Недоступно в основном процессе.

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}`);
}
workers: Dict<Worker> | undefined
только для чтения
необязательный

Хеш, в котором хранятся активные объекты рабочих процессов, индексированные по полю 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
fork(env?: any): Worker

Запускает новый рабочий процесс.

Вызывать этот метод можно только из основного процесса.

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

  1. disconnect
  2. exit
  3. fork
  4. listening
  5. message
  6. online
  7. setup
addListener(
event: "disconnect",
listener: (worker: Worker) => void,
): this
addListener(
event: "exit",
listener: (
worker: Worker,
code: number,
signal: string,
) => void
,
): this
addListener(
event: "fork",
listener: (worker: Worker) => void,
): this
addListener(
event: "listening",
listener: (
worker: Worker,
address: Address,
) => void
,
): this
addListener(
event: "message",
listener: (
worker: Worker,
message: any,
handle: net.Socket | net.Server,
) => 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: "disconnect",
worker: Worker,
): boolean
emit(
event: "exit",
worker: Worker,
code: number,
signal: string,
): boolean
emit(
event: "fork",
worker: Worker,
): boolean
emit(
event: "listening",
worker: Worker,
address: Address,
): boolean
emit(
event: "message",
worker: Worker,
message: any,
handle: net.Socket | net.Server,
): boolean
emit(
event: "online",
worker: Worker,
): boolean
emit(
event: "setup",
settings: ClusterSettings,
): boolean
on(
event: string,
listener: (...args: any[]) => void,
): this
on(
event: "disconnect",
listener: (worker: Worker) => void,
): this
on(
event: "exit",
listener: (
worker: Worker,
code: number,
signal: string,
) => void
,
): this
on(
event: "fork",
listener: (worker: Worker) => void,
): this
on(
event: "listening",
listener: (
worker: Worker,
address: Address,
) => void
,
): this
on(
event: "message",
listener: (
worker: Worker,
message: any,
handle: net.Socket | net.Server,
) => void
,
): this
on(
event: "online",
listener: (worker: Worker) => void,
): this
on(
event: "setup",
listener: (settings: ClusterSettings) => void,
): this
once(
event: string,
listener: (...args: any[]) => void,
): this
once(
event: "disconnect",
listener: (worker: Worker) => void,
): this
once(
event: "exit",
listener: (
worker: Worker,
code: number,
signal: string,
) => void
,
): this
once(
event: "fork",
listener: (worker: Worker) => void,
): this
once(
event: "listening",
listener: (
worker: Worker,
address: Address,
) => void
,
): this
once(
event: "message",
listener: (
worker: Worker,
message: any,
handle: net.Socket | net.Server,
) => void
,
): this
once(
event: "online",
listener: (worker: Worker) => 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: (
worker: Worker,
code: number,
signal: string,
) => void
,
): this
prependListener(
event: "fork",
listener: (worker: Worker) => void,
): this
prependListener(
event: "listening",
listener: (
worker: Worker,
address: Address,
) => void
,
): this
prependListener(
event: "message",
listener: (
worker: Worker,
message: any,
handle?: net.Socket | net.Server,
) => 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: (
worker: Worker,
code: number,
signal: string,
) => void
,
): this
prependOnceListener(
event: "fork",
listener: (worker: Worker) => void,
): this
prependOnceListener(
event: "listening",
listener: (
worker: Worker,
address: Address,
) => void
,
): this
prependOnceListener(
event: "message",
listener: (
worker: Worker,
message: any,
handle: net.Socket | net.Server,
) => 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";
Совместимость с Deno

Этот символ представляет собой неработающую заглушку.

Свойства

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.

uid: number | undefined
необязательный

Задаёт идентификатор пользователя процесса. (См. setuid(2).)

gid: number | undefined
необязательный

Задаёт идентификатор группы процесса. (См. setgid(2).)

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";
Совместимость с Deno

Этот символ представляет собой неработающую заглушку.

Определение

"json" | "advanced"

переменная cluster

Использование в Deno

import { cluster } from "node:cluster";

Тип

Cluster

переменная default

Использование в Deno

import mod from "node:cluster";

Тип

Cluster

© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/api/node/cluster

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API