生产环境Sentinel改造实践(二):规则管理推送改造
前文介绍了Sentinel相关的核心概念,本文开始动手对规则管理推送进行改造。
这里挑选流控规则
模式改造为示例
Sentinel Dashboard 改造
-
在
com.alibaba.csp.sentinel.dashboard.rule.nacos
新建NacosConfig.java
package com.alibaba.csp.sentinel.dashboard.rule.nacos; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.fastjson.JSON; import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.config.ConfigFactory; import com.alibaba.nacos.api.config.ConfigService; import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; import java.util.Properties; /** * @wiki https://github.com/eacdy/Sentinel-Dashboard-Nacos * add by tam */ @Configuration public class NacosConfig { @Bean public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() { return JSON::toJSONString; } @Bean public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() { return s -> JSON.parseArray(s, FlowRuleEntity.class); } @Bean public ConfigService nacosConfigService() throws Exception { NacosProperties nacosProperties = nacosProperties(); Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, nacosProperties.getServerAddr()); if (!nacosProperties.getNamespace().isEmpty()) { properties.put(PropertyKeyConst.NAMESPACE, nacosProperties.getNamespace()); } return ConfigFactory.createConfigService(properties); } @Bean @ConfigurationProperties(prefix = "spring.cloud.sentinel.datasource.nacos") public NacosProperties nacosProperties() { return new NacosProperties(); } @Getter @Setter public static class NacosProperties { private String serverAddr; private String namespace; private String groupId; } }
这里主要接收三个参数
serverAddr
: nacos服务器地址,namespace
:nacos命名空间,groupId
:nacos分组在
application.properties
里新增配置spring.cloud.sentinel.datasource.nacos.server-addr=172.16.1.20:8848 spring.cloud.sentinel.datasource.nacos.groupId=DEFAULT_GROUP spring.cloud.sentinel.datasource.nacos.namespace=wuyan_local
-
同级目录下新增
NacosConfigUtil.java
package com.alibaba.csp.sentinel.dashboard.rule.nacos; import com.alibaba.csp.sentinel.dashboard.util.JSONUtils; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.RuleEntity; import com.alibaba.fastjson.JSON; import com.alibaba.csp.sentinel.slots.block.Rule; import com.alibaba.csp.sentinel.util.AssertUtil; import com.alibaba.csp.sentinel.util.StringUtil; import com.alibaba.nacos.api.exception.NacosException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * @wiki https://github.com/eacdy/Sentinel-Dashboard-Nacos * add by tam */ @Component public class NacosConfigUtil { @Autowired private NacosConfig.NacosProperties nacosProperties; public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules"; public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-rules"; public static final String SYSTEM_DATA_ID_POSTFIX = "-system-rules"; public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-flow-rules"; public static final String AUTHORITY_DATA_ID_POSTFIX = "-authority-rules"; public static final String GATEWAY_FLOW_DATA_ID_POSTFIX = "-gateway-flow-rules"; public static final String GATEWAY_API_DATA_ID_POSTFIX = "-gateway-api-rules"; public static final String DASHBOARD_POSTFIX = "-dashboard"; public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map"; /** * cc for `cluster-client` */ public static final String CLIENT_CONFIG_DATA_ID_POSTFIX = "-cc-config"; /** * cs for `cluster-server` */ public static final String SERVER_TRANSPORT_CONFIG_DATA_ID_POSTFIX = "-cs-transport-config"; public static final String SERVER_FLOW_CONFIG_DATA_ID_POSTFIX = "-cs-flow-config"; public static final String SERVER_NAMESPACE_SET_DATA_ID_POSTFIX = "-cs-namespace-set"; /** * 将规则序列化成JSON文本,存储到Nacos server中 * * @param configService nacos config service * @param app 应用名称 * @param postfix 规则后缀 eg.NacosConfigUtil.FLOW_DATA_ID_POSTFIX * @param rules 规则对象 * @throws NacosException 异常 */ public <T> void setRuleStringToNacos(ConfigService configService, String app, String postfix, List<T> rules) throws NacosException { AssertUtil.notEmpty(app, "app name cannot be empty"); if (rules == null) { return; } List<Rule> ruleForApp = rules.stream() .map(rule -> { RuleEntity rule1 = (RuleEntity) rule; //System.out.println(rule1.getClass()); Rule rule2 = rule1.toRule(); //System.out.println(rule2.getClass()); return rule2; }) .collect(Collectors.toList()); // 存储,给微服务使用 String dataId = genDataId(app, postfix); configService.publishConfig( dataId, nacosProperties.getGroupId(), JSON.toJSONString(ruleForApp) ); // 存储,给控制台使用 configService.publishConfig( dataId + DASHBOARD_POSTFIX, nacosProperties.getGroupId(), JSONUtils.toJSONString(rules) ); } /** * 从Nacos server中查询响应规则,并将其反序列化成对应Rule实体 * * @param configService nacos config service * @param appName 应用名称 * @param postfix 规则后缀 eg.NacosConfigUtil.FLOW_DATA_ID_POSTFIX * @param clazz 类 * @param <T> 泛型 * @return 规则对象列表 * @throws NacosException 异常 */ public <T> List<T> getRuleEntitiesFromNacos(ConfigService configService, String appName, String postfix, Class<T> clazz) throws NacosException { String rules = configService.getConfig( genDataId(appName, postfix) + DASHBOARD_POSTFIX, //genDataId(appName, postfix), nacosProperties.getGroupId(), 3000 ); if (StringUtil.isEmpty(rules)) { return new ArrayList<>(); } return JSONUtils.parseObject(clazz, rules); } private static String genDataId(String appName, String postfix) { return appName + postfix; }
注意这里的
dataId
完整的为 【appId(即客户端spring.application.name配置应用名)+-flow-rules
】这个很重要,客户端在集成nacos的sentinel配置时这个要对应
-
在
com.alibaba.csp.sentinel.dashboard.rule.nacos.flow
目录下新建FlowRuleNacosProvider.java
package com.alibaba.csp.sentinel.dashboard.rule.nacos.flow; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; import com.alibaba.nacos.api.config.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; /** * @author Eric Zhao * @since 1.4.0 * add by tam */ @Component("flowRuleNacosProvider") public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> { @Autowired private ConfigService configService; @Autowired private NacosConfigUtil nacosConfigUtil; @Override public List<FlowRuleEntity> getRules(String appName) throws Exception { return nacosConfigUtil.getRuleEntitiesFromNacos( this.configService, appName, NacosConfigUtil.FLOW_DATA_ID_POSTFIX, FlowRuleEntity.class ); } }
这个类主要从Nacos拉取规则信息
-
在
com.alibaba.csp.sentinel.dashboard.rule.nacos.flow
目录下新建FlowRuleNacosPublisher.java
package com.alibaba.csp.sentinel.dashboard.rule.nacos.flow; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; import com.alibaba.nacos.api.config.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; /** * @author Eric Zhao * @since 1.4.0 * add by tam */ @Component("flowRuleNacosPublisher") public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> { @Autowired private ConfigService configService; @Autowired private NacosConfigUtil nacosConfigUtil; @Override public void publish(String app, List<FlowRuleEntity> rules) throws Exception { nacosConfigUtil.setRuleStringToNacos( this.configService, app, NacosConfigUtil.FLOW_DATA_ID_POSTFIX, rules ); } }
-
修改
com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2
类@Autowired @Qualifier("flowRuleNacosProvider") private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider; @Autowired @Qualifier("flowRuleNacosPublisher") private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
主要增加
@Qualifier("flowRuleNacosProvider")
和@Qualifier("flowRuleNacosPublisher")
Sentinel接入客户端
项目如果是SpringCloud项目在pom文件里引入
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
在bootstrap.properties
新增如下配置
server.port=8002
spring.application.name=qetesh-openapi
spring.cloud.nacos.discovery.server-addr=172.16.1.20:8848
spring.cloud.nacos.discovery.namespace=wuyan_local
spring.cloud.sentinel.transport.dashboard=localhost:8888
spring.cloud.sentinel.eager=true
spring.cloud.sentinel.datasource.ds1.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.ds1.nacos.dataId=${spring.application.name}-flow-rules
spring.cloud.sentinel.datasource.ds1.nacos.namespace=wuyan_local
spring.cloud.sentinel.datasource.ds1.nacos.groupId=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.rule-type=flow
注意三个参数 serverAddr
,namespace
,groupId
和Dashboard的保持一致
并且spring.cloud.sentinel.datasource.ds1.nacos.rule-type 值为flow(流控)
在启动类增加如下代码
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableDiscoveryClient
public class QeteshOpenapiApplication {
public static void main(String[] args) {
SpringApplication.run(QeteshOpenapiApplication.class, args);
}
@RestController
static class TestController {
@SentinelResource("ken2")
@GetMapping("/hello")
public String hello() {
return "itweek.top";
}
}
}
启动项目访问接口,在DashBoard里就能看到相关的配置
在流控规则里新增如下配置,
这时在nacos也会有相应的配置
多次访问接口会出现 即代表流控规则限流成功
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)