很多文章中关于这两个方面的介绍,都是含糊其辞,或者引用官方介绍,其实看完之后,根本理解不了,而且还会更加疑惑。这里我总结下自己的见解。当然欢迎共同探讨。
一般的网上描述如下:
漏桶法
漏桶法不同于计算器法,它有效的避免了计数器法限流的“突刺效应”缺陷,实现也不复杂,通过固定大小的队列+定时取队列元素的方式即可实现。如其名漏桶,就像一个盛水的容器,漏桶法只限制容器出水的速率,当进水的速率过大时,将会填满容器造成溢出,溢出部分的流量也就是拒绝的流量。比如,容器大小为100,出水速率为每秒10/s,当桶为空时,最大的流量可以到达100/s,但是即使这样,受限于固定的流出速率,后端处理的也只能是最大每秒10个,其余的流量都会被缓冲在漏桶中。这个也这是漏桶法的缺陷,没法真正处理突发的流量洪峰,效率不高。
令牌桶法
令牌桶法也是基于桶的原型,但是和漏桶算法截然不同的时,没有出水口。令牌桶通过令牌的产生速率+令牌桶的容积来控制流量,有效的解决了漏桶效率不高的问题。如,容积为100的桶,令牌产生速率为50/s,那么就代表当桶中令牌已满的时候,最大能够承载100的流量,后面如果流量一直居高不下,也会以每秒50个流量的速度恒速处理请求。令牌桶的这种特性有效的处理了洪峰流量也能做到不被洪峰压垮,是目前限流比较常见的实现方法。比较著名的实现有谷歌guava中的RateLimiter。然后下面将要分析的Spring Cloud Gateway中也是使用的令牌桶算法实现的限流
有没有感觉,上面这样介绍完还是疑惑,那怎么感觉这俩根本没区别呢。比如会有此疑问:
漏桶法的最大处理速率取决于出水速度.而令牌桶算法的最大处理速度取决于令牌产生的速度.这两个速度完全可以配置成一致的,有区别吗。
接下来看总结描述:
漏桶限流算法的原理
以固定速率从桶中流出水滴,以任意速率往桶中放入水滴,桶容量大小是不会发生改变的。
流入:以任意速率往桶中放入水滴。
流出:以固定速率从桶中流出水滴。
水滴:是唯一不重复的标识。
因为桶中的容量是固定的,如果流入水滴的速率>流出的水滴速率,桶中的水滴可能会溢出。那么溢出的水滴请求都是拒绝访问的,或者直接调用服务降级方法。前提是同一时刻
令牌桶算法
令牌桶分为2个动作,动作1(固定速率往桶中存入令牌)、动作2(客户端如果想访问请求,先从桶中获取token)。guava 提供的RateLimiter类来进行限流处理。
1.传统的方式整合RateLimiter 有很大的缺点:代码重复量特别大,而且本身不支持注解方式。 2.如果限流代码可以放在网关中,相当于针对所有的服务接口都实现限流(可以使用排除法进行排除不进行限流的方法),维护性不是很强。 3.正常的互联网公司项目,不是所有的服务接口都需要实现限流方法的,一般只真针对于大流量接口。比如:秒杀抢购、12306抢票等。 4.可以手动封装一个RateLimiter类 注解来解决这个方法
简单总结就是:
1.漏桶是相当于,我往桶里倒水,没有任何限制,想快就快想慢就慢,但是呢,你这个桶没一分钟,就只往滴十滴水,那禁不住我倒水直接溢出的,但是对于在桶下面接水的人来说,他合适很均衡,没一分钟就只会得到十滴水。所以伤害的是我,而不是接水的人。
2.令牌桶,我现在要看你有没有许可证,我每分钟就往桶里放十张许可证,很均衡。然后一个人要取水,这时候呢,我桶里有两个许可证,那么好,你拿到证件了,好可以去取水了。又过来一个,也同样,走人取水。突然十个人一起过来,而证件只有两个,那么不好意思,谁先拿到证,走人取水,剩下的八个人走人回家等着。因为没证了。我拒绝。你可以一会再来。
3.并不能说明令牌桶一定比漏洞好,她们使用场景不一样。令牌桶可以用来保护自己,主要用来对调用者频率进行限流,为的是让自己不被打垮。所以如果自己本身有处理能力的时候,如果流量突发(实际消费能力强于配置的流量限制),那么实际处理速率可以超过配置的限制。而漏桶算法,这是用来保护他人,也就是保护他所调用的系统。主要场景是,当调用的第三方系统本身没有保护机制,或者有流量限制的时候,我们的调用速度不能超过他的限制,由于我们不能更改第三方系统,所以只有在主调方控制。这个时候,即使流量突发,也必须舍弃。因为消费能力是第三方决定的。
4.总结起来:如果要让自己的系统不被打垮,用令牌桶。如果保证被别人的系统不被打垮,用漏桶算法。