解决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调用shell的方法
Nov 20 Python
python二叉树的实现实例
Nov 21 Python
深入探究Django中的Session与Cookie
Jul 30 Python
python实现k-means聚类算法
Feb 23 Python
Django开发中复选框用法示例
Mar 20 Python
通过selenium抓取某东的TT购买记录并分析趋势过程解析
Aug 15 Python
Python facenet进行人脸识别测试过程解析
Aug 16 Python
python使用for...else跳出双层嵌套循环的方法实例
May 17 Python
Android Q之气泡弹窗的实现示例
Jun 23 Python
pytorch 限制GPU使用效率详解(计算效率)
Jun 27 Python
详解Python 中的容器 collections
Aug 17 Python
利用python+request通过接口实现人员通行记录上传功能
Jan 13 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
说说掌握JavaScript语言的思想前提想学习js的朋友可以看看
2009/04/01 Javascript
javascript获取当前鼠标坐标的方法
2015/01/10 Javascript
JavaScript实现当网页加载完成后执行指定函数的方法
2015/03/21 Javascript
jQuery选择器源码解读(三):tokenize方法
2015/03/31 Javascript
js实现的动画导航菜单效果代码
2015/09/10 Javascript
javascript跑马灯抽奖实例讲解
2020/04/17 Javascript
简介BootStrap model弹出框的使用
2016/04/27 Javascript
javascript 用函数实现继承详解
2016/05/28 Javascript
jquery常用的12个小功能
2016/07/22 Javascript
妙用Bootstrap的 popover插件实现校验表单提示功能
2016/08/29 Javascript
jQuery实现点击后高亮背景固定显示的菜单效果【附demo源码下载】
2016/09/21 Javascript
jquery+css实现下拉列表功能
2017/09/03 jQuery
JavaScript门面模式详解
2017/10/19 Javascript
jQuery实现checkbox全选功能完整实例
2018/07/12 jQuery
js/jQuery实现全选效果
2019/06/17 jQuery
微信小程序商品详情页底部弹出框
2019/11/22 Javascript
如何在sae中设置django,让sae的工作环境跟本地python环境一致
2017/11/21 Python
python实现简单登陆流程的方法
2018/04/22 Python
Python数据结构之图的应用示例
2018/05/11 Python
Python中最好用的命令行参数解析工具(argparse)
2019/08/23 Python
python实现字典嵌套列表取值
2019/12/16 Python
Python semaphore evevt生产者消费者模型原理解析
2020/03/18 Python
解决python虚拟环境切换无效的问题
2020/04/30 Python
手把手教你从PyCharm安装到激活(最新激活码),亲测有效可激活至2089年
2020/11/25 Python
Django filter动态过滤与排序实现过程解析
2020/11/26 Python
eBay法国购物网站:eBay.fr
2017/10/21 全球购物
澳大利亚婴儿、幼儿和儿童在线设计师商店:Smooch Baby
2019/02/16 全球购物
《每逢佳节倍思亲》教后反思
2014/04/19 职场文书
室内设计专业自荐信
2014/05/31 职场文书
选秀节目策划方案
2014/06/06 职场文书
2015年高校辅导员工作总结
2015/04/20 职场文书
2015年幼儿园保育员工作总结
2015/04/23 职场文书
Nginx下配置Https证书详细过程
2021/04/01 Servers
python实现自动化群控的步骤
2021/04/11 Python
javascript拖曳互换div的位置实现示例
2021/06/28 Javascript
【海涛教你打DOTA】死灵飞龙第一视角解说
2022/04/01 DOTA