我有一个程序,其中客户端有一个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套接字有时不接收消息)
答案 0 :(得分:1)
这样的问题很容易被问到,但很难得到答案而没有其他细节和背景。
ZeroMQ
“缺少消息问题”这篇伟大的Pieter HINTJENS书中的章节"Code Connected Volume 1"
说了一些关于这个主题的一般原则:< / p>
•在SUB
套接字上,使用zmq_setsockopt()
使用ZMQ_SUBSCRIBE
设置订阅,否则您将无法收到消息。因为您通过前缀订阅消息,所以如果您订阅""
(空订阅),您将获得所有内容。
•如果在SUB
套接字开始发送数据后启动PUB
套接字(即建立与PUB
套接字的连接),您将丢失之前发布的内容建立了联系。如果这是一个问题,请设置您的体系结构,以便首先启动SUB
套接字,然后PUB
套接字开始发布。
•即使同步SUB
和PUB
套接字,您仍可能丢失消息。这是因为在实际创建连接之前不会创建内部队列。如果您可以切换bind
/ connect
方向以便SUB
套接字bind
- s和PUB
套接字connect
- s,那么可能会发现它比你期望的更有效。
•如果您使用的是REP
和REQ
套接字,并且您没有坚持同步send
/ recv
/ send
/ { {1}}订单,ØMQ将报告您可能忽略的错误。然后,看起来你会丢失消息。如果您使用recv
或REQ
,请坚持REP
/ send
订单,并始终在实际代码中检查ØMQ呼叫上的错误。
•如果您正在使用recv
套接字,您会发现要连接的第一个PUSH
套接字将获取不公平的消息份额。只有在成功连接所有PULL
个套接字时才会发生消息的准确轮换,这可能需要几毫秒。作为PULL
/ PUSH
的替代方案,对于较低的数据速率,请考虑使用PULL
/ ROUTER
和负载均衡模式。
•如果您跨线程共享套接字,则不要。它会导致随机的怪异和崩溃。
•如果您使用的是DEALER
,请确保两个套接字位于同一个inproc
。否则连接端实际上会失败。此外,context
首先是bind
,然后是connect
。 inproc
不是tcp
之类的断开连接的传输。
•如果您正在使用ROUTER
套接字,则通过发送格式错误的身份框架(或忘记send
身份框架),非常容易意外丢失邮件。一般来说,设置ZMQ_ROUTER_MANDATORY
套接字上的ROUTER
选项是个好主意,但也要检查每次send
次呼叫的返回代码。
•最后,如果你真的无法弄清楚出了什么问题,制作一个可以重现问题的最小测试用例,并向ØMQ社区寻求帮助。