文章目录
本文作者: AceCandy
博客原文链接: https://acecandy.cn/archives/从限流看juc之semaphore
版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
A.限流的定义
众所周知,谈到高并发系统开发(比如双十一、秒杀活动、12306春运等)的时候,我们通常会使用三种方式来优化保护我们的系统,分别是缓存、降级和限流。
抛开缓存和降级,这次主要说一下限流。那么什么叫「限流」呢?
我们平时也经常提到各种「限流」,普通生活中比如坐地铁或者去游乐场的时候,为了限制每一班次或者每一游戏的人数,会进行限流排队。
所以顾名思义,「限流」就是限制流量,技术上来说通过对并发访问或者请求进行限速或者一个时间窗口内的请求进行限速来保护系统。在系统达到了限制的临界点,就可以采用拒绝服务、排队、或者等待的方式来保护现有系统,不至于因为大量请求导致系统发生雪崩现象。
常见的限流方式很多,从类型上可以分为QPS限流及并发数限流。

B.QPS限流
1.计数器算法(滑动窗口)
计数器算法是限流算法里最简单也是最容易实现的一种算法。主要用来限制一定时间内的总并发数,常用的地方比如数据库连接池、线程池、秒杀的并发数;计数器限流只要一定时间内的总请求数超过设定的阀值则进行限流。
比如我们规定,对于A接口来说,我们1分钟的访问次数不能超过100个。那么我们可以这么做:在一开 始的时候,我们可以设置一个计数器counter,每当一个请求过来的时候,counter就加1,如果counter的值大于100并且该请求与第一个请求的间隔时间还在1分钟之内,那么说明请求数过多;如果该请求与第一个请求的间隔时间大于1分钟,且counter的值还在限流范围内,那么就重置 counter。
缺点:这个算法虽然简单粗暴,但是有一个十分致命的问题,那就是临界问题。假设有一个恶意用户,他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,那么其实这个用户在 1秒里面,瞬间发送了200个请求。我们刚才规定的是1分钟最多100个请求,也就是每秒钟最多1.7个请求,用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过我们的速率限制。用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。
解决方案:我们能看出上面说的这类问题是由于精度的原因导致出现的问题,所有可以使用滑动窗口,滑动窗口的格子划分的越多,那么滑动窗口的滚动就越平滑,限流的统计就会越精确。
2.令牌桶算法
令牌桶我们可以理解成是一个存放固定容量令牌的桶。所有的请求在处理之前都需要拿到一个可用的令牌才会被处理。
根据限流大小,设置按照一定的速率往桶里添加令牌。桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃。
请求是否被处理要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求。请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除。
所以令牌桶允许一定程度突发流量,只要有令牌就可以处理,支持一次拿多个令牌。令牌桶中装的是令牌。
3.漏桶算法
漏桶算法其实也很简单,顾名思义我们可以理解成一个固定容量的漏桶。然后请求就是一个注水漏水过程,往桶中以一定速率流出水(请求),以任意速率流入水(请求),当流入的水(请求)超过漏桶本身的容量时,则新流入的水(请求)自然就被丢弃了。
所以漏桶是一个具有固定容量、固定流出速率的队列,漏桶限制的是请求的流出速率。漏桶中装的是请求。漏桶算法保证了整体的速率。
4.总结
当前主流的使用还是令牌桶或者漏桶偏多。
但是由上面来看可以知道,令牌桶的特色就是以“恒定”的速率创建令牌,访问的请求获取令牌的速率是“不确定”的,当前剩的有多少令牌就发多少,没有令牌了就只能等着。
而漏桶的特色是以“恒定”的速率处理请求,但是请求流入桶内的速率是“不确定”的。处理

最低0.47元/天 解锁文章
416

被折叠的 条评论
为什么被折叠?



