解决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解析html开发库pyquery使用方法
Feb 07 Python
开源软件包和环境管理系统Anaconda的安装使用
Sep 04 Python
TensorFlow中权重的随机初始化的方法
Feb 11 Python
基于python实现简单日历
Jul 28 Python
python中利用numpy.array()实现俩个数值列表的对应相加方法
Aug 26 Python
Python生成验证码、计算具体日期是一年中的第几天实例代码详解
Oct 16 Python
python使用pyecharts库画地图数据可视化的实现
Mar 25 Python
python 数据分析实现长宽格式的转换
May 18 Python
Python Django搭建网站流程图解
Jun 13 Python
python装饰器三种装饰模式的简单分析
Sep 04 Python
python实现测试工具(二)——简单的ui测试工具
Oct 19 Python
Python机器学习之KNN近邻算法
May 14 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 escape URL编码
2008/12/10 PHP
二进制交叉权限微型php类分享
2014/02/07 PHP
浅谈PHP解析URL函数parse_url和parse_str
2014/11/11 PHP
php实现用已经过去多长时间的方式显示时间
2015/06/05 PHP
PHP多维数组转一维数组的简单实现方法
2015/12/23 PHP
PHP7.3.10编译安装教程
2019/10/08 PHP
Laravel使用模型实现like模糊查询的例子
2019/10/24 PHP
laravel框架语言包拓展实现方法分析
2019/11/22 PHP
Laravel统一错误处理为JSON的方法介绍
2020/10/18 PHP
调用HttpHanlder的几种返回方式小结
2013/12/20 Javascript
javascript简单实现命名空间效果
2014/03/06 Javascript
Egret引擎开发指南之运行项目
2014/09/03 Javascript
Bootstrap使用基础教程详解
2016/09/05 Javascript
Vue.js 2.5新特性介绍(推荐)
2017/10/24 Javascript
谈谈JS中的!!
2017/12/07 Javascript
Vue中this.$router.push参数获取方法
2018/02/27 Javascript
JS和Canvas实现图片的预览压缩和上传功能
2018/03/30 Javascript
JS实现DOM删除节点操作示例
2018/04/04 Javascript
jquery轮播图插件使用方法详解
2020/07/31 jQuery
vue项目实现设置根据路由高亮对应的菜单项操作
2020/08/06 Javascript
详谈Vue.js框架下main.js,App.vue,page/index.vue之间的区别
2020/08/12 Javascript
windows系统下Python环境搭建教程
2017/03/28 Python
pycharm 将python文件打包为exe格式的方法
2019/01/16 Python
python儿童学游戏编程知识点总结
2019/06/03 Python
TENSORFLOW变量作用域(VARIABLE SCOPE)
2020/01/10 Python
如何在Python 游戏中模拟引力
2020/03/27 Python
什么是python的列表推导式
2020/05/26 Python
Jupyter Notebook安装及使用方法解析
2020/11/12 Python
个人债务授权委托书范本
2014/10/05 职场文书
2014年质量工作总结
2014/11/22 职场文书
教师节主题班会教案
2015/08/17 职场文书
幼儿园老师新年寄语
2015/08/17 职场文书
先进个人主要事迹范文
2015/11/04 职场文书
2019森林防火宣传标语大全!
2019/07/03 职场文书
简述Java中throw-throws异常抛出
2021/08/07 Java/Android
Python爬虫 简单介绍一下Xpath及使用
2022/04/26 Python