【发布时间】:2017-05-07 20:19:19
【问题描述】:
场景
我有多个 NodeJS 脚本在 Ubuntu 操作系统中以永久模式运行。其中一个文件 (start.js) 导入一个文件,该文件通过将 ZMQ 发布者绑定到指定端口来启动它。当我以永久模式单独启动这个 start.js 文件时,它会绑定并启动发布者,并且我能够通过连接到该端口的 ZMQ 订阅者获取该发布者发布的数据。
我正在通过检查退出、SIGINT 和 SIGUSR 事件来优雅地关闭发布者。
每当我使用forever restart 单独重新启动这个 start.js 文件时,发布者就会绑定并成功启动。如果我手动停止它(使用forever stop)并使用forever start重新启动它,它也可以正常工作[也适用于我手动停止(使用forever stopall)并一一启动所有永久脚本的情况]。
注意:所有永久停止和重新启动命令都使用 CLI 选项 --killSignal=SIGINT 运行。
问题
但是当我执行forever restartall --killSignal=SIGINT 时,发布者无法绑定。它说该地址已经在使用中(我已经使用netstat 进行了检查,并且该端口上没有 tcp 套接字)。当我停止所有脚本并一一启动它们时,它会正常绑定并成功启动。
我检查了这些终止信号是否被发布者脚本捕获并在退出之前关闭发布者套接字。
尝试失败:
降低了 tcp 套接字的 TIME_WAIT 状态。
启用 TIME_WAIT 套接字的重用。
我认为 tcp 套接字需要时间才能从 TIME_WAIT状态,1000ms后尝试绑定发布者 每次绑定失败,但脚本正在尝试绑定并失败 每次尝试。
尝试使用 SIGINT、SIGUSR1 kill 永久重启所有脚本 信号并在绑定发布者的脚本中处理它们 插座。
这就是我在发布者中处理 SIG* 事件的方式:
process.stdin.resume();
function exitHandler(options, err){
if (options.cleanup) console.log('pub-clean');
if (err) console.log("pub--" + err.stack);
if (options.exit){
socket.close();
console.log("Publisher Closed")
process.exit();
}
}
process.on('exit', exitHandler.bind(null,{cleanup:true}));
process.on('SIGINT', exitHandler.bind(null, {exit:true}));
process.on('uncaughtException', exitHandler.bind(null,{exit:true}));
process.on('SIGUSR2', exitHandler.bind(null, {exit:true}));
process.on('SIGTERM', exitHandler.bind(null, {exit:true}));
为什么永远重启所有脚本会导致发布者脚本绑定失败?
如何使发布者脚本在永远重启时绑定?
【问题讨论】:
-
您如何在代码中实现
SIG*-s 处理程序以优雅地关闭/终止/退出所有 ZeroMQ 资源和上下文? -
@user3666197 >> 我已经包含了用于处理上述 SIG* 事件的 code-sn-p。
-
好吧,正如所见,您的
SIG*-handlers 代码在正常关闭/终止 ZeroMQ 资源方面没有任何作用。您能否在 ZeroMQ 初始化的设置部分发布您的代码? -
@user3666197 > 为什么 SIG* 处理程序的代码什么都不做?如果没有此代码,当进程收到 SIGINT 或 SIGTERM 或退出信号时,它不会关闭套接字。
-
恕我直言,ZeroMQ 资源的优雅释放不是通过系统级 SIG* / *KILL 完成,而是通过执行 ZeroMQ-优雅的释放步骤。正如到目前为止所发布的,您在代码中根本没有这样做,因此 ZeroMQ 资源可能而且很可能仍然挂起(至少 I/O 线程似乎如此)。
标签: node.js sockets zeromq forever