python重试(指数退避算法)
本文实现了一个重试的装饰器,并且使用了指数退避算法。指数退避算法实现还是很简单的。先上代码再详细解释。
1、指数退避算法
2、重试装饰器retry实现
# -*- coding:utf-8 -*-
import time
from random import randint
from struct import Result, ProcedureException def retry(max_retries=3, max_wait_interval=10, period=1, rand=False): def _retry(func): def __retry(*args, **kwargs):
MAX_RETRIES = max_retries
MAX_WAIT_INTERVAL = max_wait_interval
PERIOD = period
RAND = rand retries = 0
error = None
while retries < MAX_RETRIES:
try:
result = func(*args, **kwargs)
if result.code == Result.ERROR:
raise ProcedureException("procedure occur error")
if result.code == Result.TIMEOUT:
raise ProcedureException("procedure request time out")
if result.code == Result.SUCCESS:
return result
except Exception, ex:
error = ex
finally:
sleep_time = min(2 ** retries * PERIOD if not RAND else randint(0, 2 ** retries) * PERIOD, MAX_WAIT_INTERVAL)
time.sleep(sleep_time)
retries += 1
print "第", retries, "次重试, ", "等待" , sleep_time, "秒"
if retries == MAX_RETRIES:
if error:
raise error
else:
raise ProcedureException("unknown")
return __retry
return _retry
这里我们自己定义了两个东西:
1)枚举类Result,标识过程调用的状态,其中有三个状态,成功SUCCESS,失败ERROR,超时TIMEOUT;
2)异常ProcedureException,在retry装饰器中我们判断了状态,如果是失败和超时场景,我们将会抛出这个异常。
这两个东西的实现如下
from enum import Enum, unique @unique
class Result(Enum):
SUCCESS = 0
TIMEOUT = 1
ERROR = 2 class ProcedureException(Exception):
def __init__(self, message):
Exception.__init__(self, message)
retry装饰器会重试以下两个场景:
1)Procedure函数func出现异常:TIMEOUT和ERROR
2)未知异常:Procedure函数func可以抛出未能处理的异常,例如func函数可能是网络读写,遇到网络超时,链接断开等,抛出timeout或者broken pipe。
是否随机:
1)不随机,将会以2**retries,作为重试时间
2)随机,将会在(0,2**retries)之间随机一个数,作为重试时间
其实指数退避算法就是使用随机“抖动”的方式来解决高并发场景下信道碰撞的,但是我们的应用场景也有需要持续增加重试间隔(而不是增加几率)的情况。
3、测试一下
我们测试两个场景,重试10次和随机,重试5次不随机。
1)重试10次,随机,最大间隔10s
# -*- coding:utf-8 -*-
from decorator import retry
from struct import Result @retry(rand=True, max_retries=10, max_wait_interval=10)
def do_something(): class result(object):
def __init__(self, code):
self.code = code
print "########## 调用结果", Result.ERROR, " ############"
return result(Result.ERROR) do_something()
输出结果
/Users/didi/anaconda/bin/python /Users/didi/test/pythoneer/retry/test.py
########## 调用结果 Result.ERROR ############
第 1 次重试, 等待 0 秒
########## 调用结果 Result.ERROR ############
第 2 次重试, 等待 1 秒
########## 调用结果 Result.ERROR ############
第 3 次重试, 等待 2 秒
########## 调用结果 Result.ERROR ############
第 4 次重试, 等待 0 秒
########## 调用结果 Result.ERROR ############
第 5 次重试, 等待 10 秒
########## 调用结果 Result.ERROR ############
第 6 次重试, 等待 10 秒
########## 调用结果 Result.ERROR ############
第 7 次重试, 等待 10 秒
########## 调用结果 Result.ERROR ############
第 8 次重试, 等待 10 秒
########## 调用结果 Result.ERROR ############
第 9 次重试, 等待 10 秒
########## 调用结果 Result.ERROR ############
Traceback (most recent call last):
第 10 次重试, 等待 10 秒
File "/Users/didi/test/pythoneer/retry/test.py", line 14, in <module>
do_something()
File "/Users/didi/test/pythoneer/retry/decorator.py", line 36, in __retry
if error:
struct.ProcedureException: procedure occur error
2)重试5次,不随机,最大间隔10s
# -*- coding:utf-8 -*-
from decorator import retry
from struct import Result @retry(rand=False, max_retries=5, max_wait_interval=10)
def do_something(): class result(object):
def __init__(self, code):
self.code = code
print "########## 调用结果", Result.ERROR, " ############"
return result(Result.ERROR) do_something()
输出结果
/Users/didi/anaconda/bin/python /Users/didi/test/pythoneer/retry/test.py
########## 调用结果 Result.ERROR ############
第 1 次重试, 等待 1 秒
########## 调用结果 Result.ERROR ############
第 2 次重试, 等待 2 秒
########## 调用结果 Result.ERROR ############
第 3 次重试, 等待 4 秒
########## 调用结果 Result.ERROR ############
第 4 次重试, 等待 8 秒
########## 调用结果 Result.ERROR ############
第 5 次重试, 等待 10 秒
Traceback (most recent call last):
File "/Users/didi/test/pythoneer/retry/test.py", line 14, in <module>
do_something()
File "/Users/didi/test/pythoneer/retry/decorator.py", line 37, in __retry
raise error
struct.ProcedureException: procedure occur error
python重试(指数退避算法)的更多相关文章
- 采用指数退避算法实现ajax请求的重发,全部完成时触发回调函数
目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...
- 计算机网络c++实现截断二进制指数退避算法
#include<iostream> #include<vector> #include <stdio.h> #include<stdlib.h> // ...
- [Android Traffic] 调整定时更新的频率(C2DM与退避算法)
转载自: http://blog.csdn.net/kesenhoo/article/details/7395253 Minimizing the Effect of Regular Updates[ ...
- python重试库retryiny源码剖析
上篇博文介绍了常见需要进行请求重试的场景,本篇博文试着剖析有名的python第三方库retrying源码. 在剖析其源码之前,有必要讲一下retrying的用法,方便理解. 安装: pip insta ...
- 用Python实现随机森林算法,深度学习
用Python实现随机森林算法,深度学习 拥有高方差使得决策树(secision tress)在处理特定训练数据集时其结果显得相对脆弱.bagging(bootstrap aggregating 的缩 ...
- Netty 客户端使用指数退避机制实现重连
指数退避 可以理解为每次重连失败时,就把重连时间设置为之前的指数级别.例如 2 秒,4 秒,8 秒...... 亚马逊AWS关于指数退避的两篇文章介绍 AWS 中的错误重试和指数退避 Exponent ...
- Python常用加密解密算法
MD5加密 简介 这是一种使用非常广泛的加密方式,不可逆的,常见16位和32位一般都是md5 实现 import hashlib data = '你好' print(hashlib.md5(data. ...
- Python实现各种排序算法的代码示例总结
Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示 ...
- [0x00 用Python讲解数据结构与算法] 概览
自从工作后就没什么时间更新博客了,最近抽空学了点Python,觉得Python真的是很强大呀.想来在大学中没有学好数据结构和算法,自己的意志力一直不够坚定,这次想好好看一本书,认真把基本的数据结构和算 ...
随机推荐
- 201521123084 《Java程序设计》第8周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 2. 书面作业 本次作业题集集合 1. List中指定元素的删除(题目 ...
- 201521123083《Java程序设计》第12周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...
- 团队作业4---第一次项目冲刺(ALpha)版本 第五天
一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 a.完成所有基础功能 b.正在进行测试调试 四.困难与问题 1.根据测试需求功能,部分基础功能不能实现,性能不达标,后续已完成 ...
- 201521123014 《Java程序设计》第8周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 泛型(编写的代码可被不同类型的对象所重用) Java中一个集合可以放任何类型的对象,因为任何对象都 is-a ...
- 201521123012 《Java程序设计》第八周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 2. 书面作业 1.本次作业题集集合 List中指定元素的删除(题目4 ...
- 201521123052《Java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 学习了更多markdown的知识 参考资料: 百度脑图 XMind 2. 书面作 ...
- 201521044091 《Java程序设计》第3周学习总结
1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 本周学习总结 ...
- Java课程设计---团队博客
课设题目:购物车系统 题目要求: 1.先建立一个文本文件,定义出自己想要的商品.//也可用数据库以商品编号:商品名称:商品品牌:价格作为文件的内容,中间要求用分号或者分割 2.编写程序,定义一个商品类 ...
- 201521123059 《Java程序设计》第十三周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 1.协议 --网络中为了进行数据交换(通信)而建立的规则.标准或约定(=语义+语法+规则),比如http, ...
- linux各类压缩解压命令大全
01-.tar格式解包:[*******]$ tar xvf FileName.tar 打包:[*******]$ tar cvf FileName.tar DirName(注:tar是打包,不是压缩 ...