ZeroMQ:设置 LINGER=0 没有按预期工作

ZeroMQ: set LINGER=0 does not work as expected

我正在为 ZeroMQ 使用 Python 绑定。我的 libzmq 版本是 4.2.5,我的 pyzmq 版本是 17.1.2。

我正在尝试让 "producer" 将大量数据传输到 "consumer"。 "producer" 的代码是:

# producer.py
import zmq
import time
import os

ctx = zmq.Context()
sock = ctx.socket(zmq.PUB)
sock.bind('tcp://*:8000')

x = os.urandom(1000000000) # large amount of data, requires much time to transmit it
sock.send(x)
print('Done')

sock.setsockopt(zmq.LINGER, 0)
sock.close()

t1 = time.time()
ctx.term() # I expect this should return immediately
print(time.time() - t1)

而"consumer"的代码是:

# consumer.py
import zmq

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

sock.setsockopt_string(zmq.SUBSCRIBE, '')
sock.connect('tcp://localhost:8000')

data = sock.recv()

我希望 producer.py 中的 ctx.term() 应该立即 return,因为套接字的 LINGER 已经设置为零。但是当我 运行 这些代码时, ctx.term() 并没有像预期的那样立即 return 。相反,该功能需要花费数十秒 return,并且 consumer.py.

已成功接收所有大数据。

我正在尝试找出原因,希望有人能帮我一下。

Q : "ZeroMQ: set LINGER=0 does not work as expected"

ZeroMQ 设置 LINGER=0 恕我直言是否按预期工作 (如记录):

ZeroMQ 文档明确指出所有 zmq_setsockopt() 调用(包装,用于 python,进入方法 .setsockopt() ) 生效,即修改 Socket-实例的行为。

旧版本的 ZeroMQ 文档(自 v2.x 以来在我的项目中使用 ZeroMQ 包装的分布式系统)对此更加明确:

Caution: All options, with the exception of ZMQ_SUBSCRIBE, ZMQ_UNSUBSCRIBE, ZMQ_LINGER, ZMQ_ROUTER_MANDATORY and ZMQ_XPUB_VERBOSE only take effect for subsequent socket bind/connects.

考虑到这一点,sock.setsockopt( LINGER, 0 ) 确实指示 Socket()-实例 sock 不要等待相应的 <aContextINSTANCE>.term() 直到它完成所有尚未入队的消息的所有尝试都完全传播到队列头端并在那里处理到有线协议并在其监督下成功发送或接受在他们的网络上丢失- 到邻近交易对手的方式。

然而,这并没有说明,传输中的数据将要做什么,Context()-实例已经在传输中。

据我 worked extensively 自 v2.x 以来使用 ZeroMQ,恕我直言,没有任何东西提醒我如何使用暴露给 [=75] 的 ZeroMQ 语义来中断正在进行的消息传输=] API,超出了 LINGER 指示的行为,可以解释为:
" 忽略任何已知的 SENDS/RECEIVES 仍在等待轮到队列",
然而,这并不会阻止在线发送传输中数据的进程。

ZeroMQ 特意以这种方式工作。

人们可能想阅读更多有关 ZeroMQ 内部的信息 here or perhaps to just have a general view from the orbit-high perspective as in


结语:仅供不得已时使用

如果确实最终需要有某种方法来阻止甚至这些传输中的消息流,请随意 post 一个关于如何让事情以这种疯狂方式工作的新问题。

据我所知,this is still a problem

可以通过在套接字创建时而不是在关闭之前设置 linger 选项来避免。