15行Python代码带你轻松理解令牌桶算法


Posted in Python onMarch 21, 2018

在网络中传输数据时,为了防止网络拥塞,需限制流出网络的流量,使流量以比较均匀的速度向外发送,令牌桶算法就实现了这个功能, 可控制发送到网络上数据的数目,并允许突发数据的发送。

什么是令牌

从名字上看令牌桶,大概就是一个装有令牌的桶吧,那么什么是令牌呢?

紫薇格格拿的令箭,可以发号施令,令行禁止。在计算机的世界中,令牌也有令行禁止的意思,有令牌,则相当于得到了进行操作的授权,没有令牌,就什么都不能做。

用令牌实现限速器

我们用1块令牌来代表发送1字节数据的资格,假设我们源源不断的发放令牌给程序,程序就有资格源源不断的发送数据,当我们不发放令牌给程序,程序就相当于被限流,无法发送数据了。接下来我们说说限速器,所谓限速器,就是让程序在单位时间内,最多只能发送一定大小的数据。假设在1秒发放10块令牌,那么程序发送数据的速度就会被限制在10bytes/s。如果1秒内有大于10bytes的数据需要发送,就会因为没有令牌而被丢弃。

改进限速器——加个桶

15行Python代码带你轻松理解令牌桶算法 

我们实现的限速器,速度是恒定的,但是在实际的应用中,往往会有突发的传输需求(需要更快速的发送,但是不会持续太久,也不会引起网络拥塞),这种数据碰上我们的限速器,就因为拿不到令牌而无法发送。

对限速器进行一下改动,依然1秒产生10块令牌,但是我们把产生出来的令牌先放到一个桶里,当程序需要发送的时候,从桶里取令牌,不需要的时候,令牌就会在桶里沉淀下来,假设桶里沉淀了10块令牌,程序最多就可以在1秒内发送20bytes的数据,满足了突发数据传输的要求,并且由于桶里的令牌被用完,下一秒最多依然只能发10bytes的数据,不会因为持续发送大量数据,对网络造成压力。

15行Python代码带你轻松理解令牌桶算法 

15行Python代码实践令牌桶

令牌桶需要以一定的速度生成令牌放入桶中,当程序要发送数据时,再从桶中取出令牌。这里似乎有点问题,如果我们使用一个死循环,来不停地发放令牌,程序就被阻塞住了,有没有更好的办法?

我们可以在取令牌的时候,用现在的时间减去上次取令牌的时间,乘以令牌的发放速度,计算出桶里可以取的令牌数量(当然不能超过桶的大小),从而避免循环发放的逻辑。

接下来看代码:

import time
class TokenBucket(object):
 # rate是令牌发放速度,capacity是桶的大小
 def __init__(self, rate, capacity):
  self._rate = rate
  self._capacity = capacity
  self._current_amount = 0
  self._last_consume_time = int(time.time())
 # token_amount是发送数据需要的令牌数
 def consume(self, token_amount):
  increment = (int(time.time()) - self._last_consume_time) * self._rate # 计算从上次发送到这次发送,新发放的令牌数量
  self._current_amount = min(
   increment + self._current_amount, self._capacity) # 令牌数量不能超过桶的容量
  if token_amount > self._current_amount: # 如果没有足够的令牌,则不能发送数据
   return False
  self._last_consume_time = int(time.time())
  self._current_amount -= token_amount
  return True

总结

以上所述是小编给大家介绍的15行Python代码带你轻松理解令牌桶算法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python中文件操作简明介绍
Apr 13 Python
python虚拟环境virtualenv的使用教程
Oct 20 Python
Python入门之三角函数sin()函数实例详解
Nov 08 Python
python编写分类决策树的代码
Dec 21 Python
Python 创建空的list,以及append用法讲解
May 04 Python
对python文件读写的缓冲行为详解
Feb 13 Python
Django的models中on_delete参数详解
Jul 16 Python
python 解决flask 图片在线浏览或者直接下载的问题
Jan 09 Python
pytorch方法测试——激活函数(ReLU)详解
Jan 15 Python
解决python pandas读取excel中多个不同sheet表格存在的问题
Jul 14 Python
PyQt QMainWindow的使用示例
Mar 24 Python
Python+Appium自动化测试的实战
Jun 30 Python
Python反转序列的方法实例分析
Mar 21 #Python
Python常见工厂函数用法示例
Mar 21 #Python
python如何统计序列中元素
Jul 31 #Python
python如何读写json数据
Mar 21 #Python
python如何读写csv数据
Mar 21 #Python
python如何让类支持比较运算
Mar 20 #Python
python如何为创建大量实例节省内存
Mar 20 #Python
You might like
PHP 前加at符合@的作用解析
2015/07/31 PHP
PHP实现 APP端微信支付功能
2018/06/22 PHP
PHP pthreads v3下的Volatile简介与使用方法示例
2020/02/21 PHP
用JS控制回车事件的代码
2011/02/20 Javascript
IE的fireEvent方法概述及应用
2013/02/22 Javascript
Jquery选中或取消radio示例
2013/09/29 Javascript
Document.location.href和.replace的区别示例介绍
2014/03/04 Javascript
Javascript基于AJAX回调函数传递参数实例分析
2015/12/15 Javascript
简述JavaScript提交表单的方式 (Using JavaScript Submit Form)
2016/03/18 Javascript
jquery 动态合并单元格的实现方法
2016/08/26 Javascript
微信小程序 radio单选框组件详解及实例代码
2017/01/10 Javascript
JS常见算法详解
2017/02/28 Javascript
vue如何从接口请求数据
2017/06/22 Javascript
详解webpack+express多页站点开发
2017/12/22 Javascript
p5.js入门教程之小球动画示例代码
2018/03/15 Javascript
vue.js将时间戳转化为日期格式的实现代码
2018/06/05 Javascript
JS中判断字符串存在和非空的方法
2018/09/12 Javascript
python中正则的使用指南
2016/12/04 Python
详解Python文本操作相关模块
2017/06/22 Python
python类的方法属性与方法属性的动态绑定代码详解
2017/12/27 Python
numpy.delete删除一列或多列的方法
2018/04/03 Python
Python异步操作MySQL示例【使用aiomysql】
2019/05/16 Python
python网络爬虫 CrawlSpider使用详解
2019/09/27 Python
python os.path.isfile 的使用误区详解
2019/11/29 Python
PyCharm 在Windows的有用快捷键详解
2020/04/07 Python
Python基于pandas绘制散点图矩阵代码实例
2020/06/04 Python
python解释器安装教程的方法步骤
2020/07/02 Python
详解HTML5之pushstate、popstate操作history,无刷新改变当前url
2017/03/15 HTML / CSS
Spartoo瑞典:鞋子、包包和衣服
2018/09/15 全球购物
法国发饰品牌:Alexandre De Paris
2018/12/04 全球购物
丝芙兰墨西哥官网:Sephora墨西哥
2020/05/30 全球购物
什么是Connection-oriented Protocol/Connectionless Protocol面向连接的协议/无连接协议
2012/09/06 面试题
不拖欠农民工工资承诺书
2014/03/31 职场文书
湖南省党的群众路线教育实践活动总结会议新闻稿
2014/10/21 职场文书
Golang实现AES对称加密的过程详解
2021/05/20 Golang
golang内置函数len的小技巧
2021/07/25 Golang