解决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记录详细调用堆栈日志的方法
May 05 Python
使用Python的Bottle框架写一个简单的服务接口的示例
Aug 25 Python
python实现机器人行走效果
Jan 29 Python
python找出一个列表中相同元素的多个索引实例
Jun 11 Python
PYTHON EVAL的用法及注意事项解析
Sep 06 Python
python plt可视化——打印特殊符号和制作图例代码
Apr 17 Python
python判断是空的实例分享
Jul 06 Python
4种非常实用的python内置数据结构
Apr 28 Python
Python数据分析入门之教你怎么搭建环境
May 13 Python
pytorch--之halfTensor的使用详解
May 24 Python
pytorch 梯度NAN异常值的解决方案
Jun 05 Python
python manim实现排序算法动画示例
Aug 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
js和php邮箱地址验证的实现方法
2014/01/09 PHP
浅谈php自定义错误日志
2015/02/13 PHP
PHP基于递归算法解决兔子生兔子问题
2018/05/11 PHP
在Laravel中实现使用AJAX动态刷新部分页面
2019/10/15 PHP
javascript之dhDataGrid Ver2.0.0代码
2007/07/01 Javascript
Firefox中beforeunload事件的实现缺陷浅析
2012/05/03 Javascript
如何在JavaScript中实现私有属性的写类方式(一)
2013/12/04 Javascript
Js操作树节点自动折叠展开的几种方法
2014/05/05 Javascript
Javascript验证用户输入URL地址是否为空及格式是否正确
2014/10/09 Javascript
用JavaScript显示浏览器客户端信息的超相近教程
2015/06/18 Javascript
js实现二级菜单渐隐显示
2015/11/03 Javascript
Vue 过渡(动画)transition组件案例详解
2017/01/22 Javascript
实例详解display:none与visible:hidden的区别
2017/03/30 Javascript
使用DataTable插件实现异步加载数据
2017/11/19 Javascript
解决select2在bootstrap modal中不能正常使用的问题
2018/08/09 Javascript
使用JS判断页面是首次被加载还是刷新
2019/05/26 Javascript
JS async 函数的含义和用法实例总结
2020/04/08 Javascript
新手常见6种的python报错及解决方法
2018/03/09 Python
python操作xlsx文件的包openpyxl实例
2018/05/03 Python
pyqt5实现按钮添加背景图片以及背景图片的切换方法
2019/06/13 Python
python实现京东订单推送到测试环境,提供便利操作示例
2019/08/09 Python
Python爬虫实现使用beautifulSoup4爬取名言网功能案例
2019/09/15 Python
Python cookie的保存与读取、SSL讲解
2020/02/17 Python
python实现在线翻译功能
2020/03/03 Python
Python3监控windows,linux系统的CPU、硬盘、内存使用率和各个端口的开启情况详细代码实例
2020/03/18 Python
HTML5是什么 HTML5是什么意思 HTML5简介
2012/10/26 HTML / CSS
AmazeUI 平滑滚动效果的示例代码
2020/08/20 HTML / CSS
德国柯吉澳趣味家居:Koziol
2017/08/24 全球购物
酒店应聘自荐信
2013/11/09 职场文书
新闻专业推荐信范文
2013/11/20 职场文书
公司会议策划方案
2014/05/17 职场文书
机械设备与数控技术专业求职信
2014/08/10 职场文书
对党的十八届四中全会的期盼
2014/10/17 职场文书
歌咏比赛主持词
2015/06/29 职场文书
节约用水广告语60条
2019/11/14 职场文书
基于Android10渲染Surface的创建过程
2022/08/14 Java/Android