【发布时间】:2019-11-25 10:08:21
【问题描述】:
考虑一个具有少量进程的 Node.js 应用程序:
- 位于内存中并像 Web 服务器一样工作的单个主进程;
- 系统用户的命令,可以通过 CLI 运行并在完成后退出。
我想在主进程和 CLI 进程之间实现类似 IPC 的东西,似乎 ZeroMQ bindings for Node.js 是一个非常好的候选者。我选择了6.0.0-beta.4 版本:
6.0.0 版(测试版)具有全新的 API,可解决许多基本问题,建议用于新项目。
使用Request/Reply 我能够实现我想要的:CLI 进程通知主进程一些发生的事件(并可选择接收一些数据作为响应)并继续执行。我现在遇到的一个问题是,如果主进程关闭(不可用),我的 CLI 进程就会挂起。如果无法建立到套接字的连接,该命令仍然必须执行并退出,而不通知主进程。
这是我的 CLI 以异步方法运行的简化代码 sn-p:
const { Request } = require('zeromq');
async function notify() {
let parsedResponse;
try {
const message = { event: 'hello world' };
const socket = new Request({ connectTimeout: 500 });
socket.connect('tcp://127.0.0.1:33332');
await socket.send(JSON.stringify(message));
const response = await socket.receive();
parsedResponse = JSON.parse(response.toString());
}
catch (e) {
console.error(e);
}
return parsedResponse;
}
(async() => {
const response = await notify();
if (response) {
console.log(response);
}
else {
console.log('Nothing is received.');
}
})();
我设置了connectTimeout 选项,但不知道如何使用它。文档状态:
设置在connect()系统调用超时之前等待多长时间。 connect() 系统调用通常需要很长时间才能返回超时错误。设置此选项允许库以更早的时间间隔使调用超时。
查看connect 一看就知道它不是异步的:
连接到给定远程地址的套接字并立即返回。连接将在后台异步进行。
好的,可能send 套接字的方法将等待连接建立并拒绝连接超时的承诺......但那里没有任何反应。 send 方法被执行并且代码停留在解析receive。它正在等待来自永远不会到来的主进程的回复。所以主要问题是:“如何使用connectTimeout 选项来处理套接字的连接超时?” 我发现an answer 与C++ 相关的类似问题,但它实际上并没有回答这个问题(或我无法理解)。不敢相信这个选项没用,而且它被添加到 API 中是为了让任何人都无法使用它。
我也会对某种解决方法感到满意,并找到了receiveTimeout 选项。将套接字创建更改为
const socket = new Request({ receiveTimeout: 500 });
导致receive 方法中的拒绝和以下输出:
{ [Error: Socket temporarily unavailable] errno: 11, code: 'EAGAIN' }
Nothing is received.
执行了源代码,但在这种情况下进程没有退出。似乎有些资源很忙,没有被释放。当主进程上线时,一切正常,进程退出,我在输出中有以下回复:
{ status: 'success' }
所以另一个问题是:“如何在拒绝receive 方法和receiveTimeout 时优雅地退出进程?”。在这里打电话process.exit() 不是一个选项!
附:我的环境是:
- 库本图 18.04.1;
- 节点 10.15.0;
-
ZeroMQ 绑定以这种方式安装:
$ yarn add zeromq@6.0.0-beta.4 --zmq-shared
【问题讨论】: