赞
踩
文中使用的nacos版本1.4.2、sentinel版本1.8.3
当集成了Sentinel的客户端应用重启之后,在控制台配置的规则全部都没有了,如果需要上生产环境需要将规则配置进行持久化。下面就来实现Sentinel规则配置持久化。
需要持久化至nacos就需要添加相关Maven依赖
<!-- Sentinel Datasource 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
</dependency>
<!-- Sentinel Datasource Nacos 依赖 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
默认 Nacos 适配的 dataId 和 groupId 约定如下:
spring: cloud: sentinel: datasource: # 自定义命名 flow-rule: # 支持多种持久化数据源:file、nacos、zk、apollo、redis、consul nacos: # naco服务地址 server-addr: localhost:8848 # 命名空间,根据环境配置 namespace: public # 这里我做了一下细分,不同规则设置不同groupId group-id: SENTINEL_FLOW_GROUP # 仅支持JSON和XML类型 data-id: ${spring.application.name}-flow-rules.json # 规则类型:flow、degrade、param-flow、system、authority rule-type: flow # nacos开启了认证需要配置username、password # username: nacos # password: nacos
[{
"clusterMode": false,
"controlBehavior": 0,
"count": 5.0,
"grade": 1,
"limitApp": "default",
"resource": "/sentinel/flow",
"strategy": 0
}]
规则配置详细官方文档:https://sentinelguard.io/zh-cn/docs/basic-api-resource-rule.html
配置完成后,重启项目可以看到规则配置依然存在。修改Nacos中的配置也可以实时同步至Sentinel控制台了。
从上面看来配置的规则可以持久化了,Nacos配置中心修改的规则可能实时同步至Sentinel控制台。但是在控制台中新增、修改、删除规则是无法同步至Nacos配置中心。在控制台添加了一个规则,如果客户端重启,规则就会丢失。下面就来实现控制台添加规则并推送至Nacos。
根据官方文档所述:Sentinel 控制台提供 DynamicRulePublisher 和 DynamicRuleProvider 接口用于实现应用维度的规则推送和拉取。
<!-- 添加Nacos配置中心依赖 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.10</version>
</dependency>
groupId根据命名约束自定义命名。
# 配置nacos服务地址与命名空间,可根据环境配置命名空间
nacos.config.server-addr=localhost:8848
nacos.config.namespace=8b1673aa-38da-48c6-bc5a-6df956ed0956
# 配置nacos groupId,可以自定义groupId
# 跟上面一样按照不同规则设置不同groupId
sentinel.nacos.flow.group-id=SENTINEL_FLOW_GROUP
sentinel.nacos.degrade.group-id=SENTINEL_DEGRADE_GROUP
sentinel.nacos.auth.group-id=SENTINEL_AUTH_GROUP
sentinel.nacos.param.group-id=SENTINEL_PARAM_GROUP
sentinel.nacos.system.group-id=SENTINEL_SYSTEM_GROUP
/** * @ClassName FlowRulePublisher * @Description 推送流控规则 * @Author tigerkin * @Date 2022/3/9 14:40 */ @Component public class FlowRulePublisher implements DynamicRulePublisher<List<FlowRuleEntity>> { private static final Logger LOG = LoggerFactory.getLogger(FlowRulePublisher.class); @Value("${sentinel.nacos.flow.group-id}") private String nacosFlowGroupId; @Autowired private NacosConfigProperties nacosConfigProperties; /** * 重要属性: * resource 资源名,资源名是限流规则的作用对象 * count 限流阈值 * grade 限流阈值类型,QPS 或线程数模式 QPS 模式 * limitApp 流控针对的调用来源 default,代表不区分调用来源 * strategy 调用关系限流策略:直接、链路、关联 根据资源本身(直接) * controlBehavior 流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流 直接拒绝 * @param app app name * @param rules list of rules to push * @throws Exception */ @Override public void publish(String app, List<FlowRuleEntity> rules) throws Exception { if (StringUtil.isBlank(app)) { return; } if (rules == null) { return; } LOG.info("========> 流控规则推送 -> app: {} rules:{}", app, JSON.toJSONString(rules)); List<FlowRuleEntity> flowFules = rules.stream().map(data -> { FlowRuleEntity entity = new FlowRuleEntity(); entity.setResource(data.getResource()); entity.setCount(data.getCount()); entity.setGrade(data.getGrade()); entity.setLimitApp(data.getLimitApp()); entity.setStrategy(data.getStrategy()); entity.setControlBehavior(data.getControlBehavior()); return entity; }).collect(Collectors.toList()); /** * sentinel推送nacos命名约束 * 流控规则 dataId: {appName}-flow-rules,比如应用名为 appA,则 dataId 为 appA-flow-rules */ String dataId = String.format("%s-flow-rules.json", app); HttpHandler.handler(flowFules, nacosConfigProperties, nacosFlowGroupId, dataId); } }
/** * @ClassName HttpHandler * @Description * @Author tigerkin * @Date 2022/3/10 11:06 */ public class HttpHandler { private static final Logger LOG = LoggerFactory.getLogger(HttpHandler.class); public static void handler(Object rules, NacosConfigProperties nacosConfigProperties, String groupId, String dataId) throws IOException { StringJoiner param = new StringJoiner("&"); param.add(String.format("tenant=%s", nacosConfigProperties.getNamespace())); // Nacos 的命名空间ID字段 param.add(String.format("dataId=%s", dataId)); param.add(String.format("group=%s", groupId)); param.add(String.format("content=%s", URLEncoder.encode(JSON.toJSONString(rules), "UTF-8"))); param.add(String.format("type=%s", "json")); String url = String.format("http://%s/nacos/v1/cs/configs?%s", nacosConfigProperties.getServerAddr(), param.toString()); HttpPost httpPost = new HttpPost(url); CloseableHttpClient httpclient = HttpClients.createDefault(); CloseableHttpResponse response = httpclient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == 200) { HttpEntity entity = response.getEntity(); String result = EntityUtils.toString(entity); LOG.info("========> 发布成功:{}", result); } else { LOG.error("========> 发布失败:{}", response.toString()); } } }
实现在推送接口后,找到Sentinel规则配置的Controller,并添加推送逻辑。我这里改造的是FlowControllerV1。
添加依赖注入属性:
最后在Controller中找到publisherRules方法,添加推送方法调用就可以了。
Sentinel在规则变更后会给客户端发送一个请求,去同步规则配置。
下面在控制台添加规则,就会推送至Nacos配置中心了。至此Sentinel配置规则持久化至Nacos就完成了。
参考:
Nacos Open API 文档:https://nacos.io/zh-cn/docs/open-api.html
Sentinel github地址:https://github.com/alibaba/Sentinel/releases
Sentinel官方文档:
https://github.com/alibaba/Sentinel/wiki/在生产环境中使用-Sentinel
https://github.com/alibaba/Sentinel/wiki/Sentinel-控制台(集群流控管理)#规则配置
提供相关业务逻辑处理源码位置,有兴趣的童鞋可以看一看。
客户端处理Sentinel请求的源码位置:
jar: sentinel-transport-common-1.8.3.jar
package: com.alibaba.csp.sentinel.command.handler
nacos监听处理源码位置:
jar: sentinel-datasource-nacos-1.8.3.jar
package: com.alibaba.csp.sentinel.datasource.nacos
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。