简单限速器的实现
服务器在高并发的场景下,不可能处理所有的请求,这就需要我们增加一些限制访问的措施,避免服务器瘫痪的情况,这里我们讲解一个简单的限速器实现,原算法来自于stackoverflow,链接:限速器算法,本文我们实现的是一个java版本的限速器。
基本原理:
本文的限速器算法为标准的令牌桶算法,基本原理为令牌桶中放置一定数量的令牌,当一个接口请求到达后,就从令牌桶中移除一个令牌,请求到到达服务器时,只要令牌桶中有令牌,就可以继续执行,如果当前令牌桶中,令牌数量已经为0,表示请求过快了,就抛弃这个请求,不做处理,从而起到限速的作用。在从令牌桶中取数据的同时,还要定时向令牌桶中添加令牌,保证接口请求可以通过,这个添加令牌的速度,就是额定的接口请求的速度,就像是我们要按照一定的速度水桶中注入水,而取令牌的动作,就如同流出水,如果流出过快,超过注入的速度,桶就空了,无法取水。这个额定速度,就是我们设置的限速器额限制速度,例如:2000/s。
代码
public class RateLimiter
{
private static Logger logger = LoggerFactory.getLogger(RateLimiter.class);
private static RateLimiter rLi = new RateLimiter();
private long rate = 0;// unit: requests/ms
private long allowance = 0;
private long lastCheck = 0;
public static long DEFAULT_VALUE = 1;
private boolean isinit = false;
private RateLimiter()
{
};
public static RateLimiter getInstance()
{
return rLi;
}
public boolean isInit()
{
return isinit;
}
public synchronized boolean init(long logIndex, long rate)
{
String logFlag = "RateLimiter.init";
logger.info("<lid:{}>[{}] rate:{}", logIndex, logFlag, rate);
if (isInit())
{
return true;
}
if (rate < DEFAULT_VALUE)
{
logger.error("<lid:{}>[{}] init failed! rate invalid rate:{}", logIndex, logFlag, rate);
return false;
}
this.rate = rate;
this.allowance = rate;
this.lastCheck = System.currentTimeMillis();
this.isinit = true;
return true;
}
public synchronized boolean limit(long logIndex)
{
String logFlag = "RateLimiter.limit";
if (!isInit())
{
logger.warn("<lid:{}>[{}] ratelimiter is not init!", logIndex, logFlag);
return false;
}
// Calculate time from last call
long now = System.currentTimeMillis();
long time_passed = now - lastCheck;
lastCheck = now;
// add to allowance
this.allowance += time_passed * this.rate;
if (this.allowance > this.rate)
{
this.allowance = this.rate;// throttle
}
if (this.allowance < DEFAULT_VALUE)
{
// limit
return false;
}
// not limit
allowance--;
return true;
}
}
limit是我们的实际限速器的接口,在服务器每个入口函数处,增加limit,用来限制服务器整体的访问频度,已达到控制服务器访问速度的目的,在理论上如果服务器的并发访问越快,访问和访问之间的时间越短,这样allowance理论是不会增加的,这样它每次访问递减1,递减为0时,后续访问请求就会限制住
529

被折叠的 条评论
为什么被折叠?



