ZeroMQ工作人员应该如何安全地“挂断”?

2024-05-17 04:35:39 发布

您现在位置:Python中文网/ 问答频道 /正文

本周我开始使用ZeroMQ,当使用请求-响应模式时,我不确定如何让一个工作人员安全地“挂断”并关闭其套接字,而不可能丢弃消息,并导致发送该消息的客户永远得不到响应。想象一下一个用Python编写的工人,他看起来像这样:

import zmq
c = zmq.Context()
s = c.socket(zmq.REP)
s.connect('tcp://127.0.0.1:9999')
while i in range(8):
    s.recv()
    s.send('reply')
s.close()

我一直在做实验,发现在套接字类型zmq.REQ127.0.0.1:9999中,发出公平队列请求的客户可能会不幸地让公平队列算法在工作人员完成最后一个send()之后,但在运行下面的close()方法之前选择上面的工作人员。在这种情况下,请求似乎由工作进程中的MQ堆栈接收和缓冲,然后当close()抛出与套接字相关的所有内容时,请求将丢失。

一个工人如何才能“安全地”分离——有没有任何方法可以发出“我不再需要消息”的信号,然后(a)在信号传输过程中循环任何到达的最终消息,(b)生成它们的回复,然后(c)在保证没有消息被丢弃的情况下执行close()

编辑:我想输入的原始状态是“半关闭”状态,如果不能接收到更多的请求(发送方也知道),但是返回路径仍然打开,这样我就可以检查传入缓冲区中最后到达的一条消息,如果缓冲区中有一条消息,就可以对其进行响应。

编辑:针对一个好问题,更正了说明以使等待消息的数量多元化,因为可能有许多连接在等待答复。


Tags: 方法send消息编辑close客户信号公平
3条回答

你似乎认为你在试图避免一个“简单”的种族状况,比如

... = zmq_recv(fd);
do_something();
zmq_send(fd, answer);
/* Let's hope a new request does not arrive just now, please close it quickly! */
zmq_close(fd);

但我认为问题是公平排队(循环)使事情变得更加困难:您甚至可能已经在您的工人上有几个排队的请求。如果轮到发送者接收新请求,则发送者在发送新请求之前不会等待工作者空闲,因此在您调用zmq_send时,其他请求可能已经在等待。

实际上,看起来您可能选择了错误的数据方向。与其让请求池向工作人员发送请求(即使您不希望接收新请求),不如让工作人员从请求队列中获取新请求,处理它,然后发送答案。

当然,这意味着使用XREP/XREQ,但我认为这是值得的。

编辑:我写了some code实现the other direction来解释我的意思。

我认为问题在于您的消息传递体系结构是错误的。您的工人应该使用REQ套接字来发送工作请求,这样就只有一个工作在工人处排队。然后为了确认工作的完成,您可以使用另一个REQ请求,该请求可以作为前一个作业的ack并请求一个新作业,或者您可以有第二个控制套接字。

有些人使用PUB/SUB作为控件,这样每个工作进程都发布ack,而主进程订阅ack。

您必须记住,使用ZeroMQ有0个消息队列。一点也没有!只在发送方或接收方缓冲消息,这取决于设置,如高水位线和插座类型。如果您真的需要消息队列,那么您需要编写一个代理应用程序来处理这个问题,或者只需切换到AMQP,其中所有通信都是通过第三方代理进行的。

我也一直在想这个。您可能希望实现一个关闭消息,通知客户工人要离开。然后你可以让工人在关闭之前排干一段时间的水。当然,这并不理想,但可能是可行的。

相关问题 更多 >