javascript — принудительный синхронный IPC Node.js

Принудительная синхронизация Node.js IPC

У меня есть Node-сервер, который создает дочерний процесс с помощью fork() с использованием IPC. В какой-то момент ребенок отправляет результаты родителю на частоте около 10 Гц как часть длительной задачи. Когда полезная нагрузка, передаваемая в process.send() , мала, все работает хорошо: каждое отправляемое мной сообщение немедленно принимается и обрабатывается родителем.

Однако, когда полезная нагрузка является «большой» — я не определил точный предел размера — вместо того, чтобы быть немедленно полученным родителем, все полезные нагрузки сначала отправляются, и только после того, как дочерний элемент выполнен, его длительная задача получает родительский элемент и обрабатывать сообщения.

tl; dr visual:

Хорошо (бывает с малой полезной нагрузкой):

 child: send() parent: receive() child: send() parent: receive() child: send() parent: receive() ... 

Плохо (бывает с большой полезной нагрузкой):

 child: send() child: send() child: send() (repeat many times over many seconds) ... parent: receive() parent: receive() parent: receive() parent: receive() ... 
  1. Это ошибка? (Изменить: поведение происходит только в OS X, а не в Windows или Linux)
  2. Есть ли способ избежать этого, кроме попыток сохранить полезную нагрузку IPC небольшой?

Редактировать 2 : приведенный ниже пример кода использует время и счетчик итераций для выбора времени отправки обновления. (В моем реальном коде также возможно отправить обновление после n итераций или после того, как цикл достигнет определенных результатов.) Так как переписывание кода для использования setInterval / setTimeout вместо цикла является для меня последним средством, так как требует от меня, чтобы удалить функции.

Изменить : Вот тестовый код, который воспроизводит проблему. Однако он воспроизводится только в OS X, а не в Windows или Linux:

server.js

 const opts = {stdio:['inherit', 'inherit', 'inherit', 'ipc']}; const child = require('child_process').fork('worker.js', [], opts); child.on('message', msg ={amp}gt; console.log(`parent: receive() ${msg.data.length} bytes`, Date.now())); require('http').createServer((req, res) ={amp}gt; { console.log(req.url); const match = /d /.exec(req.url); if (match) { child.send(match[0]*1); res.writeHead(200, {'Content-Type':'text/plain'}); res.end(`Sending packets of size ${match[0]}`); } else { res.writeHead(404, {'Content-Type':'text/plain'}); res.end('what?'); } }).listen(8080); 

worker.js

 if (process.send) process.on('message', msg ={amp}gt; run(msg)); function run(messageSize) { const msg = new Array(messageSize 1).join('x'); let lastUpdate = Date.now(); for (let i=0; i{amp}lt;1e7;   i) { const now = Date.now(); if ((now-lastUpdate){amp}gt;200 || iP00==0) { console.log(`worker: send() {amp}gt; ${messageSize} bytes`, now); process.send({action:'update', data:msg}); lastUpdate = Date.now(); } Math.sqrt(Math.random()); } console.log('worker done'); } 

Около 8к проблема возникает. Например, при запросе http://localhost:8080/15 против http://localhost:8080/123456

 /15 worker: send() {amp}gt; 15 bytes 1571324249029 parent: receive() 15 bytes 1571324249034 worker: send() {amp}gt; 15 bytes 1571324249235 parent: receive() 15 bytes 1571324249235 worker: send() {amp}gt; 15 bytes 1571324249436 parent: receive() 15 bytes 1571324249436 worker done /123456 worker: send() {amp}gt; 123456 bytes 1571324276973 worker: send() {amp}gt; 123456 bytes 1571324277174 worker: send() {amp}gt; 123456 bytes 1571324277375 child done parent: receive() 123456 bytes 1571324277391 parent: receive() 123456 bytes 1571324277391 parent: receive() 123456 bytes 1571324277393 

Опытный как на Node v12.7, так и на 12.12.

Понравилась статья? Поделиться с друзьями:
JavaScript & TypeScript
Adblock
detector