解决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中的魔法方法深入理解
Jul 09 Python
如何处理Python3.4 使用pymssql 乱码问题
Jan 08 Python
bpython 功能强大的Python shell
Feb 16 Python
Python中使用OpenCV库来进行简单的气象学遥感影像计算
Feb 19 Python
python+pillow绘制矩阵盖尔圆简单实例
Jan 16 Python
Python解析命令行读取参数--argparse模块使用方法
Jan 23 Python
python如何对实例属性进行类型检查
Mar 20 Python
关于python多重赋值的小问题
Apr 17 Python
Python如何使用k-means方法将列表中相似的句子归类
Aug 08 Python
使用python采集Excel表中某一格数据
May 14 Python
Python分析微信好友性别比例和省份城市分布比例的方法示例【基于itchat模块】
May 29 Python
Python 爬取淘宝商品信息栏目的实现
Feb 06 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
使用symfony命令创建项目的方法
2016/03/17 PHP
解析 thinkphp 框架中的部分方法
2017/05/07 PHP
jquery 常用操作整理 基础入门篇
2009/10/14 Javascript
js 动态文字滚动的例子
2011/01/17 Javascript
JQuery扩展插件Validate 5添加自定义验证方法
2011/09/05 Javascript
jquery dialog open后,服务器端控件失效的快速解决方法
2013/12/19 Javascript
通过复制Table生成word和excel的javascript代码
2014/01/20 Javascript
JavaScript实现梯形乘法表的方法
2015/04/25 Javascript
JS实现仿Windows经典风格的选项卡Tab切换代码
2015/10/20 Javascript
深入JavaScript高级程序设计之对象、数组(栈方法,队列方法,重排序方法,迭代方法)
2015/12/01 Javascript
原生js实现class的添加和删除简单代码
2016/07/12 Javascript
基于angularjs实现图片放大镜效果
2016/08/31 Javascript
jQuery判断邮箱格式对错实例代码讲解
2017/04/12 jQuery
详解node HTTP请求客户端 - Request
2017/05/05 Javascript
BootStrap Table 后台数据绑定、特殊列处理、排序功能
2017/05/27 Javascript
Vue源码解读之Component组件注册的实现
2018/08/24 Javascript
python支持断点续传的多线程下载示例
2014/01/16 Python
对Python中9种生成新对象的方法总结
2018/05/23 Python
Python turtle画图库&&画姓名实例
2020/01/19 Python
基于Python fminunc 的替代方法
2020/02/29 Python
python目标检测给图画框,bbox画到图上并保存案例
2020/03/10 Python
纯CSS3实现圆角效果(含IE兼容解决方法)
2014/05/07 HTML / CSS
德国PC硬件网站:CASEKING
2016/10/20 全球购物
阿迪达斯希腊官方网上商店:adidas希腊
2019/04/06 全球购物
Unineed旗下时尚轻奢网站:FABHunt
2019/05/13 全球购物
纽约市的奢华内衣目的地:Anya Lust
2019/08/02 全球购物
法律工作求职自荐信
2013/10/31 职场文书
秦兵马俑教学反思
2014/02/07 职场文书
学生安全教育材料
2014/02/14 职场文书
开学典礼演讲稿
2014/05/23 职场文书
运动员获奖感言
2014/08/15 职场文书
2014领导班子四风问题对照检查材料思想汇报
2014/09/21 职场文书
推普周国旗下讲话稿
2014/09/21 职场文书
单位授权委托书范本
2014/09/26 职场文书
小学2016年第十八届推普周活动总结
2016/04/05 职场文书
pytorch锁死在dataloader(训练时卡死)
2021/05/28 Python