一段时间后RabbitMQ连接因某种原因关闭

3 投票
3 回答
10307 浏览
提问于 2025-04-17 20:54

我正在使用pika这个Python库来连接本地的RabbitMQ服务器。

class BaseRabbitSender(MessageSender):
    __metaclass__ = ABCMeta

    def __init__(self, host):
        self.node = BaseMessagingNode(host)
        self.connection = pika.BlockingConnection(pika.ConnectionParameters(
            host=host))
        self.channel = self.connection.channel()

    @abstractmethod
    def send_message(self, message):
        pass

    def close_connection(self):
        self.connection.close()


class DirectRabbitSender(BaseRabbitSender):
    def __init__(self, host, queue_name):
        super(DirectRabbitSender, self).__init__(host)
        self.queue_name = queue_name
        self.channel.queue_declare(queue=queue_name, durable=True)

    def send_message(self, message):
        self.channel.basic_publish(exchange='',
                                   routing_key=self.queue_name,
                                   body=message,
                                   properties=pika.BasicProperties(
                                       delivery_mode=2,
                                   ))

    def close_connection(self):
        self.connection.close()

但是过了一段时间(比如几天后),我就会遇到错误。

 File "build/bdist.linux-x86_64/egg/pika/adapters/blocking_connection.py", line 560, in basic_publish
    (properties, body), False)
  File "build/bdist.linux-x86_64/egg/pika/adapters/blocking_connection.py", line 1147, in _send_method
    self.connection.send_method(self.channel_number, method_frame, content)
  File "build/bdist.linux-x86_64/egg/pika/adapters/blocking_connection.py", line 267, in send_method
    self._send_method(channel_number, method_frame, content)
  File "build/bdist.linux-x86_64/egg/pika/connection.py", line 1504, in _send_method
    self._send_frame(frame.Header(channel_number, length, content[0]))
  File "build/bdist.linux-x86_64/egg/pika/adapters/blocking_connection.py", line 410, in _send_frame
    self.process_data_events()
  File "build/bdist.linux-x86_64/egg/pika/adapters/blocking_connection.py", line 236, in process_data_events
    raise exceptions.ConnectionClosed()
ConnectionClosed

这是RabbitMQ服务器的日志

=INFO REPORT==== 3-Mar-2014::15:11:03 ===
accepting AMQP connection <0.26625.0> (127.0.0.1:41846 -> 127.0.0.1:5672)

=ERROR REPORT==== 3-Mar-2014::15:38:12 ===
closing AMQP connection <0.326.0> (127.0.0.1:58580 -> 127.0.0.1:5672):
{heartbeat_timeout,running}

=WARNING REPORT==== 3-Mar-2014::16:11:04 ===
closing AMQP connection <0.26625.0> (127.0.0.1:41846 -> 127.0.0.1:5672):
connection_closed_abruptly

=INFO REPORT==== 3-Mar-2014::16:11:05 ===
accepting AMQP connection <0.27016.0> (127.0.0.1:37776 -> 127.0.0.1:5672)

=ERROR REPORT==== 3-Mar-2014::17:41:05 ===
closing AMQP connection <0.27016.0> (127.0.0.1:37776 -> 127.0.0.1:5672):
{heartbeat_timeout,running}

它运行在Ubuntu 13.10上,RabbitMQ版本是3.1.3。

我不太明白发生了什么。你能解释一下吗?

3 个回答

1

我有一些测试想要运行。在我的本地环境中一切正常,但当我在服务器上运行这些测试时,遇到了和这个问题一模一样的情况。我检查了一下我的 pika 版本,是 0.9.13。顺便说一下,我也在使用 BlockingConnection

首先,我尝试定期调用 process_data_events(),但没有成功。
其次,我尝试在每次发布消息或打开新队列时都新建一个连接和通道,但也没用。
第三,我尝试把 pika 升级到 0.9.14,结果还是不行。

在这里的一个讨论中,有人提到可能是 socket 的bug。所以,我检查了Python的版本,猜测可能真有bug,并且在后来的Python版本中修复了。在服务器上,Python版本是 2.7.3,而我本地的版本是 2.7.12。为了测试Python版本是否真的是问题,我安装了 conda,创建了一个Python版本为 2.7.3 的环境。我运行了测试,结果通过了(我无法重现这个问题)。

经过以上尝试,我又想到了一个新的假设,可能是我服务器上的 rabbitmq-server 有bug。我比较了一下版本:在本地是最新的(3.6.5),而在服务器上是 2.8.4。为了确认这是否真的是问题,我运行了测试,但这次我用了一个远程的、版本更新的rabbitmq。一切都正常。所以,我升级了 rabbitmq-server,结果问题就消失了!

总结:
解决办法就是升级你的 rabbitmq-server

3

相关的日志信息是:{heartbeat_timeout,running}。

有些东西让BlockingConnection无法发送心跳信号,所以RabbitMQ认为你的客户端无法连接或者已经死掉了。你有三种解决办法:

  • 避免阻塞的行为
  • 增加心跳信号的间隔时间
  • 尝试其他的连接方式,比如Tornado。
2

其实,真正的问题是我把rabbitmq-server给停掉了。而pika这个库在处理断开连接的时候并不好使。

撰写回答