- 一、集群流控介绍
- 二、整体架构
- 三、Sentinel 集群限流
- 3.1 集群限流客户端
- 3.1.1 添加动态获取限流规则InitFunc
- 3.1.2 指定客户端角色
- 3.1.3 添加InitFunc SPI
- 3.2 集群限流服务端
- 3.2.1 引入相关依赖
- 3.2.2 创建 SentinelTokenServer
- 3.2.3 添加动态获取限流规则InitFunc
- 3.2.4 添加InitFunc SPI
- 3.3 Nacos配置限流规则
- 四、集群流控规则
集群流控可以解决流量不均匀导致总体限流效果不佳的问题。
假设集群中有 10 台机器,我们给每台机器设置单机限流阈值为 10 QPS,理想情况下整个集群的限流阈值就为 100 QPS。不过实际情况下流量到每台机器可能会不均匀,会导致总量没有到的情况下某些机器就开始限流。
因此仅靠单机维度去限制的话会无法精确地限制总体流量。而集群流控可以精确地控制整个集群的调用总量,结合单机限流兜底,可以更好地发挥流量控制的效果。
集群流控中共有两种身份:
- Token Client:集群流控客户端,用于向所属 Token Server 通信请求 token。集群限流服务端会返回给客户端结果,决定是否限流。
- Token Server:即集群流控服务端,处理来自 Token Client 的请求,根据配置的集群规则判断是否应该发放 token(是否允许通过)。
- 创建集群限流客户端
- 创建集群限流服务端
- 配置限流规则(Nacos配置中心)
整体架构如下:
项目结构
public class DataSourceInitFunc implements InitFunc {
// token server 地址
private final String CLUSTER_SENTINEL_HOST = "127.0.0.1";
// token server 端口
private final int CLUSTER_SERVER_PORT = 9999;
// 请求超时时间
private final int REQUEST_TIMEOUT = 20000;
// dataId
private final String APP_NAME = "token-server";
// nacos远程服务地址
private static final String NACOS_REMOTE_ADDRESS = "localhost:8848";
// nacos groupId
private static final String GROUP_ID = "sentinel-group";
@Override
public void init() throws Exception {
// 加载集群信息
loadClusterClientConfig();
// 注册集群限流规则属性:故障转移方案,当token server不用时,直接从 动态限流规则配置中心获取限流规则
registryClusterFlowRuleProperty();
}
private void loadClusterClientConfig() {
// 设置 token server 集群信息
ClusterClientConfigManager.applyNewAssignConfig(new ClusterClientAssignConfig()
.setServerHost(CLUSTER_SENTINEL_HOST)
.setServerPort(CLUSTER_SERVER_PORT));
// 设置超时时间
ClusterClientConfigManager.applyNewConfig(new ClusterClientConfig()
.setRequestTimeout(REQUEST_TIMEOUT)
);
}
private void registryClusterFlowRuleProperty() {
ReadableDataSource> readableDataSources = new NacosDataSource>(
NACOS_REMOTE_ADDRESS,
GROUP_ID,
APP_NAME,
source -> JSON.parseObject(source, new TypeReference>() {
}));
FlowRuleManager.register2Property(readableDataSources.getProperty());
}
}
3.1.2 指定客户端角色
// 指定角色:表示当前的节点是集群客户端 ClusterStateManager.applyState(ClusterStateManager.CLUSTER_CLIENT);3.1.3 添加InitFunc SPI
创建文件:META-INFservicescom.alibaba.csp.sentinel.init.InitFunc
文件内容:
com.tortoise.tokenclient.DataSourceInitFunc3.2 集群限流服务端
项目结构
创建一个 Maven 项目,引入以下依赖。
3.2.2 创建 SentinelTokenServercom.alibaba.csp sentinel-cluster-server-default 1.8.4 com.alibaba.csp sentinel-datasource-nacos 1.8.4
public class SentinelTokenServer {
private static final String APP_NAME = "sentinel-token-server";
public static void main(String[] args) throws Exception {
ClusterTokenServer tokenServer = new SentinelDefaultTokenServer();
ClusterServerConfigManager.loadGlobalTransportConfig(new ServerTransportConfig()
.setIdleSeconds(600)
.setPort(9999));
ClusterServerConfigManager.loadServerNamespaceSet(Collections.singleton(SentinelTokenServer.APP_NAME));
// Start the server.
tokenServer.start();
}
}
3.2.3 添加动态获取限流规则InitFunc
public class DataSourceInitFunc implements InitFunc {
// nacos远程服务地址
private static final String NACOS_REMOTE_ADDRESS = "localhost:8848";
// nacos groupId
private static final String GROUP_ID = "sentinel-group";
@Override
public void init() throws Exception {
ClusterFlowRuleManager.setPropertySupplier(dataId -> {
ReadableDataSource> readableDataSources = new NacosDataSource>(
NACOS_REMOTE_ADDRESS,
GROUP_ID,
dataId,
source -> JSON.parseObject(source, new TypeReference>() {
}));
return readableDataSources.getProperty();
});
}
}
3.2.4 添加InitFunc SPI
创建文件:META-INFservicescom.alibaba.csp.sentinel.init.InitFunc
文件内容:
com.tortoise.tokenserver.DataSourceInitFunc3.3 Nacos配置限流规则
在Nacos创建对应的配置,添加JSON格式内容如下:
[
{
"resource": "resource-name",
"grade": 1,
"count": 100,
"clusterMode": true,
"clusterConfig": {
"flowId": 1,
"thresholdType": 1,
"fallbackToLocalWhenFail": true
}
}
]
四、集群流控规则
FlowRule 添加了两个字段用于集群限流相关配置:
private boolean clusterMode; // 标识是否为集群限流配置 private ClusterFlowConfig clusterConfig; // 集群限流相关配置项
其中 用一个专门的 ClusterFlowConfig 代表集群限流相关配置项,以与现有规则配置项分开:
// (必需)全局唯一的规则 ID,由集群限流管控端分配. private Long flowId; // 阈值模式,默认(0)为单机均摊,1 为全局阈值. private int thresholdType = ClusterRuleConstant.FLOW_THRESHOLD_AVG_LOCAL; private int strategy = ClusterRuleConstant.FLOW_CLUSTER_STRATEGY_NORMAL; // 在 client 连接失败或通信失败时,是否退化到本地的限流模式 private boolean fallbackToLocalWhenFail = true;
- flowId 代表全局唯一的规则 ID,Sentinel 集群限流服务端通过此 ID 来区分各个规则,因此务必保持全局唯一。一般 flowId 由统一的管控端进行分配,或写入至 DB 时生成。
- thresholdType 代表集群限流阈值模式。其中单机均摊模式下配置的阈值等同于单机能够承受的限额,token server 会根据客户端对应的 namespace(默认为 project.name 定义的应用名)下的连接数来计算总的阈值(比如独立模式下有 3 个 client 连接到了 token server,然后配的单机均摊阈值为 10,则计算出的集群总量就为 30);而全局模式下配置的阈值等同于整个集群的总阈值。
ParamFlowRule 热点参数限流相关的集群配置与 FlowRule 相似。
参考文献:https://sentinelguard.io/zh-cn/docs/introduction.html



