限流详解

限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的请求进行限速来保护系统,将流量削峰防止系统挂掉或雪崩,最终做到有损服务而不是不服务。

4.1 限流算法

  4.1.1 令牌桶算法

  4.1.2 漏桶算法

  4.1.3 计数器限流 比如用Redis的有序集合限流

4.2 应用级限流

  4.2.1 限流总并发/连接/请求数

    当快要超过系统QPS时,进行限流保护,新请求将被丢弃或者放到队列中

  4.2.2 限流总资源数

    比如数据库连接和线程,使用池化技术限制总资源数

  4.2.3 限流某个接口的总并发数/请求数

    单独限制某个高频接口,使用AtomicLong或者信号量,或者Hystrix的信号量模式

  4.2.4 限流某个接口时间窗请求数

    Guava的Cache统计一定时间窗内的请求次数;Redis的有序集合,score是时间,每次查询时,将时间窗口之外的节点删除掉,查询一下总节点数

  4.2.5 平滑限流某个接口的请求数

    令牌桶和漏桶,以恒定或者相对恒定速率处理请求

4.3 分布式限流

  分布式限流的关键是将限流做成原子化,是4.2的分布式场景下的延伸。针对的场景是业务层面的限流。

  4.3.1 Redis+Lua

    时间窗口实现:

    键值对设计:比如限制每秒并发量,key取时间戳到秒级别,value存请求累加数。

    判断的流程:取key,不存在新设置,存在则判断是否大于上限,没超过则将累加数加一。过期时间设置1秒多一点。整个判断写在lua脚本中。

  4.3.2 Nginx+Lua

4.4 接入层限流

  流量入口处的限流,该层主要目的是:负载均衡、非法请求过滤、请求聚合、缓存、降级、限流、A/B测试、服务质量监控。

  相对于分布式限流,这里的限制不涉及业务层面。

  对于Nginx接入层限流可以使用自带的两个模块,通过指定key,针对key进行限流:

  连接数限流模块:ngx_http_limit_conn_module。比如限定某IP下的总连接数

  请求限流模块:ngx_http_limit_req_module。漏桶算法实现,有平滑模式和允许突发模式,比如限定某IP下的总请求数

  OpenRestry提供的Lua限流模块:lua-retry-limit-traffic

4.5 节流

  防止多个相同事件连续重复执行。

  4.5.1 throttleFirst/throttleLast 在一个时间窗口内,多个重复事件只处理第一个或最后一个。

    书中举的例子,用户滚动页面触发scroll事件,防止浏览器卡顿,多个滚动时间只会执行一次

  4.5.2 throttleWithTimeout  两个连续时间的先后执行时间不得小于某个时间窗口

    书中举的例子,关键词自动补全,我们想要一个词的补全而不是每个字的补全,如果每个字都调用补全接口,先输入字的补全会很快被下一个字的补全覆盖

人生就像蒲公英,看似自由,其实身不由己。
原文地址:https://www.cnblogs.com/walker993/p/14697518.html