乐趣区

分布式限流之限流方案

网关层限流

在整个分布式系统中,如果有这么一个“一夫当关,万夫莫开”的角色,非网关层莫属。服务网关,作为整个分布式链路中的第一道关卡,承接了所有用户来访请求.

网关层限流的架构考量

我们可以将系统流量的分布层次抽象成一个简单的漏斗模型来看

上面是一个最普通的流量模型,从上到下的路径依次是:

  1. 用户流量从网关层转发到后台服务
  2. 后台服务承接流量,调用缓存获取数据
  3. 缓存中无数据,则访问数据库

为什么说它是一个漏斗模型,因为流量自上而下是逐层递减的,在网关层聚集了最多最密集的用户访问请求,其次是后台服务。然后经过后台服务的验证逻辑之后,刷掉了一部分错误请求,剩下的请求落在缓存上,如果缓存中没有数据才会请求漏斗最下方的数据库,因此数据库层面请求数量最小(相比较其他组件来说数据库往往是并发量能力最差的一环,阿里系的 MySQL 即便经过了大量改造,单机并发量也无法和 Redis、Kafka 之类的组件相比)

如果在上面这个漏斗模型中做流量限制,最合适的环节就是网关层,因为它是整个访问链路的源头,是所有流量途径的第一站。目前主流的网关层有以软件为代表的 Nginx,还有 Spring Cloud 中的 Gateway 和 Zuul 这类网关层组件,也有以硬件 + 软件为代表的 F5(F5 价钱贵到你怀疑人生)

中间件限流

我们有没有一个解决方案,将限流下沉到业务层来,让开发团队可以自行控制?我们来思考一下如何在分布式环境中引入服务层限流。

对于分布式环境来说,无非是需要一个类似中心节点的地方存储限流数据。打个比方,如果我希望控制接口的访问速率为每秒 100 个请求,那么我就需要将当前 1s 内已经接收到的请求的数量保存在某个地方,并且可以让集群环境中所有节点都能访问。那我们可以用什么技术来存储这个临时数据呢?这个场景天然适合我们的中间件大显神威!而且还得需要支持超高并发的中间件,谁能堪此重任?

一并中间件这下起劲儿了,纷纷表示“选我选我选我”。数据库行不行?不行,并发量不够。Message Queue 行不行?好像 MQ 的运作模式不太适合这个场景,而且并发量也就差强人意。Kafka 行不行,嗯,并发量杠杠的,是个 Option。那 Redis 呢?OMG,憋说话就你了!理由这就给足你!

Redis 简直就是为服务端限流量身打造的利器。利用 Redis 过期时间特性,我们可以轻松设置限流的时间跨度(比如每秒 10 个请求,或者每 10 秒 10 个请求)。同时 Redis 还有一个特殊技能–脚本编程,我们可以将限流逻辑编写成一段脚本植入到 Redis 中,这样就将限流的重任从服务层完全剥离出来,同时 Redis 强大的并发量特性以及高可用集群架构也可以很好的支持庞大集群的限流访问。

限流组件

除了上面介绍的几种方式以外,目前也有一些开源组件提供了类似的功能,比如 Sentinel 就是一个不错的选择。Sentinel 是阿里出品的开源组件,并且包含在了 Spring Cloud Alibaba 组件库中,可以为 Cloud 服务在下一个“微服务架构设计与落地”的大章节中,我们将详细介绍 Sentinel 在分布式限流中的应用。

从架构维度考虑限流设计

在真实的大型项目里,不会只使用一种限流手段,往往是几种方式互相搭配使用,让限流策略有一种层次感,达到资源的最大使用率。在这个过程中,限流策略的设计也可以参考前面提到的漏斗模型,上宽下紧,漏斗不同部位的限流方案设计要尽量关注当前组件的高可用。

退出移动版