使用 Logbook 和 ZeroMQ,为什么我需要等待才能传递消息?

With Logbook and ZeroMQ, why do I need to wait to be able to pass messages?

代码说明:
我的代码很简单,它从 Logbook 库(使用 pyzmq)启动一个 ZeroMQHandler(基于套接字的消息传递)。 Logger(日志)在整个应用程序中运行。最后,处理程序关闭端口。 .push().pop_application() 方法代替了
with handler.applicationbound(): 并缩进。

用途:
我正在测试这个基于队列的消息传递,看看它是否可以成为一个低影响的异步日志记录解决方案。我需要每秒记录大约 15000 条消息。我更喜欢使用 Python,但我的退路是用 C++ 编写记录器并将其句柄公开给 python。

问题:
问题是,如果我在打开处理程序(套接字)后不等待 四分之一秒 或更长时间,程序将在没有任何消息通过的情况下执行(测试程序花费的时间少于0.25 秒执行)。我将其解释为 ZeroMQ 套接字或类似东西所需的设置时间。所以我想看看是否有人有类似的经历,也许这在任何地方都有记录,但我似乎无法自己弄清楚。我想知道为什么需要这个。感谢您的任何输入。

我的工作代码看起来像这样:

from logbook.queues import ZeroMQHandler
from logbook import Logger
import time

addr='tcp://127.0.0.1:5053'
handler = ZeroMQHandler(addr)
time.sleep(0.25) ################################################# THIS ! ####

log = Logger("myLogbook")
handler.push_application()

log.info("start of program")
foo()
log.info("end of program")

handler.close()
handler.pop_application()

接收器,运行 在不同的 python 内核中(用于测试,将输出提供给标准输出):

from logbook.queues import ZeroMQSubscriber
from logbook import Logger, StreamHandler
import sys
import time
addr='tcp://127.0.0.1:5053'
print("ZeroMQSubscriber begin with address {}".format(addr))
subscriber = ZeroMQSubscriber(addr)
handler = StreamHandler(sys.stdout)

log = Logger("A receiver")
handler.push_application()


try:
    i=0
    while True:
        i += 1
        record = subscriber.recv(2)
        if not record:
            pass # timeout
        else:
            print("got message!")
            log.handle(record)
except KeyboardInterrupt:
    print("C-C caught, program end after {} iterations".format(i))    
handler.pop_application()

ZeroMQ 确实花了一些时间来创建一个 Context()-实例 per-se,然后它要求 O/S 分配 memory-bound 资源,以产生 I/O-threads,这也需要一些额外的时间。接下来,每个Socket()-实例化都会消耗一些add-on开销时间。

在本机 API-documentation 和教育资源中都有详细记录,异步信号/消息传递框架确实花费了一些时间,在任何 API-request 实际上在两个 [=55] 内部得到处理之前=] 和 "remote" Context()-instances,并最终标记为可交付可读的 "remote"-end of some ZeroMQ Scalable Formal Communication Archetype.

这应该不足为奇,更多 re-wrapped 使用 ZeroMQ 工具( re-wrapped 通过另一个抽象级别,编码到 logbook.queue.ZeroMQSubscriber, logbook.queue.ZeroMQHandler 类 ),只会增加额外的 { 设置和操作 }-开销,因此服务的已知异步性只会增加。

如果您的应用程序需要在任何一对两端之间进行任何类型的相互重新确认,它们已达到 R就绪-T o-Operate state ( RTO-state ),最好是引入某种 smart-reconciliation 策略,而不是保留在盲目的信仰中,依靠足够长的时间.sleep()希望事情能有足够的时间安定下来并进入RTO。

中,总是最好明确,而不是保持乐观的希望。


结语:

考虑到您的持续吞吐量应该安全地下降并保持在 预期阈值以下 <= 66 [us/message] 每条消息发送,让我也对适当的 Context()-参数化,以便在现实的硬件和system-wide资源规划下确实顺利地承载您所需的工作量。

默认值不是一成不变的,也不应该是一个值得依赖的点。