【问题标题】:A zmq subscriber unable to subscribe to the published messages if socket.send() was used only once如果仅使用了一次 socket.send(),则 zmq 订阅者无法订阅已发布的消息
【发布时间】:2016-12-02 13:04:33
【问题描述】:

如果socket.send() 在发布者中仅使用一次,则zmq 订阅者订阅消息失败。

在发布者中使用以下代码时,订阅者能够订阅消息:

var zmq = require('zmq')
  , sock = zmq.socket('pub')

sock.bindSync('tcp://127.0.0.1:3000');
var message = {"test" : true};
setInterval(function(){
    sock.send(['notify_anomaly', JSON.stringify(message)]);
},1000);

但是如果在发布者代码中去掉setInterval就不行了,如下:

var zmq = require('zmq')
  , sock = zmq.socket('pub')

sock.bindSync('tcp://127.0.0.1:3000');
var message = {"test" : true};
sock.send(['notify_anomaly', JSON.stringify(message)]);

【问题讨论】:

  • 那么不要删除setInterval?巧合的是,如果我拔掉电源线,我的电脑就会停止工作。
  • 我相信这是“慢木匠”的问题。订阅者总是会错过第一条消息,除非发布者等待订阅者连接后再发送。 zguide.zeromq.org/page:all#toc13

标签: node.js zeromq publish-subscribe


【解决方案1】:

这是“慢加入者”问题的结果。

这是guide的引述:

关于 PUB-SUB 套接字,还有一件事需要了解:您 不知道订阅者何时开始收到消息。甚至 如果您启动订阅者,请稍等片刻,然后启动发布者, 订阅者总是会错过发布者的第一条消息 发送。这是因为当订阅者连接到发布者时 (需要一小段时间但非零时间的事情),发布者可以 已经在发送消息了。

基本上,当发布者运行时,它会与订阅者握手。由于这是异步的,发布者可能会在握手完成之前完成发送消息。在这种情况下,订阅者将错过消息。为了让订阅者收到第一条消息,发布者需要等待发送,直到确定订阅者已连接。

这里还有一段话:

在第 2 章 - 套接字和模式中,我们将解释如何同步一个 发布者和订阅者,这样您就不会开始发布数据 直到订阅者真正连接并准备就绪。

它展示了当订阅者准备好在订阅套接字 here 上接收时,如何使用另一个套接字对使用 REQ-REP 发出信号。

【讨论】:

    【解决方案2】:

    嗯,不完全是,先生。

    从历史上看,
    ZeroMQ 使用 SUB 端订阅(主题过滤)。这意味着两件事。 PUB-lisher 对谁 SUB'ed 做什么和花费零了解零努力在主题过滤器处理上。另外,它倾泻而下,并且必须这样做,所有消息都流向所有不同的传输级通道,朝向(仅向下的主题过滤)SUB-scribers(这主要在传输上造成一定程度的低效率-层资源)。

    因此,如果您的代码使用“旧”ZeroMQ 包装器/语言绑定,那么您的“PUB-lisher”是毫无疑问的,而不是问题的根本原因,因为它的设计不关心任何问题,包括“后期订阅者”,交易对手。时间延迟有帮助(不是 PUB.send(),而是

    // unknown SUB code, a default SUB-state is TOPIC-FILTER throws everything, YES !
    //                                                       THROWS EVERYTHING AWAY
    SUB.setsockopt( zmq.SUBSCRIBE,
                    "<some_TOPIC_FILTER_string_to_be_used_after_this_happens_in_time"
                    );
    

    因此,这与 Q.E.D. PUB 方面的代码本身无关,但如果设计稳健的应用架构,设计人员必须牢记时间巧合。

    接下来,
    较新的 ZeroMQ 版本已切换到 PUB 侧过滤。这似乎是一个重大变化,但对您的示例没有任何重大影响。

    PUB-side 过滤刚刚通过PUB-side 上的集中主题过滤消除了传输层拥塞,代价是 sum-of-(so-far-廉价-'原因-分布式)-工作负载,现在驻留在 PUB 端。

    所以,您的观察仍然显示在SUB-side 上没有收到任何消息,那么为什么要详细说明呢?好吧,现在,在较新版本的情况下,如果 SUB 没有设法“告诉并交付”,则 SUB-scription 偏好对 PUB strong>-side,在那之前已经派出了PUB.send( aFirstMESSAGE_to_Those_whom_I_know_they_SUBed_to_this_TOPICFILTER ) 再一次,由于分布式系统事件的传播和交付及时,不是由于PUB-side(仅 ) 代码调整

    结语:

    无论哪种情况,ZeroMQ 都是一个无代理的消息传递框架。这意味着,消息的持久性甚至不是旨在创建或提供的。每个可扩展的正式通信模式的行为原型节点都在 API 文档、缓冲区管理和消息-{ 保留 | 中明确指定。丢弃}和其他规则。一定要检查不同版本的 ZeroMQ 低级协议,它在你的分布式系统领域的所有节点上使用(通常无法控制,但可以设计版本感知行为策略执行来处理这种生产生态系统不确定性)。

    最佳
    最佳
    下一步
    步骤:

    如果有人努力在分布式系统的专业设计领域停留一段时间,那么最好的办法就是阅读 ZeroMQ 之父之一 Pieter HINTJENS (may check other post on ZeroMQ and follow the direct link to the book's PDF-version) 的精彩著作。

    【讨论】:

      猜你喜欢
      • 2016-12-14
      • 1970-01-01
      • 1970-01-01
      • 2015-06-30
      • 2016-08-11
      • 2016-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多