流量控制

当系统资源不够,不足以应对大量请求,即系统资源与访问量出现矛盾的时候,我们为了保证有限的资源能够正常服务,因此对系统按照预设的规则进行流量限制或功能限制的一种方法

限流原因

  • 流量大
  • 保护服务

限流形式:

  • 技术层面限流 限制并发 限制速率等
  • 业务层面限流 类似于秒杀下场景的商品总量 抢完就完

对于限流 我们需要考虑如下问题:

  • 限流指标
  • 限流手段
  • 超额流量处理

流量统计指标

  • 每秒事务数(Transactions per Second,TPS):“事务”可以理解为一个逻辑上具备原子性的业务操作
  • 每秒请求数(Hits per Second,HPS):指每秒从客户端发向服务端的请求数
  • 每秒查询数(Queries per Second,QPS):一个请求的响应往往要由后台多个服务节点共同协作来完成 所以看似客户端发送了一条请求 但背后很可能涉及到多个查询

当然具体业务相关的系统也有其他统计指标:如IO密集型的使用最高带宽 游戏服务采用在线用户数

限流设计模式

计数器算法

系统维护一个计数器,来一个请求就加1,请求处理完成就减1,当计数器大于指定的阈值,就拒绝新的请求。

基于这个简单的方法,可以再延伸出一些高级功能,比如阈值可以不是固定值,是动态调整的。另外,还可以有多组计数器分别管理不同的服务,以保证互不影响等。

线程池大小,数据库连接池大小、nginx连接数等都属于计数器算法。

全局或某段时间范围达到阈值则限流

  • 滑动窗口计数

滑动窗口原理是在每次有访问进来时,先判断前 N 个单位时间内的总访问量是否超过了设置的阈值,并对当前时间片上的请求数 +1

202001271051

队列

就是基于FIFO队列,所有请求都进入队列,后端程序从队列中取出待处理的请求依次处理。 基于队列的方法,也可以延伸出更多的玩法来,比如可以设置多个队列以配置不同的优先级

漏桶算法

漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率

202001271537

令牌桶算法

设置一个令牌桶,另外有一个脚本以持续恒定的速度往令牌桶里面放令牌,后端处理程序每处理一个请求就必须从桶里拿出一个令牌,如果令牌拿完了,那就不能处理请求了。我们可以控制脚本放令牌的速度来达到控制后端处理的速度,以实现动态流控

2020789425

使用guava实现

@RestController
public class Controller {

    /**
     * 一个每秒创建一个token的桶
     */
    RateLimiter limiter = RateLimiter.create(1);

    @RequestMapping("index")
    public String index(){
        // 500ms内无法获取令牌,返回错误,否则成功
        if (limiter.tryAcquire(500, TimeUnit.MILLISECONDS)){
            return "success";
        }else {
            return "error";
        }

    }
}

令牌桶与漏桶

主要区别在于“漏桶算法”能够强行限制数据的传输速率, 而“令牌桶算法”在能够限制数据的平均传输速率外,还允许某种程度的突发传输 。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。

分布式限流

  • 集中式存储统计信息 将原本在每个服务节点自己内存当中的统计数据给开放出来,让全局的限流服务可以访问到 这种方式每次服务调用额外增加了一次网络开销
  • 使用货币令牌 一个令牌会携带着一定额度贯穿整条链路 每次服务调用这个额度都会被减去点 当额度为0时 要不直接失败 要不就再向中心申请一定的额度 继续请求

results matching " "

No results matching " "

results matching " "

No results matching " "