实现分布式限流的方案之多,两只手加起来都数不过来。挑选几个比较有代表性的方案,我们一起学习下。
Guava
Google 出品的客户端限流客户端组件;和分布式没半毛钱关系。但是作为使用起来最简单的客户端限流组件,值得一学。
Guava 在其多线程模块下提供了以 RateLimiter 为首的几个限流支持类。Guava 作为一个客户端组件,它的作用范围仅限于“当前”这台服务器,不能对集群以内的其他服务器施加流量控制。
打个比方,目前我有2台服务器[Server A,Server B],这两台服务器都部署了同一个服务,假如我希望对这两台机器的流量进行控制,比如将两台机器的访问量总和控制在每秒20以内,如果用 Guava 来做,只能独立控制每台机器的访问量<=10。
网关层限流
服务网关,作为整个分布式链路中的第一道关卡,承接了所有用户来访请求.
网关层限流的架构考量
将系统流量的分布层次抽象成一个简单的漏斗模型来看
从上到下的路径依次是:
- 用户流量从网关层转发到后台服务
- 后台服务承接流量,调用缓存获取数据
- 缓存中无数据,则访问数据库
流量自上而下是逐层递减的,在网关层聚集了最多最密集的用户访问请求,其次是后台服务。然后经过后台服务的验证逻辑之后,刷掉了一部分错误请求,剩下的请求落在缓存上,如果缓存中没有数据才会请求漏斗最下方的数据库,因此数据库层面请求数量最小
网关层作为用户请求的第一个关卡,是所有流量途径的第一站。目前主流的网关层有以软件为代表的Nginx,还有Spring Cloud中的Gateway和Zuul这类网关层组件
Nginx里的几种核心限流模式:
- 基于IP地址和基于服务器的访问请求限流
- 并发量(连接数)限流
- 下行带宽速率限制
中间件限流
对于分布式环境来说,无非是需要一个类似中心节点的地方存储限流数据。打个比方,如果我希望控制接口的访问速率为每秒100个请求,那么我就需要将当前1s内已经接收到的请求的数量保存在某个地方,并且可以让集群环境中所有节点都能访问。那我们可以用什么技术来存储这个临时数据呢?这个场景天然适合我们的中间件大显神威!而且还得需要支持超高并发的中间件,一般我们都会选择 Redis。
Redis简直就是为服务端限流量身打造的利器。利用Redis过期时间特性,我们可以轻松设置限流的时间跨度(比如每秒10个请求,或者每10秒10个请求)。同时Redis还有一个特殊技能–脚本编程,我们可以将限流逻辑编写成一段脚本植入到Redis中,这样就将限流的重任从服务层完全剥离出来,同时Redis强大的并发量特性以及高可用集群架构也可以很好的支持庞大集群的限流访问。
限流组件
除了上面介绍的几种方式以外,目前也有一些开源组件提供了类似的功能,比如Sentinel。Sentinel是阿里出品的开源组件,并且包含在了Spring Cloud Alibaba组件库中。
小结
在真实的大型项目里,不会只使用一种限流手段,往往是几种方式互相搭配使用,让限流策略有一种层次感,达到资源的最大使用率。在这个过程中,限流策略的设计也可以参考前面提到的漏斗模型,上宽下紧,漏斗不同部位的限流方案设计要尽量关注当前组件的高可用。
文档信息
- 本文作者:Piter Jia
- 本文链接:https://piterjia.github.io/2020/05/10/distributed-limiting-proposal/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)