Phr*_*ogz 8 javascript ipc node.js
我有一个fork()使用IPC 创建子进程的节点服务器。在某个时候,孩子会以大约10Hz的频率将结果发送回父母,这是一项长期任务的一部分。当传递给您的有效负载process.send()很小时,它们都可以正常工作:我发送的每条消息都会立即收到并由父级处理。
但是,当有效载荷为“大”时(我尚未确定确切的大小限制),而不是立即由父级接收所有有效载荷,而是仅在子级完成其长时间运行的任务后,父级才会接收父级并处理消息。
tl; dr视觉:
良好(发生有效负载较小的情况):
child: send()
parent: receive()
child: send()
parent: receive()
child: send()
parent: receive()
...
Run Code Online (Sandbox Code Playgroud)
错误(发生有效负载的情况):
child: send()
child: send()
child: send()
(repeat many times over many seconds)
...
parent: receive()
parent: receive()
parent: receive()
parent: receive()
...
Run Code Online (Sandbox Code Playgroud)
编辑2:下面的示例代码同时使用时间和迭代计数器来选择何时发送更新。(在我的实际代码中,也可以在n次迭代之后或在循环达到某些结果之后发送更新。)这样,使用setInterval/ setTimeout而不是循环来重写代码对我来说是不得已的选择,因为这需要我删除功能。
编辑:这是重现该问题的测试代码。但是,它只能在OS X上复制,而不能在Windows或Linux上复制:
server.js
child: send()
parent: receive()
child: send()
parent: receive()
child: send()
parent: receive()
...
Run Code Online (Sandbox Code Playgroud)
worker.js
child: send()
child: send()
child: send()
(repeat many times over many seconds)
...
parent: receive()
parent: receive()
parent: receive()
parent: receive()
...
Run Code Online (Sandbox Code Playgroud)
大约在8k左右,问题就发生了。例如,查询http://localhost:8080/15vshttp://localhost:8080/123456
/15
worker: send() > 15 bytes 1571324249029
parent: receive() 15 bytes 1571324249034
worker: send() > 15 bytes 1571324249235
parent: receive() 15 bytes 1571324249235
worker: send() > 15 bytes 1571324249436
parent: receive() 15 bytes 1571324249436
worker done
/123456
worker: send() > 123456 bytes 1571324276973
worker: send() > 123456 bytes 1571324277174
worker: send() > 123456 bytes 1571324277375
child done
parent: receive() 123456 bytes 1571324277391
parent: receive() 123456 bytes 1571324277391
parent: receive() 123456 bytes 1571324277393
Run Code Online (Sandbox Code Playgroud)
在Node v12.7和v12.12上都有经验。
l 长时间运行且阻塞的 while 循环与节点中的套接字或文件描述符相结合始终表明出现了错误。
如果无法测试整个设置,很难判断我的主张是否真的正确,但短消息可能可以直接以一个块的形式传递给操作系统,然后操作系统将其传递给另一个进程。对于较大的消息,节点需要等待,直到操作系统可以接收更多数据,因此发送会排队,并且当您有阻塞时,while发送会排队直到 whileloop结束。
所以对于你的问题,这不是一个错误。
当您使用最新的nodejs版本时,我将使用 andawait而不是 and 创建一个 类似于此答案中的async非阻塞。如果返回挂起的 Promise,将允许节点事件循环拦截。whilesleepawaitprocessSome
对于没有真正反映真实用例的代码,很难说出如何正确解决它。如果您不执行任何processSome允许 I/O 拦截的异步操作,那么您需要定期手动执行await new Promise(setImmediate);此操作,例如使用.
async function run() {
let interval = setInterval(() => {
process.send({action:'update', data:status()});
console.log('child: send()');
}, 1/10)
while(keepGoing()) {
await processSome();
}
clearInterval(interval)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
244 次 |
| 最近记录: |