IPC — взаимодействие процессов в Node.js

Несколько Node-процессов общаются через child_process.fork IPC-канал, сокеты или общую очередь. В пределах одной машины — IPC через pipe (быстрее сокетов), между машинами — сокеты/HTTP/брокер.

Способы IPC

1. fork + IPC канал

// parent.js
const { fork } = require('child_process');
const worker = fork('./worker.js');

worker.on('message', (msg) => console.log('From worker:', msg));
worker.send({ type: 'job', payload: [1, 2, 3] });

// worker.js
process.on('message', (msg) => {
  const result = process({ ...msg });
  process.send({ type: 'done', result });
});

Сериализация через JSON.stringify (или advanced опция для structuredClone). Лимит: одна машина.

2. Unix domain socket / Named pipe

const net = require('net');
// Unix: '/tmp/app.sock', Windows: '\\\\.\\pipe\\app'
const server = net.createServer(socket => { /* ... */ });
server.listen('/tmp/app.sock');

Быстрее TCP, не требует сетевого стека. Только локально.

3. TCP/HTTP сокеты

Универсально, но overhead на сериализацию + сетевой стек. Подходит для микросервисов.

4. Брокер очередей (Redis, RabbitMQ, NATS)

Развязывает producer и consumer. Сообщения переживают рестарт. Стандарт для микросервисов и фоновых задач.

5. SharedArrayBuffer + Atomics

Между worker_threads — общая память без сериализации, но требует ручной синхронизации через Atomics.

Пример: cluster master ↔ workers

const cluster = require('cluster');

if (cluster.isPrimary) {
  for (let i = 0; i < 4; i++) {
    const w = cluster.fork;
    w.on('message', (m) => console.log(`Worker ${w.id}:`, m));
  }
  // Broadcast
  for (const id in cluster.workers) {
    cluster.workers[id].send({ type: 'reload-config' });
  }
} else {
  process.on('message', (m) => {
    if (m.type === 'reload-config') reloadConfig;
  });
  process.send({ status: 'ready' });
}

Подводные камни

  • Большие payload в IPC канале — сериализация в JSON блокирует event loop. Для бинарных данных используй serialization: 'advanced' или общую память
  • JSON теряет типы: Date, Map, Set десериализуются как строки/объекты
  • Порядок сообщений сохраняется в одном канале, но между разными воркерами — нет
  • Зависший worker не получает сообщений — таймауты + healthcheck обязательны
  • Не использовать IPC как замену общей памяти — для частого обмена большим объёмом данных IPC становится узким местом

🎓 Источники

  • 🎓 [Межпроцессовое взаимодействие в Node.js] · 2018-10-16 · YouTube · [Marp](../../../Documents/TimurShemsedinov/2018-10-16 — Межпроцессовое взаимодействие в Node.js (2OXWZFMvfbc).md)
    • Тезисы: fork + IPC канал, рассылка сообщений всем воркерам, передача дескриптора сокета между процессами, master распределяет соединения
  • 🎓 [Песочницы, IoC, DI, IPC (Летняя школа 2017)] · 2019-11-30 · YouTube
    • Тезисы: IPC через общий setTimeout/EventEmitter между песочницами в одном процессе

См. также