sentinel-1.8.7与nacos-2.3.0实现动态规则配置、双向同步

???? @ 作者: 一恍过去
???? @ 主页: https://blog.****.net/zhuocailing3390
???? @ 社区: Java技术栈交流
???? @ 主题: sentinel-1.8.7与nacos-2.3.0实现动态规则配置、双向同步
⏱️ @ 创作时间: 2024年04月2日

目录

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

1、为什么整合Nacos

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

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

2、源码拉取

1、下载源码压缩包
Sentinel-github下载需要版本的压缩包,比如Sentinel-1.8.7.zip,或者直接从Git上将代码Clone

2、加载源码
将下载好的Sentinel-1.8.7.zip解压,使用IDE工具,打开sentinel-dashboard工程,或者直接从Git上将代码Clone
在这里插入图片描述

3、创建公共配置

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

RuleNacosConfig:

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;


@Configuration
public class NacosConfig {

    @Bean
    public ConfigService nacosConfigService() throws Exception {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, "localhost:8848");
        // properties.put(PropertyKeyConst.NAMESPACE, "xxx");
        properties.put(PropertyKeyConst.USERNAME, "nacos");
        properties.put(PropertyKeyConst.PASSWORD, "nacos");
        return ConfigFactory.createConfigService(properties);
    }
}

RuleNacosProvider:

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RuleNacosProvider {

    @Autowired
    private ConfigService configService;

    public String getRules(String dataId) throws Exception {

        // 将服务名称设置为GroupId
        return configService.getConfig(dataId, NacosConfigUtil.GROUP_ID, 3000);
    }
}

RuleNacosPublisher:

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RuleNacosPublisher {

    @Autowired
    private ConfigService configService;

    public void publish(String dataId, String rules) {
        try {
            if (rules == null) {
                return;
            }
            configService.publishConfig(dataId, NacosConfigUtil.GROUP_ID, rules);
        } catch (NacosException e) {
            throw new RuntimeException(e);
        }
    }
}

NacosConfigUtil:

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
public final class NacosConfigUtil {

    public static final String GROUP_ID = "SENTINEL_GROUP";

    public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";

    public static final String GATEWAY_FLOW_DATA_ID_POSTFIX = "-gateway-rules";

    public static final String AUTHORITY_FLOW_DATA_ID_POSTFIX = "-authority-rules";

    public static final String SYSTEM_FLOW_DATA_ID_POSTFIX = "-system-rules";

    public static final String DEGRADE_FLOW_DATA_ID_POSTFIX = "-degrade-rules";

    public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules";

    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";

    private NacosConfigUtil() {
    }
}

4、控制台规则配置

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

4.1、流控规则

修改FlowControllerV1:
RuleNacosPublisherRuleNacosProvider注入到FlowControllerV1

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

修改读取逻辑:

// 修改位置如下:
List<FlowRuleEntity> rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX);
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);
         }
    }
}

修改推送逻辑:

// 1、修改位置如下:
private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {
     List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
     return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
}

// 将上面代码修改为以下代码:
private void publishRules(String app) {
   List<FlowRuleEntity> rules = repository.findAllByApp(app);
   String ruleStr = JSON.toJSONString(rules);
   rulePublisher.publish(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, ruleStr);
}
=======================================================================================

// 2、修改位置如下:有两处
publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);

// 将上面代码修改为以下代码:
publishRules(entity.getApp());
=======================================================================================

// 3、修改位置如下:
publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(5000, TimeUnit.MILLISECONDS);

// 将上面代码修改为以下代码:
publishRules(oldEntity.getApp());

4.2、熔断降级规则

修改DegradeController:
RuleNacosProviderRuleNacosPublisher注入到DegradeController

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

修改读取逻辑:

// 修改位置如下:
List<DegradeRuleEntity> rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.DEGRADE_FLOW_DATA_ID_POSTFIX);
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);
       }
    }
}
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);

修改推送逻辑:

// 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 boolean publishRules(String app) {
   List<DegradeRuleEntity> rules = repository.findAllByApp(app);
   String ruleStr = JSON.toJSONString(rules);
   rulePublisher.publish(app + NacosConfigUtil.DEGRADE_FLOW_DATA_ID_POSTFIX, ruleStr);
   return true;
}
=======================================================================================

// 2、修改位置如下:有两处
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
     logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}

// 将上面代码修改为以下代码:
if (!publishRules(entity.getApp())){
     logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}
=======================================================================================

// 3、修改位置如下:
if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
   logger.warn("Publish degrade rules failed, app={}", oldEntity.getApp());
}

// 将上面代码修改为以下代码:
if (!publishRules(oldEntity.getApp())){
     logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}

4.3、热点规则

修改ParamFlowRuleController:
RuleNacosProviderRuleNacosPublisher注入到ParamFlowRuleController

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

修改读取逻辑:

// 修改位置如下:
return sentinelApiClient.fetchParamFlowRulesOfMachine(app, ip, port)
                .thenApply(repository::saveAll)
                .thenApply(Result::ofSuccess)
                .get();

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX);
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(app + NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX, ruleStr);
   } catch (Exception e) {
     e.printStackTrace();
   }
上一篇:Redis 如何实现分布式锁-单机 Redis


下一篇:【数据库】MySQL分页查询