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

时间:2017-09-04 03:36:04

标签: java zeromq

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

导致它被阻止的原因是什么?

如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

ZeroMQ是一个使用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套接字;没有跑。