为什么 Zyre 演员的 PAIR 插座使用 LINGER=0 和 SNDTIMEO=0?
Why are LINGER=0 and SNDTIMEO=0 used for Zyre actors' PAIR sockets?
查看 Pyre 的(Python 版本的 Zyre)源代码,我看到了以下内容:
def zcreate_pipe(ctx, hwm=1000):
backend = zsocket.ZSocket(ctx, zmq.PAIR)
frontend = zsocket.ZSocket(ctx, zmq.PAIR)
# ...
# close immediately on shutdown
backend.setsockopt(zmq.LINGER, 0)
frontend.setsockopt(zmq.LINGER, 0)
class ZActor(object):
# ...
def __init__(self, ctx, actor, *args, **kwargs):
# ...
self.pipe, self.shim_pipe = zhelper.zcreate_pipe(ctx)
# ...
def run(self):
self.shim_handler(*self.shim_args, **self.shim_kwargs)
self.shim_pipe.set(zmq.SNDTIMEO, 0)
self.shim_pipe.signal()
self.shim_pipe.close()
def destroy(self):
# ...
self.pipe.set(zmq.SNDTIMEO, 0)
self.pipe.send_unicode("$TERM")
self.pipe.wait()
self.pipe.close()
我感兴趣的是 LINGER=0
和 SNDTIMEO=0
的用法。
ZMQ_SNDTIMEO: Maximum time before a send operation returns with EAGAIN
[rather self-explanatory]
ZMQ_LINGER: Set linger period for socket shutdown
[...] The linger period determines how long pending messages which have yet to be sent to a peer shall linger in memory after a socket is closed with zmq_close(3), and further affects the termination of the socket's context with zmq_term(3). [...]
[...]
The value of 0 specifies no linger period. Pending messages shall be discarded immediately when the socket is closed with zmq_close().
[...]
所以简而言之,两个方向的最后一条消息可能都没有发送。如果 send
会阻塞,SNDTIMEO=0
会启动,并且(假设发送队列中仍有内容)LINGER=0
可能会在 close
.[=23 期间丢弃消息=]
这似乎是个坏主意,因为如果 $TERM
被丢弃,actor 不会被杀死,而如果 signal
被丢弃,调用线程只会阻塞。对我来说唯一有意义的方法是如果消息可能永远不会被丢弃(因为 PAIR
over inproc://
传输的某些特性?),但是,为什么首先使用套接字选项?
是什么让这段代码按预期工作,为什么要这样使用套接字选项,以及在什么情况下should/shouldn我不遵循这个例子?
对我来说这看起来像是一个潜在的错误 (deadlock/hang)。如果 actor 没有足够快地读取发送给它的消息,队列(大小 'hwm')可能已满 - 这意味着 zmq 不会发送任何东西,并且 destroy() 将最终等待信号actor 退出时预期 - 但由于 actor 从未收到“$TERM”,它无法做出反应 - 除非其 recv() 中存在超时,否则它也可能永远等待消息。
[我注意到在 destroy() 方法中的 wait() 之前似乎有一条持怀疑态度的评论 - 所以您可能不是第一个注意到这一点的人]
我会小心处理 destroy() - 实际上,您可以编写您的解决方案,以便极不可能溢出队列 - 或者您可以检查发送是否在 destroy() 中成功 - 如果没有 - 或者再试一次(超时)或跳过 wait()。
查看 Pyre 的(Python 版本的 Zyre)源代码,我看到了以下内容:
def zcreate_pipe(ctx, hwm=1000):
backend = zsocket.ZSocket(ctx, zmq.PAIR)
frontend = zsocket.ZSocket(ctx, zmq.PAIR)
# ...
# close immediately on shutdown
backend.setsockopt(zmq.LINGER, 0)
frontend.setsockopt(zmq.LINGER, 0)
class ZActor(object):
# ...
def __init__(self, ctx, actor, *args, **kwargs):
# ...
self.pipe, self.shim_pipe = zhelper.zcreate_pipe(ctx)
# ...
def run(self):
self.shim_handler(*self.shim_args, **self.shim_kwargs)
self.shim_pipe.set(zmq.SNDTIMEO, 0)
self.shim_pipe.signal()
self.shim_pipe.close()
def destroy(self):
# ...
self.pipe.set(zmq.SNDTIMEO, 0)
self.pipe.send_unicode("$TERM")
self.pipe.wait()
self.pipe.close()
我感兴趣的是 LINGER=0
和 SNDTIMEO=0
的用法。
ZMQ_SNDTIMEO: Maximum time before a send operation returns with EAGAIN
[rather self-explanatory]
ZMQ_LINGER: Set linger period for socket shutdown
[...] The linger period determines how long pending messages which have yet to be sent to a peer shall linger in memory after a socket is closed with zmq_close(3), and further affects the termination of the socket's context with zmq_term(3). [...]
[...]
The value of 0 specifies no linger period. Pending messages shall be discarded immediately when the socket is closed with zmq_close().
[...]
所以简而言之,两个方向的最后一条消息可能都没有发送。如果 send
会阻塞,SNDTIMEO=0
会启动,并且(假设发送队列中仍有内容)LINGER=0
可能会在 close
.[=23 期间丢弃消息=]
这似乎是个坏主意,因为如果 $TERM
被丢弃,actor 不会被杀死,而如果 signal
被丢弃,调用线程只会阻塞。对我来说唯一有意义的方法是如果消息可能永远不会被丢弃(因为 PAIR
over inproc://
传输的某些特性?),但是,为什么首先使用套接字选项?
是什么让这段代码按预期工作,为什么要这样使用套接字选项,以及在什么情况下should/shouldn我不遵循这个例子?
对我来说这看起来像是一个潜在的错误 (deadlock/hang)。如果 actor 没有足够快地读取发送给它的消息,队列(大小 'hwm')可能已满 - 这意味着 zmq 不会发送任何东西,并且 destroy() 将最终等待信号actor 退出时预期 - 但由于 actor 从未收到“$TERM”,它无法做出反应 - 除非其 recv() 中存在超时,否则它也可能永远等待消息。
[我注意到在 destroy() 方法中的 wait() 之前似乎有一条持怀疑态度的评论 - 所以您可能不是第一个注意到这一点的人]
我会小心处理 destroy() - 实际上,您可以编写您的解决方案,以便极不可能溢出队列 - 或者您可以检查发送是否在 destroy() 中成功 - 如果没有 - 或者再试一次(超时)或跳过 wait()。