【发布时间】:2021-01-18 05:22:46
【问题描述】:
我发现了很多关于类似主题的问题,但它们并没有帮助我解决我的问题。
使用:
- Linux Ubuntu 14.04
- python 3.4
- zmq : 4.0.4 // pyZMQ 14.3.1
TL;DR
即使在设置了 HWM 之后,ZMQ SUB 套接字中的接收者队列也会无限增长。当订阅者比发布者慢时会发生这种情况。 我能做些什么来防止它?
背景
我在人机交互领域工作。我们有一个庞大的代码库来控制鼠标光标之类的东西。我想在几个模块中“打破它”,与 ZMQ 通信。 它必须具有尽可能小的延迟,但丢弃(丢失)消息并不那么重要。
另一个有趣的方面是可以在节点之间添加“间谍”。因此 PUB/SUB 插座似乎是最合适的。
类似这样的:
+----------+ +-----------+ +------------+
| | PUB | | PUB | |
| Input | +----+------> | Filter | +----+------> | Output |
| | | SUB | | | SUB | |
+----------+ v +-----------+ v +------------+
+-----+ +-----+
|Spy 1| |Spy 2|
+-----+ +-----+
问题
一切正常,除了我们添加了间谍。 如果我们添加一个间谍来执行“繁重的工作”,例如使用 matplotlib 进行实时可视化,我们会注意到绘图中的延迟增加。 IE:在上图中,过滤和输出很快,没有看到延迟,但是在 Spy 2 上,运行 20 分钟后延迟可以达到 10 分钟(!!)
看起来接收器上的队列无限增长。 我们调查了 ZMQ 的高水位 (HWM) 功能,将其设置为低以丢弃旧消息,但没有任何改变。
最小代码
架构:
+------------+ +-------------+
| | PUB | |
| sender | -------------> | receiver |
| | SUB| |
+------------+ +-------------+
接收器是一个慢速接收器(在第一张图中充当间谍)
代码:
发件人.py
import time
import zmq
ctx = zmq.Context()
sender = ctx.socket(zmq.PUB)
sender.setsockopt(zmq.SNDBUF, 256)
sender.set_hwm(10)
sender.bind('tcp://127.0.0.1:1500')
print(zmq.zmq_version()) ## 4.0.4
print(zmq.__version__) ## 14.3.1
print(sender.get_hwm()) ## 10
i = 0
while True:
mess = "{} {}".format(i, time.time())
sender.send_string(mess)
print("Send : {}".format(mess))
i+= 1
receiver.py:
import time
import zmq
ctx = zmq.Context()
front_end = ctx.socket(zmq.SUB)
front_end.set_hwm(1)
front_end.setsockopt(zmq.RCVBUF, 8)
front_end.setsockopt_string(zmq.SUBSCRIBE, '')
front_end.connect('tcp://127.0.0.1:1500')
print(zmq.zmq_version()) ## 4.0.4
print(zmq.__version__) ## 14.3.1
print(front_end.get_hwm()) ## 1
while True:
mess = front_end.recv_string()
i, t = mess.split(" ")
mess = "{} {}".format(i, time.time() - float(t))
print("received : {}".format(mess))
time.sleep(1) # slow
我认为这不是 ZMQ Pub/Sub 的正常行为。 我尝试在接收器、订阅器和两者中都设置 HWM,但没有任何改变。
我错过了什么?
Edit :
我认为我在解释我的问题时并不清楚。我做了一个移动鼠标光标的实现。输入是在 ZMQ 中以 200Hz 发送的鼠标光标位置(带有 .sleep( 1.0 / 200 ) ),完成了一些处理并更新了鼠标光标位置(在我的最小示例中我没有这个睡眠)。
一切都很顺利,即使我发射了间谍。尽管如此,间谍的延迟却越来越长(因为处理速度慢)。延迟不会出现在光标中,位于“管道”的末尾。
我认为问题出在订阅者排队消息缓慢。
在我的示例中,如果我们杀死发送者并让接收者活着,消息将继续显示,直到显示所有(?)提交的消息。
间谍正在绘制光标位置以提供一些反馈,有这样的延迟仍然很不方便......我只是想得到最后发送的消息,这就是我试图降低HWM的原因。
【问题讨论】:
-
ZMQ HWM 不是与特定消息计数相关的确切数字。它更多的是关于 ZMQ 将为您的队列分配多少内存的一般建议。关键是,很难调试 HWM 的特定问题,但可以公平地说,人们遇到的大多数问题 HWM 只是不了解它的不确切性质。您是否确认 ZMQ 专用于您的队列的内存量是问题的一部分?我觉得你的问题的根源更有可能不是你的应用程序接收消息的速度,而是它对它们做了什么。
标签: python performance sockets zeromq