Sentinel数据源
Sentinel的数据源可以通过多种方式加载:json、xml文件;zookeeper;apollo;nacos;并且可以多种数据源同时使用。
扩展方式
动态数据源:DataSource`扩展常见的实现方式
拉模式
客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;
推模式
规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。
一:客户端从Nacos读取限流规则
Sentinel客户端配置
1. 引入POM依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
2. 修改配置文件
默认sentinel控制台推送到nacos的dataId定义为: ${spring.application.name}-flow-rules
server.port=8083
# 配置中心url
spring.application.name=order-server
#注册中心地址
spring.cloud.nacos.server-addr=192.168.64.128:8848
#添加sentinel依赖后 暴露/actuator/sentinel端点
# 开启健康检查
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=ALWAYS
#打开/关闭掉对Spring MVC端点的保护
spring.cloud.sentinel.filter.enabled=false
#这里的 spring.cloud.sentinel.transport.port 端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了1个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。
spring.cloud.sentinel.transport.port=8731
#指定sentinel控制台的地址
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8080
# 设置Sentinel Nacos数据源配置;其中ds是数据源名,可以自行随意修改
# Nacos数据源地址(需要启动一台Nacos Server)
# nacos 地址
spring.cloud.sentinel.datasource.ds.nacos.server-addr=${spring.cloud.nacos.server-addr}
spring.cloud.sentinel.datasource.ds.nacos.dataId=${spring.application.name}-flow-rules
spring.cloud.sentinel.datasource.ds.nacos.groupId=SENTINEL_GROUP
# 数据类型
spring.cloud.sentinel.datasource.ds3.nacos.data-type=json
# 规则类型
spring.cloud.sentinel.datasource.ds.nacos.rule-type=flow
3. 添加Nacos数据源配置类
@Configuration
public class DataSourceInitFunc {
Logger logger = LoggerFactory.getLogger(DataSourceInitFunc.class);
@Autowired
private SentinelProperties sentinelProperties;
@Bean
public DataSourceInitFunc init() throws Exception {
logger.info("[NacosSource初始化,从Nacos中获取熔断规则]");
sentinelProperties.getDatasource().entrySet().stream().filter(map -> {
return map.getValue().getNacos() != null;
}).forEach(map -> {
NacosDataSourceProperties nacos = map.getValue().getNacos();
// 限流规则,需要Nacos的dataId中包含flow字符串
if (nacos.getDataId().contains("flow")) {
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(nacos.getServerAddr(),
nacos.getGroupId(), nacos.getDataId(),
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
// 降级规则,需要Nacos的dataId中包含degrade字符串
if (nacos.getDataId().contains("degrade")) {
ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource = new NacosDataSource<>(nacos.getServerAddr(),
nacos.getGroupId(), nacos.getDataId(),
source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
}));
DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());
}
});
return new DataSourceInitFunc();
}
}
4. Nacos中添加熔断规则
根据配置文件配置的 id是 应用名-flow-rules
备注:
规则文件可以是json文件;也可以是text文件
规则是将 createOrder 的资源进行限流 使用QPS 模式 限流阈值 1
[
{
"resource": "createOrder",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
5. 测试
访问 http://localhost:8083/order/createorder/1 进行测试
这样会自动从配置中心读取配置信息不需要每次重启都需要配置了
二:Sentinel控制台 将熔断规则推送到Nacos数据源。
控制台改造主要是为规则实现
- DynamicRuleProvider:从Nacos上读取配置
- DynamicRulePublisher:将规则推送到Nacos上
1.下载控制台源码
下载Sentinel控制台:https://github.com/alibaba/Sentinel/releases
2.修改POM文件
将sentinel-datasource-nacos的 <scope>test</scope> 这一行注释掉
<!-- for Nacos rule publisher sample -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<!-- <scope>test</scope>-->
</dependency>
3. 相关类修改
找到 sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos目录,将整个目录拷贝到 sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos
4.修改NacosConfig类
修改NacosConfig类,修改NacosIP地址
5. FlowControllerV1修改
自动注入provider和publisher
@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
修改rules接口,读取nacos中的数据
@GetMapping("/rules")
@AuthAction(PrivilegeType.READ_RULE)
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app) {
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
try {
List<FlowRuleEntity> rules = ruleProvider.getRules(app);
if (rules != null && !rules.isEmpty()) {
for (FlowRuleEntity entity : rules) {
entity.setApp(app);
if (entity.getClusterConfig() != null && entity.getClusterConfig().getFlowId() != null) {
entity.setId(entity.getClusterConfig().getFlowId());
}
}
}
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
logger.error("Error when querying flow rules", throwable);
return Result.ofThrowable(-1, throwable);
}
}
该类最后的publishRules方法修改如下
private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {
List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
try {
rulePublisher.publish(app, rules);
logger.info("添加限流规则成功.....");
} catch (Exception e) {
e.printStackTrace();
logger.info("添加限流规则失败.....");
}
return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
}
测试
访问http://localhost:8080/可以进入到控制台界面,但是界面上没有任何的客户端
请求一次http://localhost:8083/order/createorder/1,等一会儿,刷新一下就可以看到客户端了
添加流控规则
并刷新一下就可以看到我们添加的规则了
在nacos配置中心查看
我们发现配置已经被推送到了nacos
重启客户端进行测试
重启客户端后发现我们的规则是生效的,并且修改规则后重启客户端规则也是生效的