为什么ZMQ不会丢弃消息?

时间:2014-05-22 07:31:01

标签: python zeromq pyzmq

我有一个应用程序,它使用PUB / SUB设置从ZeroMQ发布者获取消息。读者有时很慢,所以我在发送器和接收器上都设置了HWM。我希望接收器将填充缓冲区并跳转以便在处理速度减慢时恢复。但我观察到的行为是它永远不会掉落! ZeroMQ似乎忽视了HWM。我做错了吗?

这是一个最小的例子:

publisher.py

import zmq
import time

ctx = zmq.Context()
sock = ctx.socket(zmq.PUB)

sock.setsockopt(zmq.SNDHWM, 1)

sock.bind("tcp://*:5556")

i = 0

while True:
    sock.send(str(i))
    print i
    time.sleep(0.1)
    i += 1

subscriber.py

import zmq
import time

ctx = zmq.Context()
sock = ctx.socket(zmq.SUB)
sock.setsockopt(zmq.SUBSCRIBE, "")
sock.setsockopt(zmq.RCVHWM, 1)
sock.connect("tcp://localhost:5556")

while True:
    print sock.recv()
    time.sleep(0.5)

2 个答案:

答案 0 :(得分:0)

我相信这里有几件事情可以发挥作用:

  1. High Water Marks are not exact(请参阅链接部分的最后一段) - 通常这意味着真实的队列大小小于比列出的数字,我不知道这将如何表现在1
  2. 您的PUB HWM永远不会丢弃消息...由于PUB套接字的工作方式,它将始终立即处理消息,无论是否有可用的订阅者。因此,除非实际需要ZMQ .1秒来处理队列中的消息,否则HWM将永远不会在PUB方面发挥作用。
  3. 应该发生的事情类似于以下内容(我假设一个操作顺序,允许您实际接收第一个发布的消息):

    1. 启动subscriber.py&等待一段合适的时间,以确保它完全旋转(基本上立即)
    2. 启动publisher.py
    3. PUB处理并发送第一条消息,SUB接收并处理第一条消息
    4. PUB睡眠时间为.1秒,处理&发送第二条消息
    5. SUB睡眠时间为.5秒,套接字收到第二条消息,但是在下一次调用sock.recv()进行处理之前一直处于队列中
    6. PUB睡眠时间为.1秒,处理&发送第三条消息
    7. SUB仍在休眠.3秒,所以第三条消息应该在第二条消息后面的队列中,这将在队列中产生2条消息,第三条消息应该由于{{ 1}}
    8. ...等等等。

      我建议进行以下更改以帮助解决问题:

      1. 删除发布商的HWM ...除了在测试用例中添加我们不需要处理的变量之外什么都不做,因为我们从不期望它会改变任何内容。如果您的生产环境需要它,请将其重新添加并在以后的大批量方案中进行测试。
      2. 将订阅者的HWM更改为50.这会使测试花费更长时间,但您不会处于极端情况,并且因为ZMQ文档指出HWM不准确,极端边缘的情况可能会导致意外的行为。请注意,我相信你的测试(小数字)不会这样做,但是我没有看过实现队列的代码所以我不能肯定地说,你的数据可能足够小您的有效HWM实际上更大
      3. 将您的订阅者睡眠时间更改为3整秒...理论上,如果您的队列最多可以容纳50条消息,您将在两个循环中饱和(就像您现在一样),然后您将拥有等待2.5分钟来处理这些消息,看看你是否开始跳过,在前50条消息之后应该开始跳过大组数字。但是我要等至少5-10分钟。如果您发现在100或200封邮件后开始跳过,那么您就会被数据的小部分所困扰。
      4. 这当然没有解决如果你仍然没有跳过任何信息会发生什么......如果你这样做并且仍然遇到同样的问题,那么我们可能需要更多地了解水印的实际工作情况,我们可能会遗漏一些东西。

答案 1 :(得分:0)

我遇到了完全相同的问题,我的演示与您的演示几乎相同,订阅者或发布者在zmq.RCVHWM或zmq.SNDHWM设置为1后不会删除任何消息。

我在zguide的第5章中提到慢速用户检测的suicidal snail pattern之后走来走去。希望能帮助到你。

顺便说一下:如果你解决了zmq.HWM的错误,请告诉我吗?