Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ZeroMQ在context.term()调用中被阻止。为什么?如何预防?_Java_Zeromq - Fatal编程技术网

Java ZeroMQ在context.term()调用中被阻止。为什么?如何预防?

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);

我有一个使用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);

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()这样的对应函数。有没有其他方法可以解决这个问题?