
在网络中传输数据时,为了防止网络拥塞,需限制流出网络的流量,使流量以比较均匀的速度向外发送,令牌桶算法就实现了这个功能, 可控制发送到网络上数据的数目,并允许突发数据的发送。令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。
1
什么叫令牌
从名字上看令牌桶,顾名思义,大概就是一个装有令牌的桶吧,那么什么是令牌呢?在计算机的世界中,令牌也有令行禁止的意思,有令牌,则相当于得到了进行操作的授权,没有令牌,就什么都不能做。
2
令牌桶限速的原理
令牌桶这种控制机制,基于桶中令牌的个数,来实现流量大小的控制。大小固定的令牌桶可以以恒定的速度源源不断产生令牌,如果令牌不被消耗,或者被消耗的速度小于产生的速度,则令牌会持续增加,直到把桶填满。后面再产生令牌就会从桶中溢出,桶中可以保存的令牌数永远不可能超过桶的最大值。
当程序需要发送数据包时,需要消耗桶中的令牌,大小不同的数据包,消耗的令牌数量不一样。若桶中有足够令牌,则允许发送数据,同时桶中的令牌数相应减少对应数量。当令牌桶中令牌不足时,数据将不能被发送,只有等桶中产生了足够的新的令牌,才可以被发出。这样就可以限制数据的流量只能小于或者等于令牌生成的速度,达到限流的目的。

令牌桶算法简单的C语言实现范例:
#define LIMIT_MAX_TOKEN_IN_BUCKET 100
#define LIMIT_FLOW_SPEED 5 //per second 10
int token_bucket = 0;
time_t produce_time = 0;
void preduce_token()
{
if(token_bucket == LIMIT_MAX_TOKEN_IN_BUCKET)
{
return;
}
int times = 0; //
if(produce_time == 0)
{
produce_time = time(0);
times = LIMIT_FLOW_SPEED;
}
else
{
time_t cur_time = time(0);
times = (cur_time - produce_time) * LIMIT_FLOW_SPEED;
if(times > 0)
{
produce_time = cur_time;
}
}
token_bucket = token_bucket + times;
if(token_bucket > LIMIT_MAX_TOKEN_IN_BUCKET)
{
token_bucket = LIMIT_MAX_TOKEN_IN_BUCKET;
}
}
int cunsume_token(int datasize)
{
//产生令牌
preduce_token();
//若当前令牌桶中令牌不足,则不能发送数据
if((token_bucket <= 0) || (token_bucket < datasize))
{
return -1;
}
//消耗相应数量的令牌
token_bucket -= datasize;
return 0;
}
令牌桶算法实现的其他项目参考:
Java实现参考代码:
https://www.cnblogs.com/googlemeoften/p/6020718.html
Python实现参考:
https://www.jb51.net/article/136823.htm
Go语言实现参考:
https://github.com/juju/ratelimit




