Java ZeroMQ在context.term()调用中被阻止。为什么?如何预防?
我有一个使用ZeroMQ的java程序 但是我发现程序在Java ZeroMQ在context.term()调用中被阻止。为什么?如何预防?,java,zeromq,Java,Zeromq,我有一个使用ZeroMQ的java程序 但是我发现程序在context.term()中被阻塞如果收到消息(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);
context.term()中被阻塞代码>如果收到消息(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,当仍有消息要传输时,它会阻塞。这表明您需要其他机器或进程,即打开REP套接字的机器或进程;没有运行。ZeroMQ是一个在Context()
-factory()后面使用许多技巧的系统
我一直主张在套接字实例化时自动设置.setsockopt(ZMQ_LINGER,0)
,这是由于这些类型的行为,否则这些行为将超出本地代码控制范围。挂起的Context
-实例IO线程(可能是在已编程的.term()
发出后,尽管所有socket
-实例的.close()
尚未成功,在此Context
-实例下实例化.term())
是指从系统中拆除并释放所有的系统资源,或者是当事情进展顺利时,一个未经处理的异常情况(灾难性破坏)就是其中一个
请随意阅读教科书和在线黑客/代码片段示例,但是一个认真的分布式系统设计师应该采取所有合理的步骤和措施,以防止她/他的系统代码陷入任何死锁状态(更少的死锁状态)
原因是什么?
正如文档所述,它是ZeroMQ的一个设计特性:
尝试使用zmq\u ctx\u term()
终止套接字的上下文将被阻止,直到所有挂起的消息都已发送到对等方
在任何情况下,如果.send()
-dispatched(刚刚调度——绝不意味着它已经被发送到wire)消息仍然位于任何已识别(并且可能已断开连接或忙碌或…)对等节点的本地队列中,则刚刚默认配置的.term()
无法继续并将被阻止
解决方案是什么:
较新的API版本开始说,默认的LINGER
值将不再是-1==INFINITY
,但您永远不知道,您的代码将与哪个版本交互,显式(手动)调用.setsockopt(ZMQ_LINGER,0)
方法是一个自律的步骤,可以提高团队对如何构建可靠的分布式系统代码的认识
这里不需要提出使用try:/except:/finally:
语法处理程序。你总是要在设计时考虑到失败和冲突,不是吗?谢谢~但我还是不明白。由于recvMsg()已超时(否则程序仍将在recvMsg()处阻塞),因此应该没有要传输的消息。由于“context”对象是在程序中创建的,它会受到其他进程或机器的影响吗?使用zmq api,您必须在关闭context之前关闭所有套接字(至少是在调用zmq_term的线程中创建的)。可以实现跟踪上下文对象中的所有套接字并自动关闭它们。但我不知道它是在pyzmq中实现的。将LINGER设置为0是一个很好的主意。我要自己动手了。这是一个前所未有的富于说服力的回答,太好了。一个主意;)???我宁愿称之为必经之路,一件真正的救生衣。在我的所有工作中,实际上一些绑定已经默认做到了(据我所知,CZMQ和NetMQ)是的,somdoron,最新的API已经改变了初始默认值-1,但是任何专业分布式系统设计师的思维实践都应该是防御性的,以便强制执行它,而不考虑(目前可能暂时更友好一些)默认设置,以避免在代码没有使用匹配的API版本运行时出现死锁。这听起来是合法的,不是吗?绑定本身是绝对不确定的,因为这些绑定如何真正开始反映最新的API更改。绑定/包装设计的黑盒部分在接口爬行后出现了许多问题。它非常有帮助!谢谢!但是,在Java绑定中似乎没有像setsockopt()这样的对应函数。有没有其他方法可以解决这个问题?