解决python3 pika之连接断开的问题


Posted in Python onDecember 18, 2018

问题描述

在消费rabbitMQ队列时, 每次进入回调函数内需要进行一些比较耗时的操作;操作完成后给rabbitMQ server发送ack信号以dequeue本条消息。

问题就发生在发送ack操作时, 程序提示链接已被断开或socket error。

源码示例

#!/usr/bin
#coding: utf-8

import pika
import time


USER = 'guest'
PWD = 'guest'
TEST_QUEUE = 'just4test'

def callback(ch, method, properties, body):
 print(body)
 time.sleep(600)
 ch.basic_publish('', routing_key=TEST_QUEUE, body="fortest")
 ch.basic_ack(delivery_tag = method.delivery_tag)

def test_main():
 s_conn = pika.BlockingConnection(
  pika.ConnectionParameters('127.0.0.1', 
   credentials=pika.PlainCredentials(USER, PWD)))
 chan = s_conn.channel()
 chan.queue_declare(queue=TEST_QUEUE)

 chan.basic_publish('', routing_key=TEST_QUEUE, body="fortest")
 chan.basic_consume(callback, queue=TEST_QUEUE)
 chan.start_consuming()

if __name__ == "__main__":
 test_main()

运行一段时间后, 就会报错:

[ERROR][pika.adapters.base_connection][2017-08-18 12:33:49]Error event 25, None
[CRITICAL][pika.adapters.base_connection][2017-08-18 12:33:49]Tried to handle an error where no error existed
[ERROR][pika.adapters.base_connection][2017-08-18 12:33:49]Fatal Socket Error: BrokenPipeError(32, 'Broken pipe')

问题排查

猜测:pika客户端没有及时发送心跳,连接被server断开

一开始修改了heartbeat_interval参数值, 示例如下:

def test_main():
 s_conn = pika.BlockingConnection(
  pika.ConnectionParameters('127.0.0.1', 
   heartbeat_interval=10,
   socket_timeout=5,
   credentials=pika.PlainCredentials(USER, PWD)))
 # ....

修改后运行依然报错,后来想想应该单线程被一直占用,pika无法发送心跳;

于是又加了个心跳线程, 示例如下:

#!/usr/bin
#coding: utf-8

import pika
import time
import logging
import threading

USER = 'guest'
PWD = 'guest'
TEST_QUEUE = 'just4test'

class Heartbeat(threading.Thread):
 def __init__(self, connection):
  super(Heartbeat, self).__init__()
  self.lock = threading.Lock()
  self.connection = connection
  self.quitflag = False
  self.stopflag = True
  self.setDaemon(True)

 def run(self):
  while not self.quitflag:
   time.sleep(10)
   self.lock.acquire()
   if self.stopflag :
    self.lock.release()
    continue
   try:
    self.connection.process_data_events()
   except Exception as ex:
    logging.warn("Error format: %s"%(str(ex)))
    self.lock.release()
    return
   self.lock.release()

 def startHeartbeat(self):
  self.lock.acquire()
  if self.quitflag==True:
   self.lock.release()
   return
  self.stopflag=False
  self.lock.release()

def callback(ch, method, properties, body):
 logging.info("recv_body:%s" % body)
 time.sleep(600)
 ch.basic_ack(delivery_tag = method.delivery_tag)

def test_main():
 s_conn = pika.BlockingConnection(
  pika.ConnectionParameters('127.0.0.1', 
   heartbeat_interval=10,
   socket_timeout=5,
   credentials=pika.PlainCredentials(USER, PWD)))
 chan = s_conn.channel()
 chan.queue_declare(queue=TEST_QUEUE)
 chan.basic_consume(callback,
      queue=TEST_QUEUE)

 heartbeat = Heartbeat(s_conn)
 heartbeat.start()   #开启心跳线程
 heartbeat.startHeartbeat()
 chan.start_consuming()

if __name__ == "__main__":
 test_main()

尝试运行,结果还是不行,不得不安静下来思考自己是不是想错了。

去看它的api,看到heartbeat_interval的解析:

:param int heartbeat_interval: How often to send heartbeats.
         Min between this value and server's proposal
         will be used. Use 0 to deactivate heartbeats
         and None to accept server's proposal.

按这样说法,应该还是没有把心跳值给设置好。上面的程序期望是10秒发一次心跳,但是理论上发送心跳的间隔会比10秒多一点。所以艾玛,我应该是把heartbeat_interval的作用搞错了, 它是指超过这个时间间隔不发心跳或不给server任何信息,server就会断开连接, 而不是说pika会按这个间隔来发心跳。 结果我把heartbeat_interval值设置高一点(比实际发送心跳/信息的间隔更长),比如上面设置成60秒,就正常运行了。

如果不指定heartbeat_interval, 它默认为None, 意味着按rabbitMQ server的配置来检测心跳是否正常。

如果设置heartbeat_interval=0, 意味着不检测心跳,server端将不会主动断开连接。

以上这篇解决python3 pika之连接断开的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python django集成cas验证系统
Jul 14 Python
python输出指定月份日历的方法
Apr 23 Python
安装Python的web.py框架并从hello world开始编程
Apr 25 Python
python使用nntp读取新闻组内容的方法
May 08 Python
Python中IPYTHON入门实例
May 11 Python
Python中zfill()方法的使用教程
May 20 Python
Python运算符重载用法实例
May 28 Python
python基于xmlrpc实现二进制文件传输的方法
Jun 02 Python
Python使用filetype精确判断文件类型
Jul 02 Python
python的格式化输出(format,%)实例详解
Jun 01 Python
python 借助numpy保存数据为csv格式的实现方法
Jul 04 Python
python基本算法之实现归并排序(Merge sort)
Sep 01 Python
Python实现繁?转为简体的方法示例
Dec 18 #Python
python 自动重连wifi windows的方法
Dec 18 #Python
浅谈python中真正关闭socket的方法
Dec 18 #Python
对python中dict和json的区别详解
Dec 18 #Python
BP神经网络原理及Python实现代码
Dec 18 #Python
python 执行文件时额外参数获取的实例
Dec 18 #Python
python实现基于信息增益的决策树归纳
Dec 18 #Python
You might like
ie与session丢失(新窗口cookie丢失)实测及解决方案
2013/07/15 PHP
用JavaScript实现仿Windows关机效果
2007/03/10 Javascript
javascript禁用键盘功能键让右击及其他键无效
2013/10/09 Javascript
js中opener与parent的区别详细解析
2014/01/14 Javascript
Javascript中对象继承的实现小例
2014/05/12 Javascript
JavaScript制作简易的微信打飞机
2015/03/31 Javascript
详解javascript函数的参数
2015/11/10 Javascript
jQuery+canvas实现简单的球体斜抛及颜色动态变换效果
2016/01/28 Javascript
百度地图API之百度地图退拽标记点获取经纬度的实现代码
2017/01/12 Javascript
JavaScript实现隐藏省略文字效果的方法
2017/04/27 Javascript
node.js中fs.stat与fs.fstat的区别详解
2017/06/01 Javascript
小程序转发探索示例
2019/02/19 Javascript
D3.js(v3)+react 实现带坐标与比例尺的散点图 (V3版本)
2019/05/09 Javascript
nodejs简单抓包工具使用详解
2019/08/23 NodeJs
解决Vue在Tomcat8下部署页面不加载的问题
2019/11/12 Javascript
微信小程序swiper组件实现抖音翻页切换视频功能的实例代码
2020/06/24 Javascript
python在命令行下使用google翻译(带语音)
2014/01/16 Python
对于Python的Django框架使用的一些实用建议
2015/04/03 Python
Python机器学习之K-Means聚类实现详解
2018/02/22 Python
Python的UTC时间转换讲解
2019/02/26 Python
python爬虫工具例举说明
2020/11/30 Python
用python对excel进行操作(读,写,修改)
2020/12/25 Python
python Timer 类使用介绍
2020/12/28 Python
selenium+python自动化78-autoit参数化与批量上传功能的实现
2021/03/04 Python
详解HTML5 Canvas绘制不规则图形时的非零环绕原则
2016/03/21 HTML / CSS
中国领先的专业演出票务网:永乐票务
2016/08/29 全球购物
Nili Lotan官网:Nili Lotan同名品牌
2018/01/07 全球购物
GOLFINO英国官网:高尔夫服装
2020/04/11 全球购物
节约用水演讲稿
2014/05/21 职场文书
工作目标责任书
2014/07/23 职场文书
学生打架检讨书
2014/10/20 职场文书
2015年小学生国庆节演讲稿
2015/07/30 职场文书
2016年中秋节慰问信
2015/12/01 职场文书
小学信息技术教学反思
2016/02/16 职场文书
HTML怎么设置下划线?html文字加下划线方法
2021/12/06 HTML / CSS
python使用pycharm安装pyqt5以及相关配置
2022/04/22 Python