限流的解决方式
1、计数器算法:在一段时间间隔内(时间窗/时间区间),处理请求的最大数量固定,超过部分不做处理。
bug:
假设有一个恶意用户,他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,那么其实这个用户在 1秒里面,瞬间发送了200个请求。
我们刚才规定的是1分钟最多100个请求(规划的吞吐量),也就是每秒钟最多1.7个请求,用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过我们的速率限制。
用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。
2、漏桶算法
水(请求)进入到漏桶里,按照一定速率流出,当水流入过大超过桶得容量时会自动溢出。
做到了:
削峰:有大量请求到来时,会拒绝(自动溢出),不会使服务器突然压力剧增,从而限流保护服务可用。
缓冲:不至于直接请求到服务器,缓冲压力。
bug:
出水速度固定即请求放行速度固定。无法应对特殊紧急情况。比如,通过动态扩容,后端流量从1000QPS提升到1WQPS,漏桶没有办法。
3、令牌桶
以一个设定的速率产生令牌并放入令牌桶,每次用户请求都得申请令牌,如果令牌不足,则拒绝请求。
令牌桶限流大致的规则如下:
(1)进水口按照某个速度,向桶中放入令牌。
(2)令牌的容量是固定的,但是放行的速度不是固定的,只要桶中还有剩余令牌,一旦请求过来就能申请成功,然后放行。
(3)如果令牌的发放速度,慢于请求到来速度,桶内就无牌可领,请求就会被拒绝。
总之,令牌的发送速率可以设置,从而可以对突发的出口流量进行有效的应对。
令牌桶的好处之一就是可以方便地应对 突发出口流量(后端能力的提升)。
比如,可以改变令牌的发放速度,算法能按照新的发送速率调大令牌的发放数量,使得出口突发流量能被处理。
《小日常》
小F:
高并发的场景应该怎么考虑呀?
大M:
高并发一般解决办法就是,代码调优,加redis来减少数据库压力,加mq来缓解服务器压力,增加熔断和限流,防止服务雪崩导致业务阻断;最后就是提高硬件配置,加服务器的节点,提高数据库服务器cpu内存等。
大M:
可以通过mq来缓解服务的压力,把订单请求放到mq里,然后后台服务来消费mq。相当于mq起一个缓冲的作用
小F:
增加熔断和限流?
大M:
熔断:熔断就是,如果A服务请求B1服务,B1服务由于并发太高了,然后宕机了,这时候A服务没收到B1的返回结果,之后就不会去请求B1服务了,只会去请求B2,B3
小F:
噢噢噢,springCloud框架中hystrix组件就可以实现熔断。
大M:
对,限流:限流是通过令牌桶来实现的,就比如一分钟生成1000个令牌,每个请求过来都会从令牌桶里删除一个令牌,这样的话,当一分钟请求超过1000个的时候,就拿不到令牌了,就请求失败了;springcloud有专门的依赖来做这个的,用redis来放令牌的