Python 如何检测在使用ZeroMQ关闭套接字时是否达到了linger?

Python 如何检测在使用ZeroMQ关闭套接字时是否达到了linger?,python,zeromq,Python,Zeromq,下面运行的dispatch()函数通过队列接收消息。Queue并使用ZeroMQ推送套接字将消息发送到端点 我希望此函数在通过队列接收到None后退出,但如果套接字的底层消息缓冲区有任何未传递的消息(远程端点关闭),则应用程序不会终止。因此,一旦函数接收到一个None,它就会以指定的延迟关闭套接字 使用这种方法,如何检测是否达到指定的逗留时间?特别是,没有提出任何例外 def dispatch(self): context = zmq.Context() socket =

下面运行的
dispatch()
函数通过
队列接收消息。Queue
并使用ZeroMQ
推送
套接字将消息发送到端点

我希望此函数在通过队列接收到
None
后退出,但如果套接字的底层消息缓冲区有任何未传递的消息(远程端点关闭),则应用程序不会终止。因此,一旦函数接收到一个
None
,它就会以指定的延迟关闭套接字

使用这种方法,如何检测是否达到指定的逗留时间?特别是,没有提出任何例外

def dispatch(self):    
    context = zmq.Context()
    socket = context.socket(zmq.PUSH)
    poller = zmq.Poller()

    socket.connect('tcp://127.0.0.1:5555')
    poller.register(socket, zmq.POLLOUT)

    while True:
        try:
            msg = self.dispatcher_queue.get(block=True, timeout=0.5)
        except queue.Empty:
            continue

        if msg is None:
            socket.close(linger=5000)
            break

        try:
            socket.send_json(msg)
        except Exception as exc:
            raise common.exc.WatchdogException(
                f'Failed to dispatch resource match to processor.\n{msg=}') from exc
Q:“如何检测在使用ZeroMQ关闭套接字时是否达到
linger
?”

这可不是件容易的事

ZeroMQ在内部对用户级代码隐藏了所有这些细节,因为API(从那时起,直到最近的v4.3版)是用Zen of Zero的所有艺术之美精心打造的,目的是实现最高性能、几乎线性的扩展和最小的延迟。执行零个不支持(如果违反,则越少)的步骤

解决这个问题可能有三个主要的攻击方向:

  • 您可以尝试配置并使用
    zmq\u socket\u monitor()
    的事件观察覆盖,以可达到的最低细节级别分析事件的实际顺序
  • 您还可以尝试一种相当野蛮的方法,为
    zmq.Socket()
    -实例设置无限
    LINGER
    属性,并在设置的(现在)软“LINGER”过期后发送
    信号,直接终止阻塞操作,无论是使用
    zmq\u定时器的新的v4.3+功能(a
    [ms]
    -计时器/回调实用程序的粗略框架)或自己的
  • 人们可能更愿意通过“围绕”调用
    zmq\u ctx\u term()
    ,保持事情的整洁并仍然达到目标,根据v4.3文档化API,该调用将被阻止(警告,在其他API版本中不保证如此)。这种方式可以帮助您间接检测阻塞状态下实际花费的持续时间,如:
。。。
关闭时的标称停留时间=5000
MASK_a=“INF:.term()-ed尽快,在从{1:}[ms]授予的{0:}[us]之后”
MASK_b=“INF:.term()-ed ALAP,在从{1:}[ms]授予的{0:}[us]之后”
...
socket.setsockopt(zmq.LINGER,标称_LINGER_ON_CLOSE)#u__;始终是显式的
aClk=zmq.Stopwatch()
aClk.start()#段
context.term()。。。。。。。
_=aClk.stop()#_____________________________________
...
打印((如果<<则遮罩)(标称持续时间*1000)
其他面具
).format(u,标称_LINGER_ON_CLOSE)
)
...
我对always,的确always的宣传非常明确,这是基于两个方面都看到了从一个版本到另一个版本的“默认值”(这是公平的,希望继续以同样的方式进行),因此一个负责任的设计确实应该始终强制地重新输入这些值,我们想要到位,因为我们的代码将在我们当前的版本和我们,凡人中生存,对于我们当前假设的哪一部分在任何未来的版本/修订中仍然是“默认值”仍然没有任何保证,并且具有相同的不确定性,在我们部署的代码块的域中将出现什么版本组合(截至2020年EoY,仍然有v2.1、v2.11、v3.x、v4.x在某处疯狂运行,因此人们永远不会知道,是吗?)

...
NOMINAL_LINGER_ON_CLOSE = 5000
MASK_a = "INF: .term()-ed ASAP, after {0:} [us] from {1:} [ms] granted"
MASK_b = "INF: .term()-ed ALAP, after {0:} [us] from {1:} [ms] granted"
...
socket.setsockopt( zmq.LINGER, NOMINAL_LINGER_ON_CLOSE ) # ____ BE EXPLICIT, ALWAYS
aClk = zmq.Stopwatch()
aClk.start() #_________________________________________________ BoBlockingSECTION
context.term() # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\   BLOCKING.......
_ = aClk.stop() #______________________________________________ EoBlockingSECTION
...
print( (      MASK_a if _ < ( NOMINAL_LINGER_ON_CLOSE * 1000 )
         else MASK_b
         ).format(      _,    NOMINAL_LINGER_ON_CLOSE )
       )
...