zeromq,C ++,是否有必要为订阅者设置高水位线?

时间:2013-04-26 03:53:52

标签: zeromq publish-subscribe

我对ZeroMQ PUB / SUB进行了快速测试,现在有了一些工作代码。但是,我对zeromq中应用的高水位标记有点困惑。

我在我的发布商代码中设置了一个HWM,它为连接到套接字的每个订阅者设置了队列长度。

然而,也可以在订户的接收套接字上设置HWM。是否有任何理由在订户端设置HWM,这与设置发布者HWM有何不同?

2 个答案:

答案 0 :(得分:23)

简答:

发布者中,我们应该始终仔细考虑HWM,因为有很多原因导致崩溃(内存不足)影响整个系统(因为发布者为所有订阅者提供服务)。 / p>

同样在订户中,有些情况下调节HWM可能很有用,但这主要取决于订户的性质,接收消息的作用以及接收消息的高低程度它无法及时处理大量接收消息的概率;以及预期的运行时环境(可用内存量,订户数量等)

更详细的答案:

ZMQ使用HWM(高水位线)的概念来定义其内部管道的容量。从套接字或套接字出来的每个连接都有自己的管道,HWM用于发送和/或接收,具体取决于套接字类型。某些套接字( PUB PUSH仅包含发送缓冲区。一些( SUB PULLREQREP只有接收缓冲区。一些(DEALERROUTERPAIR)同时具有发送和接收缓冲区。

可用的socket option是:

  • ZMQ_SNDHWM :为出站邮件设置高水位标记(publisher socket上的...)
  • ZMQ_RCVHWM :为入站邮件设置高水位标记(subscriber socket上的...)

ZMQ 3.0+强制对其内部缓冲区(即所谓的HWM)进行默认限制,因为HWM是减少内存溢出问题的好方法

ZMQ_PUBZMQ_SUB都将ZMQ_HWM选项操作设置为“Drop”,因此当限制加密时,订阅者或发布者的内存应该停止增长,至少通过什么取决于ZMQ缓冲区。

通常谁需要大多数保护,以防止不加区分地使用内存(内存不足问题):发布商:

在inproc传输中,发送方和接收方共享相同的缓冲区,因此真正的HWM是双方设置的HWM的总和。

但是如果您使用的是TCP并且订阅者很慢,则消息将在发布者上排队。

PUB-SUB的常见失败原因包括:

  • 订阅者可以过慢地获取邮件,因此队列会累积然后溢出。
  • 网络可能变得太慢,因此发布方队列溢出,发布商崩溃。

在发布者上排队消息会使发布商内存不足并崩溃,尤其是如果有大量订阅者,并且出于性能原因无法刷新到磁盘。

从发布商的角度来看,伟大的策略,我们通过正确设置ZWM使用停止在一段时间后排队新消息,新消息被拒绝或者下降;这是ØMQ在发布商设置HWM时所做的事情。

ZMQ还可以对订阅者上的消息进行排队

如果有人会因内存不足而崩溃,那么它将是订阅者而不是发布者,这是公平的。这对于“高峰”流是完美的,其中订户不能保持一段时间,但是当流减慢时可以赶上。

注意:HWM不准确;虽然默认情况下你最多可以获得1,000条消息,但由于libzmq实现其队列的方式,实际缓冲区大小可能会低得多(只有一半)。

这些假设的主要来源是Pieter Hintjens的书“Code Connected Volume 1”,该书以电子格式在线提供;它有一章致力于 High-Water Marks ,其中包含有关此主题的更多解释。

答案 1 :(得分:0)

如果您同时订阅超过1000个主题,那么在订阅者上设置ZMQ_SNDHWM会很有用(据我所知,默认情况下ZMQ_SNDHWM为1000)。所以,如果你这样订阅:

for(i = 0; i < 2000; i++)
{
    subscriber.setsockopt( ZMQ_SUBSCRIBE, &i, sizeof(i));
}

由于输出队列溢出,它将无法工作。

但如果你在连接之前设置

subscriber.setsockopt( ZMQ_RCVHWM, &i, sizeof(i));
subscriber.setsockopt( ZMQ_SNDHWM, &i, sizeof(i));

效果很好。