ZeroMQ XPUB/XSUB 严重缺陷?

ZeroMQ XPUB/XSUB Serious Flaw?

似乎 XPUB/XSUB 套接字类型有一个很难解决的严重缺陷:

这是我对该中心节点的实现:

#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;
}

问题当然是慢工综合症。如果我将一个新发布者连接到 XSUB 并发布一些消息,它们就会消失在空白中:

#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;
}

但是,如果我 sleep(1) 连接到 XSUB 后,它神奇地起作用了:

#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;
}

指南声称有一个简单的解决方案可以解决此 "slow joiners" 综合症,但从未提供有效的同步 XSUB/XPUB 实施。经过大量搜索,看起来大多数人只是 sleeping,这真的很糟糕。

为什么这个问题一直没有得到解决?有任何已知的解决方法吗?我所有的 google 查询都让我回到指南...

我找到了一种解决方法 here,即在发布者端使用 PUSH/PULL,在订阅者端使用 PUB/SUB。新拓扑如下所示:

这是中心节点所需的代码:

#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;
}

然后是发布商:

#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;
}

这个解决方案似乎工作得很好,如果人们发现它有任何缺点,我希望他们能提出意见。如果我遇到更好的答案,我会 post 在这里。

缺点是您的发布商总是在发布。在 XSUB/XPUB 情况下,订阅会转发给您的发布者,以便他们可以限制发送给代理的内容。这导致更少的网络流量和更少的代理工作。在 PULL/PUB 的情况下,发布者永远不会看到订阅信息。最坏的情况是订阅者的订阅意味着他们只需要来自一个发布者的数据。所有发布者仍会向代理发送他们的数据,而代理会过滤掉除一个发布者的消息之外的所有内容。