作积极的人,越努力越幸运!node
首先一个服务有三个服务提供者,但这三台集群的硬件配置不同,如图所示:
在这里插入图片描述缓存
为了充分利用硬件的资源,诸如 Dubbo 都提供了基于权重的负载均衡机制,例如能够将8C16G的机器设置的权重是4C8G的两倍,这样充分利用硬件资源,假如如今须要引入 Sentinel 的限流机制,例如为一个 Dubbo 服务设置限流规则,这样因为三台集群分担的流量不均匀,会致使没法重复利用高配机器的资源。
假设通过压测,机器配置为C48G最高能承受的TPS为 1500,而机器配置为8C16G能承受的TPS为2800,那若是采起单机限流,其阔值只能设置为1500,由于若是超过1500,会将4C8G的机器压垮。网络
解决这种办法的方式就是针对整个集群进行限流,即为整个集群设置一个阔值,例如设置限流TPS为6000。多线程
限流的一个基本做用就是按照限流规则生成访问许可(Token),而后根据当前实时的调用信息进行判断是否能够得到许可而决定是否放行。架构
集群与单机限流在实时调用信息收集方面应该差异不大,均可以基于滑动窗口进行统计信息的收集。app
集群与单机限流的最主要区别在与许可的生成,单机模式的许可直接在本地生成,但集群限流必须有一个统一的 Token 发放机制,以此来协调当前集群内多机调用,从而基于当前“调用总数”进行限流。负载均衡
在探究集群限流实现原理以前先来回顾一下单机限流的执行流程图。
在这里插入图片描述ide
结合流程咱们能够看出集群限流的几个关键点 ClusterBuilderSlot、FlowSlot。ui
在对一个资源进行流控规则判断时,首先将进入到 NodeSelectorSlot,而后就会进入到 ClusterBuilderSlot,为了与单机限流模式,介绍 ClusterBuilderSlot 时与 NodeSelectorSlot 进行一个对比。spa
NodeSelectorSlot 的核心实现截图以下所示:
在这里插入图片描述
舒适提示:从该系列以前的文章也能得知,一个 资源对应的一个 NodeSelectorSlot 实例,即多线程访问一个资源时,都会调用同一个 NodeSelectorSlot 实例。
NodeSelectorSlot 的关键点以下:
ClusterBuilderSlot 的关键点以下:
在这里插入图片描述
FlowSlow FlowSlot 的核心处理逻辑主要是调用 FlowRuleChecker 的 canPassCheck 方法,正如上面看到的同样,根据配置规则,若是是集群模式,则调用的是其 passClusterCheck 方法,接下来咱们将重点探讨该方法。
FlowRuleChecker#passClusterCheck
代码@1:获取一个 TokenService 服务类。这里实现关键点:
代码@3:获取集群限流的流程ID,该 flowId 全局惟一。
代码@4:经过 TokenService 去申请 token,这里是与单机限流模式最大的差异。
接下来将分别从 DefaultClusterTokenClient、DefaultTokenService 分别探究集群限流相关的实现原理与细节,更好的指导咱们如何使用集群限流功能。
从咱们的经验也得知,TokenClient 的主要职责就是发送请求到 TokenService 端,主要是网络相关的细节将不在此篇文章中给出,若是有兴趣,你们能够关注个人 Netty 专栏。
首先 Sentinel 提供了 SPI 机制,故容许用户自定义 TokenClient 的实现类,官方与 SPI 默认配置的文件以下:
关于 TokenClient 主要关注其初始化代码,由于咱们须要关注一个很是重要的点:
DefaultClusterTokenClient#initNewConnection
在这里插入图片描述
在客户端启动的时候会建立与 TokenServer 之间的连接,即这边须要配置服务端的 IP 与端口号,那如何配置呢?其实配置方式彻底由本身去实现对应的解析器,下面根据官方的 Demo 示例以下:
在这里插入图片描述
这里须要说明的其配置项由 ClusterGroupEntity 来定义,其字段的定义以下:
[{"clientSet":["112.12.88.66@8729","112.12.88.67@8727"],"ip":"112.12.88.68","machineId":"112.12.88.68@8728","port":11111}]
Client 端接下来就是向服务端发送请求,与网络相关的不在本文的讨论范围内,接下来将重点探讨服务端是如何发放许可的。
Token Server 端收到客户的请求,其处理入口为 FlowRequestProcessor,其处理方法为:proce***equest,最终会调用 DefaultTokenService 的 requestToken 方法。
DefaultTokenService#requestToken
在这里插入图片描述
代码@1:根据 ruleId 获取指定的限流规则。
代码@2:而后调用 ClusterFlowChecker 的 acquierClusterToken 方法,申请许可。
许可的发放流程主要由 ClusterFlowChecker 的 acquierClusterToken 方法实现。
在这里插入图片描述
Step1:首先判断是否容许本次许可申请,这是由于 TokenServe 支持嵌入式,即支持在应用节点中嵌入一个 TokenServer,为了保证许可申请的请求不对正常业务形成比较大的影响,故对申请许可这个动做进行了限流。
一旦触发了限流,将向客户端返回 TOO_MANY_REQUEST 状态码,Sentinel 支持按 namespace 进行限流,具体由 GlobalRequestLimiter 实现,该类的内部一样基于滑动窗口进行收集,原理与 FlowSlot 类似,故这里不加以展开,默认的限流TPS为3W,有关于 Sentinel 相关的配置,将在后续文章专门梳理。
在这里插入图片描述
Step2:根据流程ID获取指标采集器。
在这里插入图片描述
Step3:计算 latestQps、globalThreashold、 nextRemaining 三个阔值,三个的含义分别以下:
Step5:当前许可数不足的状况,而且该请求为高优先级的处理逻辑:
Step6:若是当前许可不足,而且该请求为普通优先级的处理逻辑,增长阻塞相关指标的统计数,并返回 BLOCKED。
TokenServer 返回申请许可以后,那 Token Client 如何处理呢?其处理代码在 FlowRuleChecker#applyTokenResult
在这里插入图片描述
咱们能够发现,若是服务端返回OK,则顺利经过,返回BLOCKED,则直接返回 false,会抛出 FlowException,若是是 token 限流,若是规则运行退化为单机限流模式,则进行单机限流。
集群限流的基本实现原理就介绍到这里了。
集群限流的基本原理接介绍到这里了,与单机限流模式最大的区别就是集群限流模式的须要引入 TokenService,提供许可的发放服务,该服务能够嵌入应用节点,也能够独立于应用以外。这边借用官方文档上的两张图来简单介绍一下嵌入模式与独立模式的架构:
在这里插入图片描述
在这里插入图片描述
集群模式使用注意,若是使用的是集群模式限流,则以下两个配置则失效:
在这里插入图片描述
最后抛出一个思考题:集群模式应该算是高大上,但咱们项目中真的须要吗?集群限流模式有哪些缺点、哪些优势,欢迎你们留言探讨。
好了,亲爱的读者朋友,以上就是本文的所有内容了,原创不易,莫要白票,请你为本文点个【在看】吧,这将是我写做更多优质文章的最强动力。
欢迎加入个人知识星球,一块儿交流源码,探讨架构,揭秘亿级订单的架构设计与实践经验,打造高质量的技术交流圈,为广大星友提供高质量问答服务,长按以下二维码加入。
丁威素质三连是对我最大的鼓励钟意做者