集群限流的两种模式
由于请求倾斜的存在,分发到集群中每个节点上的流量不可能是均匀的,因此单机限流无法实现精确地限制整个集群的整体流量,从而造成在总流量没有达到阈值的情况下一些机器就开始限流。
例如,服务 A 部署了 3 个节点,规则配置限流阈值为 200QPS,则在理想情况下集群的限流阈值为 600QPS,若某个节点先达到 200QPS,机器就会开始限流,而其他节点才达到 100QPS,此时集群的 QPS 为 400。
Sentinel 1.4.0 开始引入集群限流功能,目的是实现精确地控制整个集群的 QPS。
本地限流与集群限流
在分析限流与热点参数限流源码的过程中,我们发现无论是限流的本地限流与集群限流,还是热点参数限流的本地限流与集群限流,它们的入口都相同,只是所走的 canpasscheck 逻辑不同。
单机限流的整个工作流程如下:
FlowSlot 作为实现限流功能的入口,在 entry 方法中调用 FlowRuleChecker#checkFlow 方法判断是否需要限流。
FlowRuleChecker 根据资源名称从限流规则管理器中获取限流规则,并遍历限流规则。
根据限流规则配置的 clusterMode 决定走本地限流逻辑还是走集群限流逻辑。
如果走本地限流逻辑,则调用流量效果控制器判断是否拒绝当前请求。
集群限流是在第三步的基础上实现的,如果限流规则配置的 clusterMode 为集群限流模式,则向集群限流服务端发起远程调用,由集群限流服务端判断是否拒绝当前请求,且流量效果控制也是在集群限流服务端完成的。
限流的 can pass check 流程如图所示:
由上图可知,当规则配置为集群限流模式时,集群限流客户端通过 TokenService 向集群限流服务端发起 RPC 远程调用;集群限流服务端根据响应结果决定如何控制当前请求。
集群限流的两种模式
Sentinel 支持采用两种模式启动集群限流服务端,分别是嵌入式模式和独立应用模式。
这两种模式都有各自的优缺点。
嵌入式模式
嵌入式模式是指将集群限流服务端作为应用的内置服务同应用一起启动,与应用在同一个进程,可动态地挑选其中一个节点作为集群限流服务端。嵌入式模式如图所示:
优点:
无须单独部署,可动态切换集群限流服务端。
缺点:
将集群限流服务端嵌入应用中,作为集群限流服务端的节点需要处理集群内的其他限流客户端发来的请求,会影响应用的性能。
适用场景:
适用于单个微服务实现集群内部限流的场景,如只对服务 A 内部集群限流提供服务。
如果将服务部署在 Kubernetes 平台上,则嵌入式模式还有另外一个缺点。由于 POD 的重启会造成 POD 动态 IP 地址变更,因此使用嵌入式模式需要频繁调整配置,以选择一个节点作为集群限流服务端,并且需要调整其他客户端的连接配置,才能让其他客户端连接上服务端。试想一下,如果某个节点挂掉了,且该节点正好作为集群限流的服务端,由于配置不变,Kubernetes 为了保持服务总存活的节点数就会新起一个 POD,而新起的 POD 的 IP 地址与挂掉的 POD 的 IP 地址肯定不同,则新起的节点就变成了集群限流客户端,此时,所有集群限流客户端都会连接不上服务端,最终只能回退为本地限流。
独立应用模式
独立应用模式是指将集群限流服务端作为一个独立的应用部署,如图所示:
优点:
与应用隔离,不影响应用的性能。
适用场景:
适用于为所有微服务实现集群限流提供服务,如服务 A 和服务 B 等所有微服务都可以接入这个集群限流服务端。
Sentinel 集群限流客户端与集群限流服务端通信只保持一个长连接,底层通信基于 Netty 框架实现,使用自定义通信协议,并且数据包设计得足够小,对网络 I/O 性能的影响可降到最低,再加上集群限流服务端处理一次 requestToken 请求都会访问内存且计算量少,响应时间短,因此使用集群限流功能对集群限流客户端性能的影响并不大。
Sentinel 集群限流对集群限流服务端的可用性要求不高,当集群限流服务端挂掉时,可回退为本地限流。嵌入式模式并未实现类似于主/从自动切换的功能,当集群限流服务端挂掉时,集群限流客户端并不能自动切换为集群限流服务端。所以选择哪种集群限流服务端启动模式更多的是考虑使用嵌入式模式是否会严重影响应用的性能,以及应用是否有必要严重依赖集群限流。当然,如果服务是部署在 Kubernetes 平台上的,就应该选择独立应用模式。
评论