我有一个使用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();
导致它被阻止的原因是什么?
如何解决这个问题?
答案 0 :(得分:3)
Context()
- factory 我总是提倡在Socket实例化时自动设置 .setsockopt( ZMQ_LINGER, 0 )
,这是由于这些类型的行为,否则它们将保留在本地代码控制域之外。悬挂Context
- 实例IO线程(尽管尚未成功.term()
所有.close()
实例,但已经发布了编程socket
- 实例,在Context
实例化 - 实例.term()
将要拆除并释放所有系统资源,或者未处理的异常情况,当事情直接破坏时,残骸就是其中之一第
随意关注教科书和在线黑客/代码段示例,但是一个严肃的分布式系统设计师应该采取所有合理的步骤和措施,以防止她/他的系统代码陷入任何死锁状态(更少进入联合国 - 可挽救的)。
正如文档所述 - 它是ZeroMQ的一个设计功能:
尝试使用
zmq_ctx_term()
终止套接字的上下文将阻塞,直到所有未决消息都已发送给对等方。
任何情况下,.send()
- 调度(仅调度 - 绝不意味着它已经被发送到线路)消息仍然在本地队列中用于任何已识别的消息(和可能断开连接或忙或...)对等节点,刚刚默认配置的.term()
无法继续并将阻止。
较新的API版本开始说,默认LINGER
值不再是 -1 == INFINITY
,但你不知道,你的代码将与哪个版本接口,一个明确的(手动)调用.setsockopt( ZMQ_LINGER, 0 )
方法是一个自律的步骤,可以提高团队对如何构建可靠的分布式系统代码的认识。
在这里不必提出使用try: / except: / finally:
语法处理程序。你只需要设计失败和安全;记住碰撞,不是吗?
答案 1 :(得分:0)
根据API http://api.zeromq.org/4-2:zmq-term,当仍有消息要传输时,它会阻止。这表明你的其他机器或进程,将打开REP套接字;没有跑。