ZeroMQ 在 context.term() 调用中阻塞。为什么?如何预防?
ZeroMQ blocked in a context.term() call. Why? How to prevent?
我有一个使用 ZeroMQ 的 java 程序。
但我发现程序在 context.term();
中被阻止,如果接收到 message( recvMsg() )
超时!
ZMQ.Context context = ZMQ.context(1);
ZMQ.Socket socket = context.socket(ZMQ.REQ);
socket.connect(mAddress);
ZMsg ZM = new ZMsg();
ZM.add(qString);
ZM.send(socket, true);
socket.setReceiveTimeOut(mTimeout);
ZMsg receivedZM = ZMsg.recvMsg(socket);
if(receivedZM != null) {
System.out.println(receivedZM.getFirst().toString());
}
socket.close();
context.term();
阻塞是什么原因?
以及如何解决这个问题?
根据API,http://api.zeromq.org/4-2:zmq-term,当还有消息要传输时,它会阻塞。这表明您是其他机器或进程,将打开 REP 套接字的那个;不是 运行.
ZeroMQ 是一个在 Context()
-factory
背后使用许多技巧的系统
我一直提倡在 Socket 实例化时自动设置 .setsockopt( ZMQ_LINGER, 0 )
,正是由于这些类型的行为,否则将保留在您的本地代码之外控制域。一个挂起的 Context
-instance IO-thread(s)(尽管所有 socket
-instances 尚未成功 .close()
,但已发出编程的 .term()
, 在这个 Context
实例下实例化 .term()
是为了拆除并释放所有系统资源,或者是一个未处理的异常情况,当事情直接发生破坏时)是这样的一种 - s.
请随意遵循教科书和在线 hacks/snippet 示例,但认真的分布式系统设计人员应该采取所有合理的步骤和措施,以防止 her/his 系统代码陷入任何死锁状态(少成不可救药)。
这是什么原因?
如文档所述 - 它是 ZeroMQ 的内置功能:
attempting to terminate the socket's context with zmq_ctx_term()
shall block until all pending messages have been sent to a peer.
任何情况下,.send()
-已分派(刚刚分派——绝不意味着它已经被发送到电汇)消息仍在本地队列中以供任何已识别的(并且可能断开连接或忙碌或...)对等节点,刚刚默认配置的 .term()
无法继续并将阻塞。
解决方法是什么:
较新的 API 版本开始说,默认的 LINGER
值不再是 -1 == INFINITY
,但你永远不知道,哪个版本将与您的代码交互,对 .setsockopt( ZMQ_LINGER, 0 )
方法的显式(手动)调用是一个自律步骤,可以提高您的团队对如何构建可靠的分布式系统代码的认识。
使用try: / except: / finally:
syntax-handlers 这里就不用提了。您只是在设计时始终要考虑到故障和碰撞,不是吗?
我有一个使用 ZeroMQ 的 java 程序。
但我发现程序在 context.term();
中被阻止,如果接收到 message( recvMsg() )
超时!
ZMQ.Context context = ZMQ.context(1);
ZMQ.Socket socket = context.socket(ZMQ.REQ);
socket.connect(mAddress);
ZMsg ZM = new ZMsg();
ZM.add(qString);
ZM.send(socket, true);
socket.setReceiveTimeOut(mTimeout);
ZMsg receivedZM = ZMsg.recvMsg(socket);
if(receivedZM != null) {
System.out.println(receivedZM.getFirst().toString());
}
socket.close();
context.term();
阻塞是什么原因?
以及如何解决这个问题?
根据API,http://api.zeromq.org/4-2:zmq-term,当还有消息要传输时,它会阻塞。这表明您是其他机器或进程,将打开 REP 套接字的那个;不是 运行.
ZeroMQ 是一个在 Context()
-factory
背后使用许多技巧的系统
我一直提倡在 Socket 实例化时自动设置 .setsockopt( ZMQ_LINGER, 0 )
,正是由于这些类型的行为,否则将保留在您的本地代码之外控制域。一个挂起的 Context
-instance IO-thread(s)(尽管所有 socket
-instances 尚未成功 .close()
,但已发出编程的 .term()
, 在这个 Context
实例下实例化 .term()
是为了拆除并释放所有系统资源,或者是一个未处理的异常情况,当事情直接发生破坏时)是这样的一种 - s.
请随意遵循教科书和在线 hacks/snippet 示例,但认真的分布式系统设计人员应该采取所有合理的步骤和措施,以防止 her/his 系统代码陷入任何死锁状态(少成不可救药)。
这是什么原因?
如文档所述 - 它是 ZeroMQ 的内置功能:
attempting to terminate the socket's context with
zmq_ctx_term()
shall block until all pending messages have been sent to a peer.
任何情况下,.send()
-已分派(刚刚分派——绝不意味着它已经被发送到电汇)消息仍在本地队列中以供任何已识别的(并且可能断开连接或忙碌或...)对等节点,刚刚默认配置的 .term()
无法继续并将阻塞。
解决方法是什么:
较新的 API 版本开始说,默认的 LINGER
值不再是 -1 == INFINITY
,但你永远不知道,哪个版本将与您的代码交互,对 .setsockopt( ZMQ_LINGER, 0 )
方法的显式(手动)调用是一个自律步骤,可以提高您的团队对如何构建可靠的分布式系统代码的认识。
使用try: / except: / finally:
syntax-handlers 这里就不用提了。您只是在设计时始终要考虑到故障和碰撞,不是吗?