> 文档中心 > Sentinel(五)整合Nacos实现动态规则配置持久化、双向同步

Sentinel(五)整合Nacos实现动态规则配置持久化、双向同步

这里写目录标题

  • 1、为什么整合Nacos
  • 2、效果演示
  • 3、源码拉取
  • 3、创建公共配置
  • 4、控制台规则配置
    • 4.1、流程规则
    • 4.2、降级规则
    • 4.3、热点规则
    • 4.4、系统规则
    • 4.5、授权规则
  • 5、网关控制台规则配置
    • 5.1、API管理
    • 5.2、流程规则
    • 5.3、降级规则
    • 5.4、系统规则
  • 5、打包部署
  • 6、源码包下载

1、为什么整合Nacos

默认情况下Sentinel配置的规则是储存的内存中,在重新Sentinel服务后,配置会显示,我们通过整合第三方中间件实现,配置的持久化,比如使用Nacos

我们要实现SentinelNacos的双向同步持久化,就需要对sentinel-dashboard的源码包进行修改。

2、效果演示

我们以流控规则为例,演示一个数据同步持久化的操作;

1、nacos同步到sentinel:

在nacos中,新增配置文件,文件的DataId为sentinel,内容为:

[    {    "app":"user-service",// 服务名称 "resource": "/list", //资源名称 "count": 1, //阀值 "grade": 1, //阀值类型,0表示线程数,1表示QPS; "limitApp": "default", //来源应用 "strategy": 0,// 流控模式,0表示直接,1表示关联,2表示链路; "controlBehavior": 0 //流控效果,0表示快速失败,1表示Warm Up,2表示排队等待    }]

Sentinel(五)整合Nacos实现动态规则配置持久化、双向同步
查看Sentinel控制台:数据已经实现了同步
Sentinel(五)整合Nacos实现动态规则配置持久化、双向同步

2、sentinel同步到nacos:

我们在sentinel控制台,建立任意流控规则,如下:
Sentinel(五)整合Nacos实现动态规则配置持久化、双向同步

查看Nacos控制台:配置数据已经实现了同步
Sentinel(五)整合Nacos实现动态规则配置持久化、双向同步

3、源码拉取

1、下载源码压缩包
在Sentinel-github下载需要版本的压缩包,比如Sentinel-1.8.1.zip

2、加载源码
将下载好的Sentinel-1.8.1.zip解压,使用IDE工具,打开sentinel-dashboard工程
Sentinel(五)整合Nacos实现动态规则配置持久化、双向同步

3、修改pom

sentinel-datasource-nacosscope标签注释掉

<dependency>    <groupId>com.alibaba.csp</groupId>    <artifactId>sentinel-datasource-nacos</artifactId>    <!--test--></dependency>

3、创建公共配置

在进行规则代码修改之前需要创建Nacos配置文件,在com.alibaba.csp.sentinel.dashboard.rule包下创建nacos包,并且在包下创建四个类:RuleNacosConfigRuleNacosProviderRuleNacosPublisherRuleNacosConstants
在这里插入图片描述

RuleNacosConfig:

@Configurationpublic class RuleNacosConfig{    @Bean    public ConfigService nacosConfigService() throws Exception { Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, "112.15.11.18:8848"); // properties.put(PropertyKeyConst.NAMESPACE, "xxx"); 命名空间 // properties.put(PropertyKeyConst.USERNAME, "xxx"); 用户名 // properties.put(PropertyKeyConst.PASSWORD, "xxx"); 密码 return ConfigFactory.createConfigService(properties);    }}

RuleNacosProvider:

@Componentpublic class RuleNacosProvider {    @Autowired    private ConfigService configService;    public String getRules(String dataId, String app) throws Exception { // 将服务名称设置为GroupId return configService.getConfig(dataId, app, 3000);    }}

RuleNacosPublisher:

@Componentpublic class RuleNacosPublisher {    @Autowired    private ConfigService configService;    public void publish(String dataId, String app, String rules) throws Exception { AssertUtil.notEmpty(app, "app name cannot be empty"); if (rules == null) {     return; } // 将服务名称设置为GroupId configService.publishConfig(dataId, app, rules);    }}

RuleNacosConstants :

public class RuleNacosConstants {    public static final String FLOW_DATA_ID = "sentinel.rule.flow";    public static final String DEGRADE_DATA_ID = "sentinel.rule.degrade";    public static final String SYSTEM_DATA_ID = "sentinel.rule.system";    public static final String PARAM_DATA_ID = "sentinel.rule.param";    public static final String AUTHORITY_DATA_ID = "sentinel.rule.authority";    public static final String GATEWAY_API_DATA_ID = "sentinel.rule.gateway.api";    public static final String GATEWAY_FLOW_DATA_ID = "sentinel.rule.gateway.flow";}

4、控制台规则配置

通过修改源码,实现流控规则、降级规则、热点规则、系统规则、授权规则的持久化操作;

4.1、流程规则

1、修改sidebar.html:

<li ui-sref-active="active">    <a ui-sref="dashboard.flowV1({app: entry.app})"> <i class="glyphicon glyphicon-filter"></i>  流控规则    </a></li><li ui-sref-active="active">    <a ui-sref="dashboard.flow({app: entry.app})"> <i class="glyphicon glyphicon-filter"></i>  流控规则    </a></li>

2、修改FlowControllerV2:
RuleNacosProviderRuleNacosPublisher注入到FlowControllerV2

// 修改位置如下:@Autowired@Qualifier("flowRuleDefaultProvider")private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;@Autowired@Qualifier("flowRuleDefaultPublisher")private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;// 将上面代码修改为以下代码:@Autowiredprivate RuleNacosProvider ruleProvider;@Autowiredprivate RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下: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());   }     }}// 将上面代码修改为以下代码:String ruleStr = ruleProvider.getRules(RuleNacosConstants.FLOW_DATA_ID, app);List<FlowRuleEntity> rules = new ArrayList<>();if (ruleStr != null) {    rules = JSON.parseArray(ruleStr, FlowRuleEntity.class);    if (rules != null && !rules.isEmpty()) { for (FlowRuleEntity entity : rules) {     entity.setApp(app); }    } }

修改推送逻辑:

// 修改位置如下:private void publishRules(/*@NonNull*/ String app) throws Exception {    List<FlowRuleEntity> rules = repository.findAllByApp(app);    rulePublisher.publish(app, rules);}// 将上面代码修改为以下代码:private void publishRules(String app) {  try {List<FlowRuleEntity> rules = repository.findAllByApp(app);String ruleStr = JSON.toJSONString(rules);rulePublisher.publish(RuleNacosConstants.FLOW_DATA_ID, app, ruleStr);  } catch (Exception e) {      e.printStackTrace();  }}

4.2、降级规则

修改DegradeController:
RuleNacosProviderRuleNacosPublisher注入到DegradeController

// 加入以下代码:@Autowiredprivate RuleNacosProvider ruleProvider;@Autowiredprivate RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:List<DegradeRuleEntity> rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);// 将上面代码修改为以下代码:String ruleStr = ruleProvider.getRules(RuleNacosConstants.DEGRADE_DATA_ID, app);List<DegradeRuleEntity> rules = new ArrayList<>();if (ruleStr != null) {    rules = JSON.parseArray(ruleStr, DegradeRuleEntity.class);    if (rules != null && !rules.isEmpty()) {for (DegradeRuleEntity entity : rules) {    entity.setApp(app);}   }}

修改推送逻辑:

// 1、修改位置如下:private boolean publishRules(String app, String ip, Integer port) {   List<DegradeRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));   return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);}// 将上面代码修改为以下代码:private void publishRules(String app) {  try {      List<DegradeRuleEntity> rules = repository.findAllByApp(app);      String ruleStr = JSON.toJSONString(rules);      rulePublisher.publish(RuleNacosConstants.DEGRADE_DATA_ID, app, ruleStr);  } catch (Exception e) {     e.printStackTrace();  }}=======================================================================================// 2、修改位置如下:有两处if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {     logger.warn("Publish degrade rules failed, app={}", entity.getApp());}// 将上面代码修改为以下代码:publishRules(entity.getApp());=======================================================================================// 3、修改位置如下:if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {   logger.warn("Publish degrade rules failed, app={}", oldEntity.getApp());}// 将上面代码修改为以下代码:publishRules(oldEntity.getApp());

4.3、热点规则

修改ParamRuleController:
RuleNacosProviderRuleNacosPublisher注入到ParamFlowRuleController

// 加入以下代码:@Autowiredprivate RuleNacosProvider ruleProvider;@Autowiredprivate RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:return sentinelApiClient.fetchParamFlowRulesOfMachine(app, ip, port)  .thenApply(repository::saveAll)  .thenApply(Result::ofSuccess)  .get();// 将上面代码修改为以下代码:String ruleStr = ruleProvider.getRules(RuleNacosConstants.PARAM_DATA_ID, app);List<ParamFlowRuleEntity> rules = new ArrayList<>();if (ruleStr != null) {    rules = JSON.parseArray(ruleStr, ParamFlowRuleEntity.class);    if (rules != null && !rules.isEmpty()) { for (ParamFlowRuleEntity entity : rules) {    entity.setApp(app);   }    }}rules = repository.saveAll(rules);return Result.ofSuccess(rules);

修改推送逻辑:

// 1、修改位置如下:private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {    List<ParamFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));    return sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules);}// 将上面代码修改为以下代码:private void publishRules(String app) {   try {List<ParamFlowRuleEntity> rules = repository.findAllByApp(app);String ruleStr = JSON.toJSONString(rules);rulePublisher.publish(RuleNacosConstants.PARAM_DATA_ID, app, ruleStr);   } catch (Exception e) {     e.printStackTrace();   }}=======================================================================================// 2、修改位置如下:有两处try {   entity = repository.save(entity);   publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get();   return Result.ofSuccess(entity);} catch (ExecutionException ex) {....}// 将上面代码修改为以下代码:try {   entity = repository.save(entity);   publishRules(entity.getApp());   return Result.ofSuccess(entity);} catch (Exception ex) {....}=======================================================================================// 3、修改位置如下:try { repository.delete(id);    publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get();    return Result.ofSuccess(id);} catch (ExecutionException ex) {....}// 将上面代码修改为以下代码:try { repository.delete(id);    publishRules(oldEntity.getApp());    return Result.ofSuccess(id);} catch (Exception ex) {....}

4.4、系统规则

修改SystemController:
RuleNacosProviderRuleNacosPublisher注入到SystemController

// 加入以下代码:@Autowiredprivate RuleNacosProvider ruleProvider;@Autowiredprivate RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:List<SystemRuleEntity> rules = sentinelApiClient.fetchSystemRuleOfMachine(app, ip, port);// 将上面代码修改为以下代码:String ruleStr = ruleProvider.getRules(RuleNacosConstants.SYSTEM_DATA_ID, app);List<SystemRuleEntity> rules = new ArrayList<>();if (ruleStr != null) {    rules = JSON.parseArray(ruleStr, SystemRuleEntity.class);    if (rules != null && !rules.isEmpty()) { for (SystemRuleEntity entity : rules) {      entity.setApp(app); }    }}

修改推送逻辑:

// 1、修改位置如下:private boolean publishRules(String app, String ip, Integer port) {   List<SystemRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));   return sentinelApiClient.setSystemRuleOfMachine(app, ip, port, rules);}// 将上面代码修改为以下代码:private void publishRules(String app) {  try {List<SystemRuleEntity> rules = repository.findAllByApp(app);String ruleStr = JSON.toJSONString(rules);rulePublisher.publish(RuleNacosConstants.SYSTEM_DATA_ID, app, ruleStr);   } catch (Exception e) {e.printStackTrace();  }}=======================================================================================// 2、修改位置如下if (!publishRules(app, ip, port)) {    logger.warn("Publish system rules fail after rule add");}// 将上面代码修改为以下代码:publishRules(entity.getApp());=======================================================================================// 3、修改位置如下if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {    logger.info("publish system rules fail after rule update");}// 将上面代码修改为以下代码:publishRules(entity.getApp());=======================================================================================// 4、修改位置如下:if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {    logger.info("publish system rules fail after rule delete");}// 将上面代码修改为以下代码:publishRules(oldEntity.getApp());

4.5、授权规则

修改AuthorityRuleController:
RuleNacosPublisherRuleNacosProvider注入到AuthorityRuleController

// 加入以下代码:@Autowiredprivate RuleNacosProvider ruleProvider;@Autowiredprivate RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:List<AuthorityRuleEntity> rules = sentinelApiClient.fetchAuthorityRulesOfMachine(app, ip, port);// 将上面代码修改为以下代码: String ruleStr = ruleProvider.getRules(RuleNacosConstants.AUTHORITY_DATA_ID, app);List<AuthorityRuleEntity> rules = new ArrayList<>();if (ruleStr != null) {     rules = JSON.parseArray(ruleStr, AuthorityRuleEntity.class);     if (rules != null && !rules.isEmpty()) {  for (AuthorityRuleEntity entity : rules) {entity.setApp(app);  }    }}  

修改推送逻辑:

// 1、修改位置如下:private boolean publishRules(String app, String ip, Integer port) {    List<AuthorityRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));    return sentinelApiClient.setAuthorityRuleOfMachine(app, ip, port, rules);}// 将上面代码修改为以下代码:private void publishRules(String app) {   try {List<AuthorityRuleEntity> rules = repository.findAllByApp(app);String ruleStr = JSON.toJSONString(rules);rulePublisher.publish(RuleNacosConstants.AUTHORITY_DATA_ID, app, ruleStr);   } catch (Exception e) {e.printStackTrace();   }}=======================================================================================// 2、修改位置如下:有两处if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {    logger.info("Publish authority rules failed after rule update");}// 将上面代码修改为以下代码:publishRules(entity.getApp());=======================================================================================// 3、修改位置如下:if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {   logger.error("Publish authority rules failed after rule delete");}// 将上面代码修改为以下代码:publishRules(oldEntity.getApp());

5、网关控制台规则配置

配置网关控制台规则,在启动网关时需要加上参数:-Dcsp.sentinel.app.type=1

5.1、API管理

修改GatewayApiController:
RuleNacosPublisherRuleNacosProvider注入到GatewayApiController

// 加入以下代码:@Autowiredprivate RuleNacosProvider ruleProvider;@Autowiredprivate RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:List<ApiDefinitionEntity> apis = sentinelApiClient.fetchApis(app, ip, port).get();// 将上面代码修改为以下代码:String ruleStr = ruleProvider.getRules(RuleNacosConstants.GATEWAY_API_DATA_ID, app);List<ApiDefinitionEntity> apis = new ArrayList<>();if (ruleStr != null) {    apis = JSON.parseArray(ruleStr, ApiDefinitionEntity.class);    if (apis != null && !apis.isEmpty()) { for (ApiDefinitionEntity entity : apis) {      entity.setApp(app); }    }}  

修改推送逻辑:

// 1、修改位置如下:private boolean publishApis(String app, String ip, Integer port) {   List<ApiDefinitionEntity> apis = repository.findAllByMachine(MachineInfo.of(app, ip, port));   return sentinelApiClient.modifyApis(app, ip, port, apis);}// 将上面代码修改为以下代码:private void publishApi(String app) {  try {     List<ApiDefinitionEntity> apis= repository.findAllByApp(app);     String ruleStr = JSON.toJSONString(apis);     rulePublisher.publish(RuleNacosConstants.GATEWAY_API_DATA_ID, app, ruleStr);     } catch (Exception e) {  e.printStackTrace();   }}=======================================================================================// 2、修改位置如下if (!publishApis(app, ip, port)) {     logger.warn("publish gateway apis fail after add");}// 将上面代码修改为以下代码:publishApi(entity.getApp());=======================================================================================// 3、修改位置如下if (!publishApis(app, entity.getIp(), entity.getPort())) {    logger.warn("publish gateway apis fail after update");}// 将上面代码修改为以下代码:publishRules(entity.getApp());=======================================================================================// 4、修改位置如下:if (!publishApis(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {    logger.warn("publish gateway apis fail after delete");}// 将上面代码修改为以下代码:publishRules(oldEntity.getApp());

5.2、流程规则

修改GatewayFlowRuleController:
RuleNacosPublisherRuleNacosProvider注入到GatewayFlowRuleController

// 加入以下代码:@Autowiredprivate RuleNacosProvider ruleProvider;@Autowiredprivate RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:List<GatewayFlowRuleEntity> rules = sentinelApiClient.fetchGatewayFlowRules(app, ip, port).get();// 将上面代码修改为以下代码:String ruleStr = ruleProvider.getRules(RuleNacosConstants.GATEWAY_FLOW_DATA_ID, app);List<GatewayFlowRuleEntity> rules = new ArrayList<>();if (ruleStr != null) {    rules = JSON.parseArray(ruleStr, GatewayFlowRuleEntity.class);    if (rules != null && !rules.isEmpty()) {for (GatewayFlowRuleEntity entity : rules) {    entity.setApp(app); }    }}

修改推送逻辑:

// 1、修改位置如下:private boolean publishRules(String app, String ip, Integer port) {   List<GatewayFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));   return sentinelApiClient.modifyGatewayFlowRules(app, ip, port, rules);}// 将上面代码修改为以下代码:private void publishRules(String app) {  try {      List<GatewayFlowRuleEntity> rules = repository.findAllByApp(app);      String ruleStr = JSON.toJSONString(rules);      rulePublisher.publish(RuleNacosConstants.GATEWAY_FLOW_DATA_ID, app, ruleStr);   } catch (Exception e) {      e.printStackTrace();   }}=======================================================================================// 2、修改位置如下if (!publishRules(app, ip, port)) {    logger.warn("publish gateway flow rules fail after add");}// 将上面代码修改为以下代码:publishRules(entity.getApp());=======================================================================================// 3、修改位置如下if (!publishRules(app, entity.getIp(), entity.getPort())) {    logger.warn("publish gateway flow rules fail after update");}// 将上面代码修改为以下代码:publishRules(entity.getApp());=======================================================================================// 4、修改位置如下:if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {    logger.warn("publish gateway flow rules fail after delete");}// 将上面代码修改为以下代码:publishRules(oldEntity.getApp());

5.3、降级规则

使用的是控制台规则配置中的降级规则接口,无需在做操作,参考《4.2、降级规则》。

5.4、系统规则

使用的是控制台规则配置中的降级规则接口,无需在做操作,参考《4.4、系统规则》。

5、打包部署

进入到sentinel-dashboard所在目的,通过mvn clean install package -DskipTests=true进行打包。

部署jar参考:
《Linux搭建Sentinel 控制台环境》
《Docker搭建Sentinel 控制台环境》

6、源码包下载

对于上述修改的代码,源码下载地址:https://download.csdn.net/download/zhuocailing3390/83337923,将下载的ControllerNacos配置代码直接拷贝到源码中即可使用。