ZeroMQ XPUB/XSUB Serious Flaw?

匿名 (未验证) 提交于 2019-12-03 08:56:10

问题:

It seems as though the XPUB/XSUB socket types have a serious flaw that is difficult to work around:

This is my implementation of that center node:

#include <zmq.hpp>  int main() {     zmq::context_t context(1);      //Incoming publications come here     zmq::socket_t sub(context, ZMQ_XSUB);     sub.bind("ipc://subscriber.ipc");      //Outgoing publications go out through here.     zmq::socket_t pub(context, ZMQ_XPUB);     pub.bind("ipc://publisher.ipc");      zmq::proxy(sub, pub, nullptr);      return 0; } 

The problem is, of course, slow joiner syndrome. If I connect a new publisher to XSUB and publish some messages, they disappear into the void:

#include "zhelpers.hpp"  int main () {     //  Prepare our context and publisher     zmq::context_t context(1);     zmq::socket_t publisher(context, ZMQ_PUB);     publisher.connect("ipc://subscriber.ipc");      s_sendmore (publisher, "B");     s_send (publisher, "Disappears into the void!!");      return 0; } 

However, if I sleep(1) after connecting to XSUB, it magically works:

#include "zhelpers.hpp"  int main () {     //  Prepare our context and publisher     zmq::context_t context(1);     zmq::socket_t publisher(context, ZMQ_PUB);     publisher.connect("ipc://subscriber.ipc");      sleep(1);     s_sendmore (publisher, "B");     s_send (publisher, "Magically works!!");      return 0; } 

The Guide claims there is a simple solution to this "slow joiners" syndrome, but then never delivers a working synchronized XSUB/XPUB implementation. After much searching it looks like most people are just sleeping, which is really bad.

Why hasn't this ever been fixed? Are there any known workarounds? All my google queries just point me back to the guide...

回答1:

I found one workaround here, and that is to use PUSH/PULL on the publisher side, and PUB/SUB on the subscriber side. The new topology looks like this:

This is the code you need for the center node:

#include <zmq.hpp>  int main() {     zmq::context_t context(1);      //Incoming publications come here     zmq::socket_t sub(context, ZMQ_PULL);     sub.bind("ipc://subscriber.ipc");      //Outgoing publications go out through here.     zmq::socket_t pub(context, ZMQ_PUB);     pub.bind("ipc://publisher.ipc");      zmq::proxy(sub, pub, nullptr);      return 0; } 

And then for publishers:

#include "zhelpers.hpp"  int main () {     //  Prepare our context and publisher     zmq::context_t context(1);     zmq::socket_t publisher(context, ZMQ_PUSH);     publisher.connect("ipc://subscriber.ipc");      s_sendmore (publisher, "B");     s_send (publisher, "No sleep!");      return 0; } 

This solution seems to work fairly well, and I hope people chime in if they see any downsides to it. If I come across a better answer, I'll post here.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!