限流是保护高并发系统的三把利器之一,另外两个是缓存和降级。
一、为什么要限流
限制并发和请求量,保护自身系统和下游系统不被巨型流量冲垮等。
二、原理
限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务或进行流量整形。
三、场景
秒杀抢购
四、限流方式
限制总并发数、限制瞬时并发数、限制时间窗口内的平均速率,其他还有如限制远程接口调用速率、限制MQ的消费速率。另外还可以根据网络连接数、网络流量、CPU或内存负载等来限流。
1、限制总并发数
比如数据库连接池、线程池
2、瞬时并发数
如nginx的limitconn模块,用来限制瞬时并发连接数,Java的Semaphore也可以实现
3、限制时间窗口内的平均速率:
Guava的RateLimiter、nginx的limitreq模块,限制每秒的平均速率
比如说,我们需要限制方法被调用的并发数不能超过100(同一时间并发数),则我们可以用信号量 Semaphore实现。
可如果我们要限制方法在一段时间内平均被调用次数不超过100,则需要使用RateLimiter。
五、限流的基础算法:漏桶算法和令牌桶算法
1、漏桶算法:
进来的水量就好像访问流量一样,而出去的水量就像是我们的系统处理请求一样。当访问流量过大时,这个漏斗中就会积水,如果水太多了就会溢出。
漏桶算法的实现往往依赖于队列,请求到达如果队列未满则直接放入队列,然后有一个处理器按照固定频率从队列头取出请求进行处理。如果请求量大,则会导致队列满,那么新来的请求就会被抛弃。
2、令牌桶算法
令牌桶算法则是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。桶中存放的令牌数有最大上限,超出之后就被丢弃或者拒绝。当流量或者网络请求到达时,每个请求都要获取一个令牌,如果能够获取到,则直接处理,并且令牌桶删除一个令牌。如果获取不同,该请求就要被限流,要么直接丢弃,要么在缓冲区等待。
区别:
漏桶算法:一次新接受多个请求,固定的速录处理请求,主要用语处理一段时间内的总并发。
令牌桶算法:一次性多个请求过来,一下会拿掉多个令牌,瞬间处理多个请求。主要用语处理瞬时并发。