ZeroMQ:设置LINGER = 0不能按预期工作

时间:2019-07-29 18:28:04

标签: python multithreading message-queue zeromq pyzmq

我正在将Python绑定用于ZeroMQ。我的libzmq版本是4.2.5,而我的pyzmq版本是17.1.2。

我正试图让“生产者”向“消费者”传输大量数据。 “生产者”的代码是:

# 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.py
import zmq

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

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

data = sock.recv()

我希望ctx.term()中的producer.py应该立即返回,因为套接字的LINGER已设置为零。但是,当我运行这些代码时,ctx.term()不会立即返回预期的结果。取而代之的是,该函数需要数十秒钟才能返回,并且consumer.py已成功接收到所有大数据。

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

2 个答案:

答案 0 :(得分:1)

  

Q :“ ZeroMQ:集LINGER=0不能按预期工作

ZeroMQ集LINGER=0确实可以IMHO正常工作(已记录)

ZeroMQ文档清楚地表明,所有 zmq_setsockopt() 调用(包装用于python中的方法.setsockopt())均生效,即修改{{ 1}}-实例的行为。

ZeroMQ文档的较早版本(自v2.x以来,已在我的带有ZeroMQ封装的分布式系统的项目中使用)在这方面更明确:

  

警告:除SocketZMQ_SUBSCRIBE ZMQ_UNSUBSCRIBE ZMQ_LINGERZMQ_ROUTER_MANDATORY仅对后续的套接字ZMQ_XPUB_VERBOSE / bind生效。

请牢记这一点,connects实际上指示sock.setsockopt( LINGER, 0 )实例 Socket() 请勿等待相应的sock直到其所有试图完成所有仅被入队列的消息的尝试会完全传播到队列头端,并在那里处理成有线协议,并在其监督下被成功发送或接受,并已以全网方式丢失给了邻居交易对手。

但是,这并不是说传输数据要做什么,<aContextINSTANCE>.term()实例已经沿线移动了。

从v2.x开始,我对ZeroMQ拥有worked extensively,IMHO并没有提醒我一种方法,该方法如何使用暴露于公共API的ZeroMQ语义来中断正在进行的消息传输,除了{{ 1}}所指示的行为,可能是这样解释的:
“忽略任何仍会排队等待的已知发送/接收消息”
但是,这并不会阻止在线传输传输数据的进度。

ZeroMQ故意以此方式工作。

一个人可能想了解更多关于ZeroMQ内部here的信息,或者也许只是像"ZeroMQ Hierarchy in less than a Five Seconds"那样从高轨道的角度进行一般性的了解。


结尾:仅在不得已的情况下使用

如果确实确实最终有必要采取某种措施来阻止这些正在传输的消息流,请随时提出一个新的问题,以解决问题的方法。

答案 1 :(得分:0)

AFAIK,this is still a problem

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