解决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 greenlet实现原理和使用示例
Sep 24 Python
Python json模块使用实例
Apr 11 Python
python通过ssh-powershell监控windows的方法
Jun 02 Python
python实现爬虫统计学校BBS男女比例之数据处理(三)
Dec 31 Python
Python学习小技巧之利用字典的默认行为
May 20 Python
R语言 vs Python对比:数据分析哪家强?
Nov 17 Python
python中的插值 scipy-interp的实现代码
Jul 23 Python
python实现将汉字保存成文本的方法
Nov 16 Python
python多线程+代理池爬取天天基金网、股票数据过程解析
Aug 13 Python
Python如何基于selenium实现自动登录博客园
Dec 16 Python
Python3实现飞机大战游戏
Apr 24 Python
Python matplotlib可视化实例解析
Jun 01 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
咖啡语言
2021/03/03 咖啡文化
探讨:web上存漏洞及原理分析、防范方法
2013/06/29 PHP
php表单提交与$_POST实例分析
2015/01/26 PHP
浅谈COOKIE和SESSION区别
2015/07/19 PHP
Smarty模板常见的简单应用分析
2016/11/15 PHP
php接口实现拖拽排序功能
2018/04/23 PHP
PHP+MySQL实现输入页码跳转到指定页面功能示例
2018/06/01 PHP
jQuery.extend 函数详解
2012/02/03 Javascript
IE的fireEvent方法概述及应用
2013/02/22 Javascript
Json对象与Json字符串互转(4种转换方式)
2013/03/27 Javascript
IE中JS跳转丢失referrer问题的2个解决方法
2014/07/18 Javascript
使用jQuery实现图片遮罩半透明坠落遮挡
2015/03/16 Javascript
js由下向上不断上升冒气泡效果实例
2015/05/07 Javascript
Jquery实现弹性滑块滑动选择数值插件
2015/08/08 Javascript
JSON遍历方式实例总结
2015/12/07 Javascript
js获取Get值的方法
2016/09/29 Javascript
基于jquery实现左右上下移动效果
2018/05/02 jQuery
React组件内事件传参实现tab切换的示例代码
2018/07/04 Javascript
JQuery通过后台获取数据遍历到前台的方法
2018/08/13 jQuery
原生javascript实现连连看游戏
2019/01/03 Javascript
JavaScript 异步时序问题
2020/11/20 Javascript
python实现备份目录的方法
2015/08/03 Python
Python编程入门之Hello World的三种实现方式
2015/11/13 Python
Python中read()、readline()和readlines()三者间的区别和用法
2017/07/30 Python
python 简单搭建阻塞式单进程,多进程,多线程服务的实例
2017/11/01 Python
Python 错误和异常代码详解
2018/01/29 Python
使用memory_profiler监测python代码运行时内存消耗方法
2018/12/03 Python
Python中变量的输入输出实例代码详解
2019/07/28 Python
Python综合应用名片管理系统案例详解
2020/01/03 Python
Tensorflow tf.tile()的用法实例分析
2020/05/22 Python
Timex手表官网:美国运动休闲手表品牌
2017/01/28 全球购物
Under Armour安德玛法国官网:美国高端运动科技品牌
2018/06/29 全球购物
东芝官网商城:还原日式美学,打造美好生活
2018/12/27 全球购物
2014银行领导班子群众路线对照检查材料思想汇报
2014/09/17 职场文书
项目技术负责人岗位职责
2015/04/13 职场文书
分布式Redis Cluster集群搭建与Redis基本用法
2022/02/24 Redis