IPC — взаимодействие процессов в Node.js
Несколько Node-процессов общаются через
child_process.forkIPC-канал, сокеты или общую очередь. В пределах одной машины — 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 между песочницами в одном процессе