解决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环境搭建之OpenCV的步骤方法
Oct 20 Python
python的构建工具setup.py的方法使用示例
Oct 23 Python
Django学习笔记之ORM基础教程
Mar 27 Python
Python 查找字符在字符串中的位置实例
May 02 Python
python pandas修改列属性的方法详解
Jun 09 Python
python通过tcp发送xml报文的方法
Dec 28 Python
解决Pytorch训练过程中loss不下降的问题
Jan 02 Python
Python实现链表反转的方法分析【迭代法与递归法】
Feb 22 Python
python 装饰器功能与用法案例详解
Mar 06 Python
Opencv图像处理:如何判断图片里某个颜色值占的比例
Jun 03 Python
Python使用UDP实现720p视频传输的操作
Apr 24 Python
python数据可视化使用pyfinance分析证券收益示例详解
Nov 20 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
php 表单验证实现代码
2009/03/10 PHP
php简单的留言板与回复功能具体实现
2014/02/19 PHP
自定义min版smarty模板引擎MinSmarty.class.php文件及用法
2016/05/20 PHP
Javascript 通过json自动生成Dom的代码
2010/04/01 Javascript
THREE.JS入门教程(2)着色器-上
2013/01/24 Javascript
JS 实现列表与多选框选择附预览动画
2014/10/29 Javascript
JavaScript实现图片自动加载的瀑布流效果
2016/04/11 Javascript
jQuery1.9+中删除了live以后的替代方法
2016/06/17 Javascript
seajs学习之模块的依赖加载及模块API的导出
2016/10/20 Javascript
基于AGS JS开发自定义贴图图层
2017/03/31 Javascript
Angular2中select用法之设置默认值与事件详解
2017/05/07 Javascript
Three.js实现浏览器变动时进行自适应的方法
2017/09/26 Javascript
详解NodeJs开发微信公众号
2018/05/25 NodeJs
详解基于mpvue微信小程序下载远程图片到本地解决思路
2019/05/16 Javascript
vue项目前端错误收集之sentry教程详解
2019/05/27 Javascript
使用p5.js临摹动态图片
2019/11/04 Javascript
angular8和ngrx8结合使用的步骤介绍
2019/12/01 Javascript
微信小程序实现滑动翻页效果(完整代码)
2019/12/06 Javascript
Python使用代理抓取网站图片(多线程)
2014/03/14 Python
跟老齐学Python之深入变量和引用对象
2014/09/24 Python
Python实现拼接多张图片的方法
2014/12/01 Python
python私有属性和方法实例分析
2015/01/15 Python
python使用7z解压apk包的方法
2015/04/18 Python
django的auth认证,authenticate和装饰器功能详解
2019/07/25 Python
python属于解释语言吗
2020/06/11 Python
Python是怎样处理json模块的
2020/07/16 Python
python爬虫用mongodb的理由
2020/07/28 Python
Python正则re模块使用步骤及原理解析
2020/08/18 Python
详解HTML5 Canvas绘制时指定颜色与透明度的方法
2016/03/25 HTML / CSS
酷瑞网络科技面试题
2012/03/30 面试题
校优秀毕业生主要事迹
2014/05/26 职场文书
门卫岗位职责说明书
2014/08/18 职场文书
市级绿色学校申报材料
2014/08/25 职场文书
简历中自我评价范文
2015/03/11 职场文书
2019年最新证婚词精选集!
2019/06/28 职场文书
Mysql调整优化之四种分区方式以及组合分区
2022/04/13 MySQL