vlambda博客
学习文章列表

微服务-服务限流-开发实战

学习思路

  1. 各种限流方式应用场景及优缺点

  2. 具体实现


一、各种限流方式应用场景及优缺点


  1. 限流:在了解了系统的负荷之后,如果访问流量超过负荷那么将导致服务整体被压垮,为保证服务可用预防突发流量,在流量到达设置指标时允许摒弃部分以保证服务运行正常

  2. 总流量限流:一般以服务资源为标准,在有限资源的基础上设置最高上限;如:在服务器数量、配置一定的条件下,通过压测等手段设置系统访问阈值

  3. 按用户或客户端Ip限流:可防止同一ip或同一用户下恶意操作,可以统计正常情况下用户的平均访问频率设置阈值

  4. 接口级别限流:在单接口上限制;防止系统资源被某个接口全用完毕,导致其他接口不可用,跟线程池隔离原理类似


应用场景及优缺点


  1. 总流量限流:主要在网关层/Nginx层做,优点:可以设置上限,有效保护系统稳定,缺点:依赖于下游资源,如果资源变更需要动态调整

  2. 按用户、ip等限流:主要在网关做,优点:主要限制个人、低级的恶意刷,缺点:不能控制总量,多ip刷一个接口也可以刷死服务

  3. 按接口限流:主要用于抢购类接口定制开发,优点:可以根据不同接口单独设置,可有效隔离接口资源,缺点:代码浸入,局限性高,总资源不能有效保护,但如果真的遇到资源不足的时候基本已经做服务横向扩容了


实际应用上


  1. 在Nginx或者网关做总流量限流,防止恶意攻击

  2. 在抢购类接口按ip或者用户做定制开发;当然我们也可以在网关层进行拦截(只需要简单配置)


二、具体实现方式


原理分析

1、令牌桶算法

解释:

  1. 系统按照恒定的速率往桶里放入token

  2. 桶满时溢出放弃

  3. 新请求来时可拿取一个或多个token

  4. 如果没有token拒绝请求

获取的时候可以获取多个token从而应对突发流量


2、漏铜算法


解释

  1. 流量以任意的速度流入桶中

  2. 当桶内流量满时溢出

  3. 流量以均衡的速度漏出

  4. 桶内没有流量时流不出(拒绝访问)


可见这里有两个变量,一个是桶的大小,支持流量突发增多时可以存多少的水(burst),另一个是水桶漏洞的大小(rate)。

         因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使流突发(burst)到端口速率.因此,漏桶算法对于存在突发特性的流量来说不能很好解决


3、计数器


这个就比较粗糙了,但往往我们一般都用粗糙的

  1. 利用atomic包里的对象进行原子++

  2. redis的原子++


总归一个思路:设置两个变量,一个记录时间,一个记录次数,在规定的时间内达到这个次数就认为该限流了


二、代码实战


实现思路

  1. 自定义注解在Controller方法用

  2. 基于AOP拦截注解上属性,限流策略可自定义

  3. 使用线程池异步执行

  4. 运用redis+lua实现原子操作


看一下代码结构: