Zmq 套接字在一段时间后不工作



我有一个程序,其中客户端有一个ZMQ_SUB套接字,服务器端有一个ZMQ_PUB套接字,客户端订阅服务器:

非常简单的代码:

客户端:

zmq::socket_t subscriber(context, ZMQ_SUB);     
subscriber.connect("tcp://xxx:xxx");    
subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);

服务器端:

zmq::socket_t publisher(zmqContext, ZMQ_PUB);
publisher->bind("tcp://*.xxx");

我在客户端和服务器之间使用另一对ZMQ_REQ ZMQ_REP套接字。每次客户端通过ZMQ_REQ套接字向服务器发送一些请求时,服务器都会通过ZMQ_REP套接字接收它,执行一些工作,通过 REP 套接字响应,同时生成一堆消息,并通过ZMQ_PUB套接字发布它们。

大多数情况下,客户端能够从ZMQ_SUB套接字接收消息,但我确实遇到客户端无法收到这些消息的情况。

消息保证在服务器端生成,并在生成后立即发布。

正常吗?或者我的用法/设置是否有问题,导致这种不确定的行为。(客户端 SUB 套接字有时收不到消息)

正常吗?

这样的问题很容易被问到,但在没有其他细节和背景的情况下很难得到答案。

ZeroMQ伟大的Pieter HINTJENS的书中的"丢失消息问题"一章"Code Connected Volume 1"谈到了关于这个主题的一些一般原则


• 在SUB套接字上,使用zmq_setsockopt()ZMQ_SUBSCRIBE设置订阅,否则您将不会收到消息。因为您按前缀订阅消息,所以如果您订阅""(空订阅),您将获得所有内容。

• 如果在PUB套接字开始发送数据后启动SUB套接字(即建立与PUB套接字的连接),您将丢失在建立连接之前发布的任何内容。如果这是一个问题,请设置您的体系结构,以便首先启动SUB套接字,然后PUB套接字开始发布。

• 即使您同步SUBPUB套接字,您仍然可能会丢失消息。这是因为在实际创建连接之前不会创建内部队列。如果您可以切换bind/connect方向,使SUB套接字bind-s,PUB套接字connect-s,您可能会发现它的工作方式更符合您的预期。

• 如果您使用的是REPREQ套接字,并且不遵守同步send/recv/send/recv顺序,ØMQ将报告错误,您可能会忽略这些错误。然后,看起来您正在丢失消息。如果您使用 REQREP ,请坚持 send/recv 顺序,并始终在实际代码中检查 ØMQ 调用中的错误。

• 如果您使用的是PUSH套接字,您会发现第一个要连接的PULL套接字将获取不公平的消息份额。仅当所有PULL套接字都成功连接时,才会发生消息的准确轮换,这可能需要几毫秒。作为 PUSH/PULL 的替代方案,对于较低的数据速率,请考虑使用 ROUTER/DEALER 和负载平衡模式。

• 如果要跨线程共享套接字,请不要这样做。它会导致随机的怪异和崩溃。

• 如果您使用的是 inproc ,请确保两个套接字位于同一context中。否则,连接端实际上将失效。另外,先bind,然后connectinproc不是像tcp那样断开连接的运输。

• 如果您使用的是ROUTER套接字,则很容易通过发送格式错误的标识框(或忘记send标识框)意外丢失消息。通常,在ROUTER套接字上设置ZMQ_ROUTER_MANDATORY选项是个好主意,但也要在每次send调用时检查返回代码。

• 最后,如果您真的无法弄清楚出了什么问题,请创建一个重现问题的最小测试用例,并向ØMQ社区寻求帮助。

最新更新