java-rate-limiter

35 阅读2分钟

rate-limiter

保障服务稳定的三大利器

  • 熔断降级
  • 服务限流
  • 故障模拟

限流的地点:

  1. Nginx层面的限流
  2. 业务代码层逻辑上的限流。

实现

计数器、令牌桶、漏桶

计数器

// 伪码: 对于A接口,我们1分钟的访问次数不能超过100个
var limiterKey = getKeyFromEL()
if(`exists limiterKey`){
    // 已经存在
    var count = get limiterKey;
    if(count > 100){
        return false;
    }
    incry limiterKey 1;
    return true;
}else{
    // 创建新的
    `incry limiterKey 1`;
    `expire limiterKey 1min`;
    return true;    
}

问题这个算法很简单,但是有一个十分致命的问题,那就是临界问题,还有会出现突刺现象拒绝大部分请求.

普通限流的临界问题:

假设有一个恶意用户,他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,那么其实这个用户在 1秒里面,瞬间发送了200个请求。规定的是1分钟最多100个请求,也就是每秒钟最多1.7个请求,用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过我们的速率限制。用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。

解决方案1: 滑动窗口算法

解决方案 滑动窗口,将时间窗口进行多段划分,当时间到达1:00时,我们的窗口会往右移动一格,每一个格子都有自己独立的计数器counter,此时分析时间窗口内的总请求数量一共是200个,超过了限定的100个,所以此时能够检测出来触发限流

漏桶

// 水(请求)先进桶(阻塞队列),再匀速流出

漏桶算法实现限流可以解决突刺现象,无法应对短时间的突发流量

短时间内流量激增的问题:

令牌-token-桶

// token先匀速进桶,再提取token处理请求

已有源码解读

demo