解决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 相关文章推荐
推荐11个实用Python库
Jan 23 Python
在Python中使用正则表达式的方法
Aug 13 Python
Python实现树莓派WiFi断线自动重连的实例代码
Mar 16 Python
利用python为运维人员写一个监控脚本
Mar 25 Python
Python cookbook(数据结构与算法)将多个映射合并为单个映射的方法
Apr 19 Python
python实现将一个数组逆序输出的方法
Jun 25 Python
Python实现快速傅里叶变换的方法(FFT)
Jul 21 Python
python 实现语音聊天机器人的示例代码
Dec 02 Python
Python自动采集微信联系人的实现示例
Feb 28 Python
Python3 assert断言实现原理解析
Mar 02 Python
python构造IP报文实例
May 05 Python
Python实现Appium端口检测与释放的实现
Dec 31 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解决URL中文GBK乱码问题的两种方法
2014/06/03 PHP
PHP使用Mysql事务实例解析
2014/09/08 PHP
linux下为php添加iconv模块的方法
2016/02/28 PHP
PHP中抽象类和抽象方法概念与用法分析
2016/05/24 PHP
workerman结合laravel开发在线聊天应用的示例代码
2018/10/30 PHP
Extjs Ext.MessageBox.confirm 确认对话框详解
2010/04/02 Javascript
js换图片效果可进行定时操作
2014/06/09 Javascript
jQuery的text()方法用法分析
2014/12/20 Javascript
javascript模拟map输出与去除重复项的方法
2015/02/09 Javascript
JavaScript获取指定元素位置的方法
2015/04/08 Javascript
jquery捕捉回车键及获取checkbox值与异步请求的方法
2015/12/24 Javascript
js HTML5 Ajax实现文件上传进度条功能
2016/02/13 Javascript
jQuery结合jQuery.cookie.js插件实现换肤功能示例
2017/10/14 jQuery
使用Vue组件实现一个简单弹窗效果
2018/04/23 Javascript
layer页面跳转,获取html子节点元素的值方法
2019/09/27 Javascript
Python的动态重新封装的教程
2015/04/11 Python
python对url格式解析的方法
2015/05/13 Python
python任务调度实例分析
2015/05/19 Python
ubuntu系统下 python链接mysql数据库的方法
2017/01/09 Python
Python数据结构与算法之二叉树结构定义与遍历方法详解
2017/12/12 Python
Python批量合并有合并单元格的Excel文件详解
2018/04/05 Python
详解Python最长公共子串和最长公共子序列的实现
2018/07/07 Python
Python装饰器简单用法实例小结
2018/12/03 Python
在 Pycharm 安装使用black的方法详解
2020/04/02 Python
scrapy爬虫:scrapy.FormRequest中formdata参数详解
2020/04/30 Python
html5 Canvas画图教程(1)—画图的基本常识
2013/01/09 HTML / CSS
推荐WEB开发者最佳HTML5和CSS3代码生成器
2015/11/24 HTML / CSS
GNC健安喜美国官网:美国第一营养品牌
2016/07/22 全球购物
美国大型的健身社区和补充商店:Bodybuilding.com
2016/09/06 全球购物
端口镜像是怎么实现的
2014/03/25 面试题
乡镇党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
现役军人家属慰问信
2015/03/24 职场文书
解决pytorch读取自制数据集出现过的问题
2021/05/31 Python
Java实现简易的分词器功能
2021/06/15 Java/Android
解决Mysql的left join无效及使用的注意事项说明
2021/07/01 MySQL
CSS3中Animation实现简单的手指点击动画的示例
2021/07/15 HTML / CSS