Sentinel中的集群流控
Sentinel 1.4.0 开始引入了集群流控模块,Sentinel的集群流控中,应用分为两个角色
- Token Client:集群流控客户端,用于向所属 Token Server 通信请求 token。集群限流服务端会返回给客户端结果,决定是否限流。
- Token Server:即集群流控服务端,处理来自 Token Client 的请求,根据配置的集群规则判断是否应该发放 token(是否允许通过)。
同时,TokenServer又有两种部署方式
一种是嵌入模式,即Token Server嵌入普通web应用中,在此模式下,集群中各个实例都是对等的,token server 和 client 可以随时进行转变,缺点是需要限制 token server 的总 QPS,防止影响应用本身。嵌入模式适合某个应用集群内部的流控,对应架构图如下:
另外一种是独立模式,即作为独立的 token server 进程启动,独立部署,隔离性好,但是需要额外的部署操作。独立模式适合作为 Global Rate Limiter 给应用集群提供流控服务,对应架构图如下
本文会基于嵌入模式,结合Apollo配置中心,做到零侵入实现集群流控,直接进入主题
基本概念介绍
针对集群流控,Sentinel中有几个基本的类需要介绍,方便大家理解下文中的代码
先贴上一个Token Server配置的流转图,图片来自Sentinel官方Wiki
先介绍下最重要的,图片最上方的JSON串,也就是
这段JSON串是Sentinel Dashboard后台分配TokenServer时产生的,控制台分配Token Server时的界面如图所示
serverId:对应选择的TokenServer的机器及其Sentinel端口
ip:对应选择的TokenServer的机器ip
port:对应选择的TokenServer的提供Token服务的端口
clientSet: 作为TokenClient的机器列表
这个JSON串是实现集群流控的关键,需要同时被TokenServer及TokenClient监听到,因此需要推送配置并持久化到配置中心中。
所以第一个关键点是,需要将TokenServer分配配置推送到Apollo中,具体代码实现环节再做介绍
剩下几个类,分为TokenClient和TokenServer两个端来做介绍
TokenServer端:
- ClusterServerConfigManager#loadGlobalFlowConfig:设置Token Server最大允许qps
- ClusterServerConfigManager#registerServerTransportProperty:设置TokenServer的Token获取端口
- ClusterFlowRuleManager.setPropertySupplier:集群限流TokenServer同样需要监听到集群限流规则的变化,否则怎么知道该限制多少的qps呢?
TokenClient端:
- ClusterClientConfigManager#registerClientConfigProperty: 设置TokenClient获取Token的超时时间
- ClusterClientConfigManager#registerServerAssignProperty:设置TokenClient链接的TokenServer地址
通用:
ClusterStateManager:设置当前应用为TokenClient,或者TokenServer
基本思路及流程
先根据一个例子来简单说明下实现思路
假设现在集群内有三台机器192.168.0.1,192.168.0.2,192.168.0.3,TokenServer对应的JSON配置如下,即在Dashboard分配192.168.0.1为TokenServer,其他为TokenClient
[
{
"clientSet": [
"192.168.0.2@8719",
"192.168.0.3@8719",
],
"ip": "192.168.0.1",
"machineId": "192.168.0.1@8719",
"maxAllowedQps": 20000,
"port": 18730
}
]
现在的问题来了,应用端都监听到了这个TokenServer的配置
- 如何设定某个服务为TokenServer(或者是TokenClient)?
- 如何为每个Client指定TokenServer的地址?
先来看第一个问题,因为我们已经指定了192.168.0.1为TokenServer,伪代码如下
if(currentMachineId == 配置的machineId){
设置当前应用为TokenServer(ClusterStateManager.registerProperty)
设置TokenServer最大QPS(ClusterServerConfig