1. 什么是限流
限流是指以某种维度统计流量,然后将预期范围内的流量放行,而超过预期的部分流量拒绝、降级或者排队等待。
那这里流量具体指什么呢?可以是请求数,可以是连接用户数,也可以是请求响应报文大小等。
2. 如何限流
- 通过nginx进行限流
- 通过spring cloud 网关进行限流
3. 限流算法
- 计数器
统计每个固定时间段内的请求数,统计完之后,再统计下一个时间段的请求数。
比如固定时间段为5秒,5秒内的请求数不可超过500,若超过500,则拒绝请求。5秒统计完后,统计下一个5秒。
时间窗口算法的优势就是统计简单,劣势就是限流不够精准。比如0-5秒的请求数为499,5-10秒的请求数也为499,都未超过500的限制。但是4-5有480个请求,5-9秒有400个请求,显然4-9秒的总请求数880超过了500的限制,可能导致服务无法承载压力而宕机。
所以实际使用的时候很少使用时间窗口算法。
- 滑动窗口
想象成时间轴上有一个固定大小的窗口一直在往前滑动,并统计窗口内的请求数。
比如一个时间窗口为1秒,切割成10份小窗口,每份是100ms。当滑动到第11个小窗口的时候,会丢弃第1个小窗口的数据,保证整个时间窗口统计的是1秒(10个小窗口)的请求数据。若限制1秒的请求数为100,则超过100的请求就会被丢弃。
通过切割小窗口的设计,可以将限流的精准度提高。除非流量在1个时间窗口的第一个小窗口以及相近的时间窗口的最后一个小窗口涌入,才可能出现流量超出的问题。
若小窗口切割的更细,那么限流的精准度将更高,但是这样的性能消耗成本更高。
滑动窗口的劣势在于若第一个小窗口请求数为100,也是会被放行的。这样在秒杀场景下,会导致商品被最快的100个请求抢完了。那什么情况下100ms内会有100请求呢?答案就是机器人。商品都被机器人抢走了,而真正的消费者抢不到商品。
- 漏斗算法
想象有一个漏斗,每次请求过来的时候就像水一样先进入漏斗,而漏斗的出口是很细的,以匀速往下滴。
漏斗的入口很大,但是容量是有限的,若超过了漏斗的大小,那么直接就被会拒绝掉。
通过控制出口匀速处理的方式,限制了进入系统的流量,不会出现大批流量涌入而击垮服务的情况。
漏斗算法的劣势也在于出口是匀速处理,这样即使系统在空闲的情况下,也无法处理更多请求,导致系统资源被浪费。
- 令牌桶算法
想象有一个桶,匀速地往里面放入令牌。每次请求过来的时候,都要先从桶里面获取一个令牌,获取到令牌之后才会被处理,若桶中无令牌了,那么请求可以直接被拒绝也可以排队等待。
注意往桶中放入令牌的速度是匀速的,令牌桶的容量也是有限的,超过之后就不会再放了。这种情况下,有可能会有突发的大流量,一下子消费完了令牌桶中的所有令牌,即使这样,令牌桶的容量和放置速率是我们可调控的,所以可以调整到合适的大小。这样就解决了漏斗算法可能浪费系统资源的问题。