Python 如何重新连接到RabbitMQ?

Python 如何重新连接到RabbitMQ?,python,rabbitmq,pika,Python,Rabbitmq,Pika,我的python脚本从另一个数据源接收消息后,必须不断向RabbitMQ发送消息。python脚本发送它们的频率可能会有所不同,例如,1分钟到30分钟 以下是我如何建立到RabbitMQ的连接: rabt_conn = pika.BlockingConnection(pika.ConnectionParameters("some_host")) channel = rbt_conn.channel() 我只是有个例外 pika.exceptions.ConnectionClosed

我的python脚本从另一个数据源接收消息后,必须不断向RabbitMQ发送消息。python脚本发送它们的频率可能会有所不同,例如,1分钟到30分钟

以下是我如何建立到RabbitMQ的连接:

  rabt_conn = pika.BlockingConnection(pika.ConnectionParameters("some_host"))
  channel = rbt_conn.channel()
我只是有个例外

pika.exceptions.ConnectionClosed
如何重新连接到它?最好的办法是什么?有什么“策略”吗?是否能够发送ping以保持连接活动或设置超时


任何提示都将受到欢迎。

非常简单:一些类似的模式

import time

while True:
    try:
        communication_handles = connect_pika()
        do_your_stuff(communication_handles)
    except pika.exceptions.ConnectionClosed:
        print 'oops. lost connection. trying to reconnect.'
        # avoid rapid reconnection on longer RMQ server outage
        time.sleep(0.5) 
您可能需要重新考虑您的代码,但基本上它是关于捕获异常、缓解问题并继续执行您的工作。
通信\u句柄
包含所有pika元素,如通道、队列以及您的员工通过pika与RabbitMQ通信所需的任何内容。

RabbitMQ使用心跳来检测和关闭“死”连接,并防止网络设备(防火墙等)终止“空闲”连接。从3.5.5版开始,默认超时设置为60秒(以前为10分钟)。从:

心跳帧大约每超时/2秒发送一次。错过两次心跳后,对方被认为无法联系到

Pika的BlockingConnection的问题是,在进行某些API调用之前(例如,
channel.basic\u publish()
connection.sleep()
,等等),它无法响应心跳

到目前为止,我发现的方法是:

增加或停用超时 RabbitMQ在建立连接时与客户端协商超时。理论上,应该可以使用
heartbeat_interval
参数用更大的值覆盖服务器默认值,但当前的Pika版本(0.10.0)使用服务器和客户端提供的值之间的最小值。这个问题是固定的电流

另一方面,通过将
heartbeat\u interval
参数设置为
0
,可以完全停用heartbeat功能,这可能会导致出现新问题(防火墙断开连接等)

重新连接 扩展@itsafire的答案,您可以编写自己的发布者类,以便在需要时重新连接。一个简单的实现示例:

import logging
import json
import pika

class Publisher:
    EXCHANGE='my_exchange'
    TYPE='topic'
    ROUTING_KEY = 'some_routing_key'

    def __init__(self, host, virtual_host, username, password):
        self._params = pika.connection.ConnectionParameters(
            host=host,
            virtual_host=virtual_host,
            credentials=pika.credentials.PlainCredentials(username, password))
        self._conn = None
        self._channel = None

    def connect(self):
        if not self._conn or self._conn.is_closed:
            self._conn = pika.BlockingConnection(self._params)
            self._channel = self._conn.channel()
            self._channel.exchange_declare(exchange=self.EXCHANGE,
                                           type=self.TYPE)

    def _publish(self, msg):
        self._channel.basic_publish(exchange=self.EXCHANGE,
                                    routing_key=self.ROUTING_KEY,
                                    body=json.dumps(msg).encode())
        logging.debug('message sent: %s', msg)

    def publish(self, msg):
        """Publish msg, reconnecting if necessary."""

        try:
            self._publish(msg)
        except pika.exceptions.ConnectionClosed:
            logging.debug('reconnecting to queue')
            self.connect()
            self._publish(msg)

    def close(self):
        if self._conn and self._conn.is_open:
            logging.debug('closing queue connection')
            self._conn.close()
其他可能性 我尚未探索的其他可能性:

  • 将RabbitMQ连接和“发布”代码保留在后台线程上,该线程定期调用
    connection.sleep()
    ,以响应服务器心跳

您可以尝试gearman模块,请检查此项。用于创建客户端和工作程序连接。在这里,您的python脚本将是客户端,rabbitmq将是客户端worker@PrashantPuri,我不想使用任何api来完成如此简单的任务@PrashantPuri,您是否使用web服务api打开终端?或者重新启动您的计算机?它不是api,而是通用的应用程序框架,允许您并行工作、负载平衡处理以及在不同语言之间调用函数。@PrashantPuri,您是否使用框架添加2和2?或者您只是调用+?很好,但是这个解决方案将进入最大的递归深度,以防服务器离开更长的时间。这只是如何处理断开连接的指针。我添加了一个关于如何处理langer服务器中断的可选建议。还可以添加一个宽限计数器,以便在尝试过多重新连接时最终退出。击倒自己。可以与结合使用,在放弃之前重试N次,以避免无限次的重新连接尝试/重试/递归等。