我的python脚本一旦从另一个数据源收到消息,就不得不向RabbitMQ发送消息。 python脚本发送它们的频率可以变化,例如1分钟到30分钟。
以下是我与RabbitMQ建立连接的方法:
rabt_conn = pika.BlockingConnection(pika.ConnectionParameters("some_host"))
channel = rbt_conn.channel()
我刚刚遇到异常
pika.exceptions.ConnectionClosed
如何重新连接?最好的方法是什么?有没有"策略"?是否有能力发送ping来保持连接活动或设置超时?
任何指针都将受到赞赏。
答案 0 :(得分:12)
RabbitMQ使用心跳来检测并关闭" dead"连接并防止网络设备(防火墙等)终止"空闲"连接。从版本3.5.5开始,默认超时设置为60秒(之前为~10分钟)。来自docs:
每隔超时/ 2秒发送一次心跳帧。在两次错过心跳后,该对等体被认为无法访问。
Pika BlockingConnection 的问题在于,在进行某些API调用之前,它无法响应心跳(例如,channel.basic_publish()
,connection.sleep()
,等)。
到目前为止我找到的方法:
RabbitMQ在建立连接时与客户端协商超时。从理论上讲,应该可以使用heartbeat_interval
参数覆盖较大的服务器默认值,但当前的Pika版本(0.10.0)在提供的值之间使用 min 值由服务器和客户端。此问题已在当前master上修复。
另一方面,可以通过将heartbeat_interval
参数设置为0
来完全停用心跳功能,这可能会引发新问题(防火墙丢弃连接等)
扩展@ 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()
我尚未探索的其他可能性:
connection.sleep()
来响应服务器心跳。答案 1 :(得分:7)
死亡简单:像这样的一些模式。
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)
您可能需要对代码进行重新分解,但基本上是关于捕获异常,缓解问题并继续执行您的操作。
communication_handles
包含所有的pika元素,如频道,队列以及您的东西需要通过鼠兔与RabbitMQ进行通信的任何内容。