系列文章

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)

【开源】Sentinel高性能高可用集群限流解决方案

一、前言

很久前就已经开始使用Sentinel。当时为了解决其开源的控制台单点故障问题,于是开源了Sentinel控制台集群方案(使用Ignite解决单点故障问题)。当初就一直计划要做Sentinel集群限流的高性能高可用解决方案,并给大家开源。但是由于种种原因,这个事情一直没有完成。经过快两年多的时间,楼主终于该解决方法的实现,并给大家开源。今天就给大家详细介绍下Sentinel集群限流的高性能高可用解决方案。其主要涉及如下几个改造点:

1、接入协调集群节点单点故障问题

2、实现集群容错策略,实现集群不可用时主动降级本地流控

3、实现资源路由模式,解决Token Server节点流量不均问题

4、实现动态集群限流,解决单Token Server节点上限对业务的限制

二、方案详解

我们都知道开源的Sentinel提供了一个基础版本的集群限流实现。但是要直接在业务系统中使用还是存在很多问题。其中主要的有两个:一是集群节点存在单点故障的问题。二是集群节点不可用时,没有对应的容错策略。因此我们的集群限流解决方案便主要是围绕解决这两个问题。

1、Token Server单点故障解决方案

其实单点故障的解决方案比较简单,我们只需要在集群节点(Token Server)和客户端之间构建一个高可用协调集群即可。这里我们可以选择zookeeper或者ETCD。这样我们就可以部署很多Token Server节点构建一个Token Server集群,当集群节点变更之后,就能够实时通知到客户端,客户端则可以及时获取到当前可用的集群节点信息。从而解决了Token Server单点故障的问题。其大致架构如下:

2、集群容错解决方案

我们都知道咱们得客户端SDK需要连接并请求对应的Token Server节点,去实时判断计数才能实现集群限流。但当我们的Token Server节点挂了之后,我们怎么去判断该节点不可用并终止请求呢?如果我们不做任何判断,则会出现大量无效调用对客户端SDK性能也会有影响,且对业务也会产生影响。因此,我们需要判断出Token Server挂了,并主动将集群流控降级为本地流控。

我们设计了DiagnoseFaultToleranter,来判断Token Server是否可用。大概思路就是:通过滑动窗口来统计该节点的请求可用率或者异常数。然后根据设置阈值来判断是否该节点是否可用。

 这样我们就能够判断Token Server是否可用,并执行相应的降级策略了。

3、资源路由方案

解决了前面两个问题之后,集群限流基本就可以在线上系统使用了。至少其满足了高可用的特性,不再具有单点故障问题。但是我们还可以做进一步的优化改进。

由于Sentinel开源默认集群限流的时候的路由方式为系统维度路由:及一个系统下的所有资源(接口)都路由到一个Token Server上进行计数统计。这样如果我们有多个系统需要接入集群限流集群,且每个系统的流量差距很大,就会导致Token Server节点之间的流量差距很大,导致资源无法得到充分利用。如下图,如果系统A和系统B的流量差距很大,则会导致节点1和节点2承载的流量非常不均匀。

 因此我们需要改造支持按资源(接口)维度进行路由。这样才能够尽量让Token Server之间的流量差距变小,让其资源得到充分利用。如下图根据细粒度的资源维度进行路由,则能很好的解决节点流量承载不均的问题。

代码实现上我们使用了MappedClusterTokenClient来支持资源路由,使用SystemClusterTokenClient来支持系统路由。同时设计了代理模式,使用了ClusterTokenClientProxy来根据配置代理选择咱们最终的TokenClient。

4、动态集群限流

咱们都知道Sentinel默认的集群流控是每次业务请求都去请求一次Token Server。由Token Server做一个统一的中心点计数。因此咱们同一个系统下的相同接口(不同的机器)必须路由到同一个Token Server节点上。否则就会出现集群限流计数错误的问题。因此咱们前面提到的系统路由和资源路由都遵守了这一原则。但是这样有一个比较明显的问题,那就是咱们得Token Server单节点肯定有性能上限,比如单节点最大QPS为30W。那么如果某个系统下的某个接口的最大QPS大于30W,则就不能对其进行集群限流。

为了解决上述问题,咱们就设计出了动态集群限流。基本思想很简单,即所有的集群限流在业务机器本地完成。业务机器根据自己被分配的限流阈值直接在本地计数判断即可。然后业务机器再异步定时到Token Server上去动态获取其最新分配的限流阈值。这里的分配策略可以有两种:动态策略和均值策略。均值策略就是单机限流阈值等于集群限流阈值除以当前有效的机器数;动态策略则是单机限流阈值等于单机上一秒的QPS在全局中的占比乘以集群限流阈值。其大致架构如下图。

三、基本使用

1、配置推送接入

和Sentinel原生一样,都使用了FlowRuleManager.loadRules加载配置。所以业务可以接入自己的配置服务,比如Zookeeper等。然后当配置变更后,通过加载到客户端SDK中即可。其配置的具体代码参考TestController.initRuleAndConfig()方法。

2、Token Server集群接入

当Token Server集群变更时,咱们需要通知SDK客户端。对应样例都在TestController.initRuleAndConfig()中,如下图:

3、系统/资源路由设置

路由设置功能变更是和Token Server集群变更放(Token Server集群接入章节中)在一起。具体位置如下:

 4、动态集群限流配置

动态集群限流设置则是随单个限流规则中随流控配置(配置推送接入章节中)一起下发。

四、开源信息

开源地址:https://github.com/lifeofcoder/AutoLimiter

五、惯例

如果你喜欢本文或觉得本文对你有所帮助,欢迎一键三连支持,非常感谢。

如果你对本文有任何疑问或者高见,欢迎添加公众号lifeofcoder共同交流探讨(添加公众号可以获得楼主最新博文推送以及”Java高级架构“上10G视频和图文资料哦)。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐