ZeroMQ发布者在永远重启之后没有绑定

时间:2014-11-12 18:18:21

标签: node.js sockets zeromq forever

方案

我在Ubuntu OS中有永久模式运行的多个NodeJS脚本。其中一个文件( start.js )通过将其绑定到指定端口来导入启动ZMQ发布者的文件。当我分别以永久模式启动此 start.js 文件时,它会绑定并启动发布者,并且我能够通过连接到此端口的ZMQ订阅者获取此发布者发布的数据。 / p>

我通过检查exit,SIGINT和SIGUSR事件来优雅地关闭发布者。

每当我使用forever restart单独重新启动此 start.js 文件时,发布者就会成功绑定并启动。如果我手动停止它(使用forever stop)并使用forever start再次启动它也可以正常工作[也适用于我手动停止的情况(使用forever stopall)并永远启动它脚本一个接一个]。

注意:所有永久停止和重启命令都使用CLI选项运行--killSignal = SIGINT。

问题

但是当我forever restartall --killSignal=SIGINT时,发布者未能绑定。它说该地址已被使用(我已使用netstat检查了该地址,并且该端口没有tcp套接字)。当我停止所有脚本并逐个启动它时,它会正常绑定并成功启动。

我已经检查过这些kill信号是由发布者脚本捕获的,并在退出之前关闭了发布者套接字。

尝试失败:

  • 降低了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}));

为什么永远重启所有脚本导致发布者脚本无法绑定?

可以做些什么来使发布商脚本永远重新启动时绑定?

1 个答案:

答案 0 :(得分:0)

建议以受控方式释放ZeroMQ资源

正如上面的评论中所讨论的,ZeroMQ资源的真正优雅版本通过系统级 SIG* 完成/ *KILL ,但执行ZeroMQ建议的优雅释放步骤。

到目前为止发布时,你在代码中根本不这样做,因此ZeroMQ资源可能并且很可能仍然悬而未决(至少I / O线程似乎)。

检查(尚未发布)设置中使用的ZeroMQ套接字设置(设置阶段使用的 .setsockopt() 调用)并添加:

  1. 确保设置所有套接字设置的非阻塞 .close() (无论是否使用)
  2. 然后只有在[ 1 ]确定并且有效后才能执行 .close()
  3. 最后,执行显式ZeroMQ Context 实例 .term()
  4. 这被认为是所有(内部处理的)资源的保证ZeroMQ优雅释放。



    在示例代码请求中:​​

    优雅的释放

    void  msLIB.deinit() {
          aComment.ADD( "msLIB.INFO: msLIB.deinit() TracePOINT.<BoPROC>|", False );
    
       // --------------------------------------------------------------------------------------<THANKS>
       // DO NOT EDIT: the below  IS TRULY NEEDED or else one might get some nice memory leaks!
       // ------------            |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||   
    
    
       // -----------------------------------------------------------------------
       // ZMQ-IMPERATIVE ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
       // _______________________________________________________________________ msMOD: ZMQ_Safe&CleanCODE_IMPERATIVE
          zmq_setsockopt(   zmqSpeaker,  ZMQ_LINGER, 0 );                         // no Sending QUEUE .... on ZMQ_PUBLISHER end
          zmq_close(        zmqSpeaker  );                                        // Protect against memory leaks on shutdown.
                            aComment.ADD( "<1>", False );
                            aComment.ADD( " [[[ZMQ]]]<speaker_socket>.set( ZMQ_LINGER ) / .close()-ed ", True );
    
          zmq_setsockopt(   zmqListener, ZMQ_LINGER, 0 );                         // aKBD.PUB 
          zmq_close(        zmqListener );                                        // Protect against memory leaks on shutdown.
                            aComment.ADD( "<2>", False );
                            aComment.ADD( " [[[ZMQ]]]<listener_socket>.set( ZMQ_LINGER ) / .close()-ed ", True );      
    
          zmq_term(         zmqContext  );                                        // Protect against memory leaks on shutdown.
                            aComment.ADD( "<3>", False );
                            aComment.ADD( " [[[ZMQ]]]<context>.term()-ed ", True );
    
       // _______________________________________________________________________ msMOD: ZMQ_Safe&CleanCODE_IMPERATIVE
    
       // ------------
       // DO NOT EDIT: the above  IS TRULY NEEDED or else one might get some nice memory leaks!               
       // --------------------------------------------------------------------------------------<THANKS>
    
          aComment.ADD( "|<EoPROC>", False );
          msLIB.aSnapshot.MAKE();
          aComment.ADD( "|aSnapshot.MAKE()-<DONE>", True );
          return;
       }
    


    缺少&#34;内置&#34;对照

    可以扩展架构,以便包含一个自己的软信令代码,用于所有需要处理得更软的情况,而不是通过 SIGKILL

    a simpler case

    a more complex case