让sentinel-dashboard的流控配置持久化到nacos

 

 

让sentinel-dashboard的流控配置持久化到nacos

 

官网 git: https://github.com/alibaba/Sentinel

微服务可以将流控配置放在nacos中,但dashboard修改的规则不能持久化。

本文将dashboard中的修改同步到nacos中,dashboard监控流控仍然从微服务客户端读取。

微服务客户端重启后会从nacos中读取数据,实现持久化。

 

主要思路: dashboard修改配置的时候,将数据发布到nacos中。注意dashboard中的是xxRuleEntity,而客户端读取nacos的是xxRule.

 

master分支 目前为sentinel-1.8.0为例

下载源码,idea打开。

找到sentinel-dashboard这个项目

在该项目下的pom.xml文件中找到:

      <!-- for Nacos rule publisher sample -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <scope>test</scope>
        </dependency>

将<scope>test</scope>注释掉。

 

展开test->java->com.alibaba.csp.sentinel.dashboard->rule->nacos

复制到src->java->com.alibaba.csp.sentinel.dashboard

 

1. 主要文件

NacosCofig 服务配置 及convert

​
@Configuration
public class NacosConfig {

    @Value("${sentinel.datasource.nacos.server-addr:localhost:8848}")
    private String serverAddr;

    @Value("${sentinel.datasource.nacos.enable:false}")
    private boolean enable;

    @Bean
    public FlowRuleConvert flowRuleEntityEncoder() {
        return new FlowRuleConvert();
    }

    @Bean
    public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, FlowRuleEntity.class);
    }

    @Bean
    public ParamFlowRuleConvert paramFlowRuleEntityEncoder() {
        return new ParamFlowRuleConvert();
    }

    @Bean
    public Converter<String, List<ParamFlowRuleEntity>> paramFlowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
    }



    @Bean
    public DegradeRuleConvert degradeRuleEntityEncoder() {
        return new DegradeRuleConvert();
    }

    @Bean
    public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
        return s -> JSON.parseArray(s, DegradeRuleEntity.class);
    }

    @Bean
    public ConfigService nacosConfigService() throws Exception {
        return ConfigFactory.createConfigService(serverAddr);
    }


    public boolean isEnable() {
        return enable;
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }
}

​

默认配置 NacosConfigUtil

注意 GROUP_ID 、xx_DATA_ID_POSTFIX 需要微服务客户端的一致

public final class NacosConfigUtil {

//    public static final String GROUP_ID = "SENTINEL_GROUP";
    public static final String GROUP_ID = "DEFAULT_GROUP";

    public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";
    public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules";
    public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-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() {}
}

FlowRuleNacosPublisher 规则发布

@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private FlowRuleConvert converter;

    @Override
    public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        boolean success = configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
            NacosConfigUtil.GROUP_ID, converter.convert(rules));
        if(!success){
            throw new RuntimeException("publish to nacos fail");
        }
    }
}

 

ParamFlowRuleNacosPublisher


@Component("paramFlowRuleNacosPublisher")
public class ParamFlowRuleNacosPublisher implements DynamicRulePublisher<List<ParamFlowRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private ParamFlowRuleConvert converter;

    @Override
    public void publish(String app, List<ParamFlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        boolean success = configService.publishConfig(app + NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX,
            NacosConfigUtil.GROUP_ID, converter.convert(rules));
        if(!success){
            throw new RuntimeException("publish to nacos fail");
        }
    }
}

DegradeRuleNacosPublisher


@Component("degradeRuleNacosPublisher")
public class DegradeRuleNacosPublisher implements DynamicRulePublisher<List<DegradeRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private DegradeRuleConvert converter;

    @Override
    public void publish(String app, List<DegradeRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        boolean success = configService.publishConfig(app + NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX,
            NacosConfigUtil.GROUP_ID, converter.convert(rules));

        if(!success){
            throw new RuntimeException("publish to nacos fail");
        }
    }
}

2. 转换类

FlowRuleConvert

public class FlowRuleConvert implements Converter<List<FlowRuleEntity>, String> {

    @Override
    public String convert(List<FlowRuleEntity> flowRuleEntities) {
        if(flowRuleEntities==null){
            return null;
        }
        List<FlowRule> flowRules = new ArrayList<>();
        for (FlowRuleEntity entity : flowRuleEntities) {
            FlowRule rule = new FlowRule();
            rule.setLimitApp(entity.getLimitApp());
            rule.setResource(entity.getResource());
            if(entity.getGmtCreate()!=null){
                rule.setGrade(entity.getGrade());
            }
            if(entity.getCount()!=null){
                rule.setCount(entity.getCount());
            }
            if(entity.getStrategy()!=null){
                rule.setStrategy(entity.getStrategy());
            }
            rule.setRefResource(entity.getRefResource());
            if(entity.getControlBehavior()!=null){
                rule.setControlBehavior(entity.getControlBehavior());
            }
            if(entity.getWarmUpPeriodSec()!=null){
                rule.setWarmUpPeriodSec(entity.getWarmUpPeriodSec());
            }
            if(entity.getMaxQueueingTimeMs()!=null){
                rule.setMaxQueueingTimeMs(entity.getMaxQueueingTimeMs());
            }
            rule.setClusterMode(entity.isClusterMode());
            rule.setClusterConfig(entity.getClusterConfig());

            flowRules.add(rule);
        }
        return JSON.toJSONString(flowRules,true);
    }
}

ParamFlowRuleConvert

DegradeRuleConvert


@Autowired
private NacosConfig nacosConfig;

@Autowired
private FlowRuleNacosPublisher flowRuleNacosPublisher;

/** 修改publish **/
private CompletableFuture<Void> publishRules(String app, String ip, Integer port) throws Exception {
    List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
    if(nacosConfig.isEnable()){
        flowRuleNacosPublisher.publish(app,rules);
    }
    return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
}

ParamFlowRuleController

@Autowired
private NacosConfig nacosConfig;

@Autowired
private ParamFlowRuleNacosPublisher paramFlowRuleNacosPublisher;

private CompletableFuture<Void> publishRules(String app, String ip, Integer port) throws Exception {
    List<ParamFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
    if(nacosConfig.isEnable()){
        paramFlowRuleNacosPublisher.publish(app,rules);
    }
    return sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules);
}

DegradeController

 


@Autowired
private NacosConfig nacosConfig;

@Autowired
private DegradeRuleNacosPublisher degradeRuleNacosPublisher;

private boolean publishRules(String app, String ip, Integer port) {
    List<DegradeRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
    if(nacosConfig.isEnable()){
        try {
            degradeRuleNacosPublisher.publish(app,rules);
        } catch (Exception e) {
            logger.error("publishRules failed. ",e);
            return false;
        }
    }
    return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
}

4. 配置文件

# nacos 配置开关 默认false
sentinel.datasource.nacos.enable=true
# nacos 地址 默认 localhost:8848
sentinel.datasource.nacos.server-addr=localhost:8848

5 微服务端示例

配置文件

server:
  port: 8081
spring:
  application:
    name: sentinel-spring-cloud-nacos
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
      eager: false
      # sentinel nacos
      datasource:
        ds-flow:
          nacos:
            server-addr: 192.168.116.128:8848
            dataId: ${spring.application.name}-flow-rules
            groupId: DEFAULT_GROUP
            dataType: json
            rule-type: flow
        ds-param:
          nacos:
            server-addr: 192.168.116.128:8848
            dataId: ${spring.application.name}-param-rules
            groupId: DEFAULT_GROUP
            dataType: json
            rule-type: param-flow
        ds-degrade:
          nacos:
            server-addr: 192.168.116.128:8848
            dataId: ${spring.application.name}-degrade-rules
            groupId: DEFAULT_GROUP
            dataType: json
            rule-type: degrade

SentinelResource

@RestController
@RequestMapping("/api/sentinel")
public class SentinelDemoController {

    @SentinelResource(value = "helloSentinel",blockHandler = "blockHandler",blockHandlerClass = SentinelBlockUtil.class )
    @GetMapping("/helloSentinel")
    public Object helloSentinel(){
        return "hello sentinel. "+System.currentTimeMillis();
    }


    @SentinelResource(value = "helloSentinelParam",blockHandler = "oneParamBlockHandler",blockHandlerClass = SentinelBlockUtil.class)
    @GetMapping("/helloSentinelParam")
    public Object helloSentinelParam(String userId){
        String data = "hello helloSentinelParam. userId:"+userId+"  "+System.currentTimeMillis();
        return data;
    }
}

 

源码:https://github.com/lvzhyt/Sentinel/tree/dashboard-nacos

dashboard-nacos 分支 sentinel-dashboard

微服务客户端示例 sentinel-demo-spring-cloud-nacos

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值