ZeroMQ的可靠性?

时间:2013-08-14 15:46:56

标签: python zeromq

我一直在使用ZeroMQ的请求/响应套接字,以便在Web应用程序和用于卸载处理的从属应用程序之间交换消息。我注意到,在少数情况下,并非所有发送的ZMQ消息都是由另一方实际接收的。即使使用 IPC 协议,我甚至认为这种情况发生了,我认为这种协议非常可靠。

什么可以负责发送的邮件没有发送,而不会产生任何错误?

以下是客户端代码的示例:

# ironic
class ReliableClient(object):
    def _reconnect(self):
        if self.socket:
            self.socket.close()
            self.socket = None

        self.socket = self.context.socket(zmq.REQ)
        self.socket.connect(self.server_url)

        # Give the server 2 sec to respond
        self.socket.RCVTIMEO = 2000
        self.socket.SNDTIMEO = 2000

        self.socket.LINGER = 3

    def __init__(self, server_url=None, server_name=None):
        self.socket = None
        self.server_url = server_url

        if server_name is None:
            self.server_name = server_url
        else:
            self.server_name  = server_name

        self.lock = threading.Lock()
        self.context = zmq.Context()

        self._reconnect()

    def msg(self, msg):
        raw_out = dumps(msg)

        # send
        self.lock.acquire()
        try:
            self.socket.send(
                raw_out,
                copy=True
            )
        except zmq.ZMQError as ex:
            log.exception(ex, '%s: failed to send', self.server_name)
            self.lock.release()
            raise CommunicationError('failed to send')

        # receive
        try:
            raw_in = self.socket.recv()
        except zmq.ZMQError as ex:
            log.exception(ex, '%s: failed to receive', self.server_name)
            raise CommunicationError('failed to receive')
        finally:
            self.lock.release()

        msg_in = loads(raw_in)  

        return msg_in

3 个答案:

答案 0 :(得分:3)

我不熟悉IPC协议,但我已广泛使用ZMQ / TCP。

即使是最简单的ZMQ REQ / REP模式,TCP 也绝不会丢弃消息如果您正确使用它。如果您的网络连接或远程端点出现故障,它可能会无限期挂起,但它永远不会无声地失败。在某些情况下,某些套接字设计会丢弃消息。例如,有些人可能会在达到HWM时丢弃消息。

答案 1 :(得分:2)

  

对于未发送的已发送消息可能负责的是什么,   虽然没有产生任何错误?

如果您正在使用ROUTER套接字来中间从服务器到zmq工作进程的消息,默认情况下,ROUTER将丢弃它们无法传递的任何出站消息。 “无法交付”是什么意思?路由器维护客户端身份到客户端连接的内部映射,并且因为路由器上的所有消息都具有由客户端提供或由路由器自动分配的身份,所以没有相应连接的任何出站消息路线,将被静静地丢弃。

通过告诉ROUTER报告无法传递的消息,您可以确定何时发生此情况,换句话说,ROUTER在无法传递消息时会生成错误。在Java中,方法是routerSocket.setRouterMandatory(true),你只需要找到对应的python(我不是py家伙,哈哈)

如果您确定ROUTER正在丢弃消息,那么问题就变成了原因?在我的情况下,我有一个zmq客户端,它在不同的线程上发送和接收服务器消息,并且接收线程没有足够快地连接来自服务器的初始“Ok”响应,所以这只是一个时间问题。客户。

希望有所帮助

答案 2 :(得分:0)

如果保证两个系统始终处于活动状态(24X7)或仅在两个系统处于活动状态时发送消息,则ZeroMQ可用作在系统之间传输小事件的绝佳方式,作为一种出色的选择。

我们在ZeroMQ pub-sub模式上遇到问题,因为用户速度慢而发送大量消息,我们开始在中间丢失消息。 后来我们转向ActiveMQ嵌入式代理模式,它将消息保存在内存中,直到消费者使用它们。关于ZeroMQ的好事,即使没有发布者,或者发布者稍后会出现,也可以启动订阅者。

活动MQ的限制,在生产者创建队列之前,无法启动从队列读取的消费者。它会明显抛出异常。我们也可以同时使用这两个库并获得最佳效果。