简介
借用官方的话
为什么要使用集群流控呢?假设我们希望给某个用户限制调用某个 API 的总 QPS 为 50,但机器数可能很多(比如有 100 台)。这时候我们很自然地就想到,找一个 server 来专门来统计总的调用量,其它的实例都与这台 server 通信来判断是否可以调用。这就是最基础的集群流控的方式
集群模块
- sentinel-cluster-common-default: 公共模块,包含公共接口和实体
- sentinel-cluster-client-default: 默认集群流控 client 模块,使用 Netty 进行通信,提供接口方便序列化协议扩展
- sentinel-cluster-server-default: 默认集群流控 server 模块,使用 Netty 进行通信,提供接口方便序列化协议扩展;同时提供扩展接口对接规则判断的具体实现(TokenService),默认实现是复用 sentinel-core 的相关逻辑
概述
Sentinel支持采用集群的方式进行限流,采用Server控制规则和Client检索规则的方式进行集群流控,Server可以有两种存在方式
- 独立模式:独立出Client来不参与流量计算,隔离性强,适合全局流控,当Server掉线时Client会进行本利限流
- 内嵌模式:既可以作为Server也可以作为Client,参与流量计算,隔离性较差适合某个服务集群内使用,当Server掉线时会自主把某个Client作为Server进行推荐
独立模式详解
独立模式需要一个不参与流量计算的服务端和多个可以不集群的客户端
本例中采用Nacos做动态规则
服务端示例
Maven 依赖
<!--sentinel的核心-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>
<!--Nacos数据源的依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--使用sentinel注解的依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
</dependency>
<!--集群服务端必须的依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-server-default</artifactId>
</dependency>
<!--如果加入sentinel控制台就需要这个-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
代码示例
Set<String> applyNamespaces = new HashSet<>(Arrays.asList("test"));
// 创建集群限流的独立服务端对象并设置端口,这个端口是集群客户端将要使用到的端口
ClusterTokenServer server = new SentinelDefaultTokenServer();
ClusterServerConfigManager.loadGlobalTransportConfig(new ServerTransportConfig().setPort(13002));
// 这是可选向,用于动态配置这个限流在哪个应用(project.name)上
SentinelProperty<Set<String>> namespaceProperty = new NacosDataSource<>(
"localhost", // 配置Nacos ip
"DEFUALT", // 配置Nacos data的分组
"dubb-sentinel-cluster-server-namespaces-config.json", // data id
namespacesConverter()).getProperty(); // 获取property属性
// 这是必选项,配置集群的限流规则,
ClusterFlowRuleManager.setPropertySupplier(namespace -> {
NacosDataSource<List<FlowRule>> dataSource = new NacosDataSource<>(
"localhost", // 配置Nacos ip
"DEFUALT", // 配置Nacos data的分组
"dubb-sentinel-cluster-server-config.json", // data id
flowRulesConverter());
return dataSource.getProperty();
});
// 集群服务配置管理器应用一下当前所应用服务名配置做初始值
ClusterServerConfigManager.loadServerNamespaceSet(applyNamespaces);
ClusterServerConfigManager.registerNamespaceSetProperty(namespaceProperty);
// 启动独立的服务
server.start();
// server.stop(); // 停止服务
以上是如何搭建一个基本的独立模式的集群限流服务端,并加入了sentinel控制台
注意事项
对于独立模式服务端的注意事项有以下几点
- 服务端限流规则(
FlowRule
)的clusterMode
字段必须为true
,并且设置clusterConfig
字段的属性,配置集群相关配置,其中最重要的是flowId
字段,这个字段用于表示一个唯一的集群规则配置表示
[
{
"clusterConfig": {
"fallbackToLocalWhenFail": true, // 在服务器dump后是否退化
"thresholdType": 0, // 阈值模式
"windowIntervalMs": 1000, // 窗口时间
"flowId": 11112 // 配置唯一id,客户端需要用到
},
"clusterMode": true, // 集群模式开启
"controlBehavior": 0,
"count": 2, // 限流数量
"grade": 1, // 限流方式
"limitApp": "default", // 针对哪些规则进行限流
"resource": "/test1/demo4", // 限流资源名称
}
]
客户端示例
Maven
<!--sentinel核心依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>
<!--sentinel注解依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
</dependency>
<!--web流控依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
</dependency>
<!--客户端集群依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-client-default</artifactId>
</dependency>
<!--控制台依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<!--Nacos依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
代码示例
// 创建基于Nacos的动态集群配置,动态指定了服务端的IP、端口
NacosDataSource<ClusterClientAssignConfig> assignConfigNacosDataSource =
new NacosDataSource<>("localhost",
"DEFUALT", "dubb-sentinel-cluster-client-config.json",
serverAssignDatasourceConverter());
// 创建基于Nacos的动态规则配置,指定了本地模式以及集群模式的规则配置
NacosDataSource<List<FlowRule>> dataSource = new NacosDataSource<>(
"localhost",
"DEFUALT",
"dubb-sentinel-config.json",
converter());
// 注册服务访问相关属性并指定了token为客户端
ClusterClientConfigManager.registerServerAssignProperty(assignConfigNacosDataSource.getProperty());
ClusterClientConfigManager.applyNewConfig(new ClusterClientConfig().setRequestTimeout(1000));
ClusterStateManager.applyState(ClusterStateManager.CLUSTER_CLIENT);
// 注册了基于Nacos的动态规则配置
FlowRuleManager.register2Property(dataSource.getProperty());
以上展示如何搭建了集群的客户端
注意事项
- 集群的客户端
project.name
属性不一定要一致,但是要注意服务限流应用在哪个应用上 - 集群的客户端的规则必须将
clusterMode
字段设为true
,并且设置clusterConfig
字段
[
{
"clusterConfig": {
"fallbackToLocalWhenFail": true, // 在服务器dump后是否退化
"thresholdType": 0, // 阈值模式
"windowIntervalMs": 1000, // 窗口时间
"flowId": 11112 // 配置唯一id,客户端需要用到
},
"clusterMode": true, // 集群模式开启,必须
"controlBehavior": 0,
"count": 4, // 限流数量
"grade": 1, // 限流方式
"limitApp": "default", // 针对哪些规则进行限流
"resource": "/test1/demo4", // 限流资源名称
}
]
这里我们看到clusterConfig字段几乎与服务端配置一致,这是必须的(至少ID要),而剩下配置是不会起效的,只有当这个客户端从集群模式退化到本地模式时才会启动本地规则的限流
内嵌模式详解
尽快更新。。。。