15行Python代码,帮你搞懂令牌桶算法

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

什么是令牌

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

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

用令牌实现限速器

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

改进限速器——加个桶

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

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

15行Python代码实践令牌桶

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

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

接下来看代码:

 1import time
 2
 3
 4class TokenBucket(object):
 5
 6    # rate是令牌发放速度,capacity是桶的大小
 7    def __init__(self, rate, capacity):
 8        self._rate = rate
 9        self._capacity = capacity
10        self._current_amount = 0
11        self._last_consume_time = int(time.time())
12
13    # token_amount是发送数据需要的令牌数
14    def consume(self, token_amount):
15        increment = (int(time.time()) - self._last_consume_time) * self._rate  # 计算从上次发送到这次发送,新发放的令牌数量
16        self._current_amount = min(
17            increment + self._current_amount, self._capacity)  # 令牌数量不能超过桶的容量
18        if token_amount > self._current_amount:  # 如果没有足够的令牌,则不能发送数据
19            return False
20        self._last_consume_time = int(time.time())
21        self._current_amount -= token_amount
22        return True

本文分享自微信公众号 - Python私房菜(python-fans)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-03-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python专栏

Python 面试问答 Top 25

Python 是一种解释型,交互式,面向对象的高级编程语言。和别的一些使用标点符号的语言不同,Python使用了大量的英语单词作为关键字,因而具有很好的可读性。...

14130
来自专栏生信宝典

生信宝典文章集锦,众多干货,有趣有料 (20180825版)

生信的作用越来越大,想学的人越来越多,不管是为了以后发展,还是为了解决眼下的问题。但生信学习不是一朝一夕就可以完成的事情,也许你可以很短时间学会一个交互式软件的...

12430
来自专栏FreeBuf

你知道吗?图形验证码可能导致服务器崩溃

图片验证码是为了防止恶意破解密码、刷票、论坛灌水等才出现的,但是你有没有想过,你的图形验证码竟然可能导致服务器的崩溃?

14330
来自专栏极客猴

Python 面试宝典

步入 9 月,徐徐的秋风给酷热的天气带来丝丝凉意。同时,也吹来一股招聘高潮。俗话说“金九银十”,每年的 9、10 月都是招聘高潮。有些小伙伴会参加秋招,有些小伙...

45910
来自专栏极客猴

盘点一些网站的反爬虫机制

因为 Python 语法简介以及强大的第三方库,所以我们使用它来制作网络爬虫程序。网络爬虫的用途是进行数据采集,也就是将互联网中的数据采集过来。

3.1K30
来自专栏Python中文社区

回归树的原理及Python实现

提到回归树,相信大家应该都不会觉得陌生(不陌生你点进来干嘛[捂脸]),大名鼎鼎的 GBDT 算法就是用回归树组合而成的。本文就回归树的基本原理进行讲解,并手把手...

11820
来自专栏FreeBuf

利用基础数据对某IDC大量网站被黑进行关联分析

*本文作者:feiniao,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。

36040
来自专栏FreeBuf

自己动手打造工具系列之自动刷新简历

话说搞安全的大佬们都非常忙,自己在一步一步成长中无暇顾及其他琐碎的事情,比如让猎头注意到各位大佬。如何让猎头和大厂注意到自己呢?第一、提高自己在整个行业的曝光度...

17750
来自专栏安恒网络空间安全讲武堂

二进制学习系列-堆溢出

在C++中,如果类中有虚函数,那么它就会有一个虚函数表的指针__vfptr,在类对象最开始的内存数据中。之后是类中的成员变量的内存数据。 对于子类,最开始的内存...

32930
来自专栏极客慕白的成长之路

Python中使用Xpath

XPath介绍: 是什么? 全称为XML Path Language 一种小型的查询语言 说道XPath是门语言,不得不说它所具备的优点: 1) 可在XM...

44420

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励