简单限速器的实现

简单限速器的实现

服务器在高并发的场景下,不可能处理所有的请求,这就需要我们增加一些限制访问的措施,避免服务器瘫痪的情况,这里我们讲解一个简单的限速器实现,原算法来自于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时,后续访问请求就会限制住

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值