Sentinel同步流控规则到Nacos(Apollo、zookeeper同理)

1.必看!!!(右边有目录导航)

  • 已集成Nacos、Sentinel并且Sentinel dashboard可正常显示Nacos持久化的流控规则
    Sentinel
  • 下载sentinel源码:https://github.com/alibaba/Sentinel/archive/refs/tags/1.8.3.zip
  • sentinel-dashboard工程添加lombok依赖、修改Nacos scope
  • 新建或修改package、class、enum不再赘婿,详见class和enum的package路径!!
  • 已确认无误,复制粘贴当伸手党即可。
<!-- for Nacos rule publisher sample -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <!--<scope>test</scope>-->
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <!--请自行在父pom中管理依赖-->
    <version>1.18.16</version>
</dependency>

2.项目目录(下述代码全部在sentinel-dashboard工程)

项目目录

3.修改文件:sidebar.html

  • 文件目录:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LfzAjtP9-1645099256107)(img_3.png)]

  • 替换内容:

        <!--启用Sentinel同步Nacos,2022年2月17日 14点11分-->
        <!--<li ui-sref-active="active" ng-if="!entry.isGateway">
            <a ui-sref="dashboard.flowV1({app: entry.app})">
            <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>
        </li>-->
    
        <li ui-sref-active="active" ng-if="!entry.isGateway">
            <a ui-sref="dashboard.flow({app: entry.app})">
                <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;服务流控规则
            </a>
        </li>
    
  • 修改identity.js为(目的:簇点链路添加流控规则调用API改为V2)
    在这里插入图片描述

  • 产生影响:

    将流控规则时保存调用的API由V1改为V2(/v2/flow/rules)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dlU6xk8t-1645099256111)(img_4.png)]

4. 新增配置

在这里插入图片描述

#在resources/application.properties中添加Sentinel -> Nacos的连接信息
#Nacos -> Sentinel:Nacos -> 服务 -> Sentinel dashboard
sentinel.nacos.serverAddr=192.168.1.135:8847
sentinel.nacos.groupId=SENTINEL_GROUP
sentinel.nacos.namespace=95c0ce18-50e0-4e1b-917e-6429d0c54c5e
#dataId未使用
sentinel.nacos.dataId= 

5. 添加/修改同步代码(有问题看标题1)

  • 添加完后目录:

在这里插入图片描述

  • 实现思路借鉴test/com.alibaba.csp.sentinel.dashboard.rule.nacos

在这里插入图片描述

5.2 NacosPropertiesConfiguration

package com.alibaba.csp.sentinel.dashboard.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix="sentinel.nacos")
public class NacosPropertiesConfiguration{
    private String serverAddr;
    private String groupId = "DEFAULT_GROUP";
    private String namespace;
    private String dataId;
}

5.3 NacosPropertiesConfiguration

package com.alibaba.csp.sentinel.dashboard.config;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum RuleTypeEnum {
    FLOW("-flow-rules"),
    DEGRADE("-degrade-rules"),
    SYSTEM("-system-rules"),
    AUTHORITY("-authority-rules"),
    PARAM_FLOW("-param-flow-rules");

    private String ruleTypePostfix;
}

5.1 nacos包

  • flow/degrade,system/authority/param-flow参考degrade实现
  • NacosConfig
package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.config.NacosPropertiesConfiguration;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.*;
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 com.alibaba.nacos.api.exception.NacosException;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.Properties;

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
@EnableConfigurationProperties(NacosPropertiesConfiguration.class)
@Configuration
public class NacosConfig {

    @Bean
    public Converter<List<FlowRuleEntity>,String> flowRuleEntityEncoder(){
        return JSON::toJSONString;
    }

    @Bean
    public Converter<String,List<FlowRuleEntity>> flowRuleDecoder(){
        return s->JSON.parseArray(s,FlowRuleEntity.class);
    }
    @Bean
    public Converter<String,List<DegradeRuleEntity>> degradeRuleDecoder(){
        return s->JSON.parseArray(s,DegradeRuleEntity.class);
    }
    @Bean
    public Converter<String,List<SystemRuleEntity>> systemRuleDecoder(){
        return s->JSON.parseArray(s,SystemRuleEntity.class);
    }
    @Bean
    public Converter<String,List<AuthorityRuleEntity>> authorityRuleDecoder(){
        return s->JSON.parseArray(s,AuthorityRuleEntity.class);
    }
    @Bean
    public Converter<String,List<ParamFlowRuleEntity>> paramFlowRuleDecoder(){
        return s->JSON.parseArray(s,ParamFlowRuleEntity.class);
    }
    @Bean
    public ConfigService nacosConfigService(NacosPropertiesConfiguration nacosPropertiesConfiguration) throws NacosException {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.NAMESPACE,nacosPropertiesConfiguration.getNamespace());
        properties.put(PropertyKeyConst.SERVER_ADDR,nacosPropertiesConfiguration.getServerAddr());
        return ConfigFactory.createConfigService(properties);
    }
}
  • NacosRuleApiProvider
package com.alibaba.csp.sentinel.dashboard.rule.nacos;

public interface NacosRuleApiProvider<T>  {
    T getRules(String app) throws Exception;
}

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

public interface NacosRuleApiPublisher<T>  {
    void publish(String app, T rules) throws Exception;
}

  • DegradeRuleNacosApiProvider
package com.alibaba.csp.sentinel.dashboard.rule.nacos.degrade;

import com.alibaba.csp.sentinel.dashboard.config.NacosPropertiesConfiguration;
import com.alibaba.csp.sentinel.dashboard.config.RuleTypeEnum;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosRuleApiProvider;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.nacos.api.config.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component("degradeProvider")
public class DegradeRuleNacosApiProvider implements NacosRuleApiProvider<List<DegradeRuleEntity>> {
    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<DegradeRuleEntity>> converter;
    @Autowired
    private NacosPropertiesConfiguration nacosPropertiesConfiguration;

    @Override
    public List<DegradeRuleEntity> getRules(String app) throws Exception {
        String dataId = new StringBuilder(app).append(RuleTypeEnum.DEGRADE.getRuleTypePostfix()).toString();
        String rules = configService.getConfig(dataId, nacosPropertiesConfiguration.getGroupId(), 3000);
        log.info("从Nacos配置中心获取{}规则:{}", RuleTypeEnum.DEGRADE.name(), rules);
        if (StringUtils.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }


}

  • DegradeRuleNacosPublisher
/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.degrade;

import com.alibaba.csp.sentinel.dashboard.config.NacosPropertiesConfiguration;
import com.alibaba.csp.sentinel.dashboard.config.RuleTypeEnum;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosRuleApiPublisher;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
@Slf4j
@Component("degradePublisher")
public class DegradeRuleNacosPublisher implements NacosRuleApiPublisher<List<FlowRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<FlowRuleEntity>, String> converter;
    @Autowired
    private NacosPropertiesConfiguration nacosPropertiesConfiguration;

    @Override
    public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "appName 不能为空");
        if (rules == null) {
            return;
        }
        String dataId = new StringBuilder(app).append(RuleTypeEnum.DEGRADE.getRuleTypePostfix()).toString();
        configService.publishConfig(dataId, nacosPropertiesConfiguration.getGroupId(), converter.convert(rules));
        log.info("推送{}到Nacos配置中心,DataId:{},规则:{}", RuleTypeEnum.DEGRADE.name(), dataId, rules);
    }
}
  • FlowRuleNacosApiProvider
package com.alibaba.csp.sentinel.dashboard.rule.nacos.flow;

import com.alibaba.csp.sentinel.dashboard.config.NacosPropertiesConfiguration;
import com.alibaba.csp.sentinel.dashboard.config.RuleTypeEnum;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosRuleApiProvider;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.nacos.api.config.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component("flowProvider")
public class FlowRuleNacosApiProvider implements NacosRuleApiProvider<List<FlowRuleEntity>> {
    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<FlowRuleEntity>> converter;
    @Autowired
    private NacosPropertiesConfiguration nacosPropertiesConfiguration;

    @Override
    public List<FlowRuleEntity> getRules(String app) throws Exception {
        String dataId = new StringBuilder(app).append(RuleTypeEnum.FLOW.getRuleTypePostfix()).toString();
        String rules = configService.getConfig(dataId, nacosPropertiesConfiguration.getGroupId(), 3000);
        log.info("从Nacos配置中心获取{}规则:{}", RuleTypeEnum.FLOW.name(), rules);
        if (StringUtils.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }


}

  • FlowRuleNacosPublisher
/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.flow;

import com.alibaba.csp.sentinel.dashboard.config.NacosPropertiesConfiguration;
import com.alibaba.csp.sentinel.dashboard.config.RuleTypeEnum;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosRuleApiPublisher;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
@Slf4j
@Component("flowPublisher")
public class FlowRuleNacosPublisher implements NacosRuleApiPublisher<List<FlowRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<FlowRuleEntity>, String> converter;
    @Autowired
    private NacosPropertiesConfiguration nacosPropertiesConfiguration;

    @Override
    public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "appName 不能为空");
        if (rules == null) {
            return;
        }
        String dataId = new StringBuilder(app).append(RuleTypeEnum.FLOW.getRuleTypePostfix()).toString();
        configService.publishConfig(dataId, nacosPropertiesConfiguration.getGroupId(), converter.convert(rules));
        log.info("推送{}到Nacos配置中心,DataId:{},规则:{}", RuleTypeEnum.FLOW.name(), dataId, rules);
    }
}

5.4 FlowControllerV2

//改动:指定依赖注入类型
@Autowired
@Qualifier("flowProvider")
private NacosRuleApiProvider<List<FlowRuleEntity>> ruleProvider;

@Autowired
@Qualifier("flowPublisher")
private NacosRuleApiPublisher<List<FlowRuleEntity>> rulePublisher;

5.5 DegradeController

在这里插入图片描述

/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.csp.sentinel.dashboard.controller;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosRuleApiPublisher;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
import com.alibaba.csp.sentinel.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

/**
 * Controller regarding APIs of degrade rules. Refactored since 1.8.0.
 *
 * @author Carpenter Lee
 * @author Eric Zhao
 */
@RestController
@RequestMapping("/degrade")
public class DegradeController {

    private final Logger logger = LoggerFactory.getLogger(DegradeController.class);

    @Autowired
    private RuleRepository<DegradeRuleEntity, Long> repository;
    @Autowired
    private SentinelApiClient sentinelApiClient;
    @Autowired
    @Qualifier("degradePublisher")
    NacosRuleApiPublisher publisher;

    @GetMapping("/rules.json")
    @AuthAction(PrivilegeType.READ_RULE)
    public Result<List<DegradeRuleEntity>> apiQueryMachineRules(String app, String ip, Integer port) {
        if (StringUtil.isEmpty(app)) {
            return Result.ofFail(-1, "app can't be null or empty");
        }
        if (StringUtil.isEmpty(ip)) {
            return Result.ofFail(-1, "ip can't be null or empty");
        }
        if (port == null) {
            return Result.ofFail(-1, "port can't be null");
        }
        try {
            List<DegradeRuleEntity> rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);
            rules = repository.saveAll(rules);
            return Result.ofSuccess(rules);
        } catch (Throwable throwable) {
            logger.error("queryApps error:", throwable);
            return Result.ofThrowable(-1, throwable);
        }

    }

    @PostMapping("/rule")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entity) {
        Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
        if (checkResult != null) {
            return checkResult;
        }
        Date date = new Date();
        entity.setGmtCreate(date);
        entity.setGmtModified(date);
        try {
            entity = repository.save(entity);
            publishRules(entity.getApp());
        } catch (Throwable t) {
            logger.error("Failed to add new degrade rule, app={}, ip={}", entity.getApp(), entity.getIp(), t);
            return Result.ofThrowable(-1, t);
        }
        if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
            logger.warn("Publish degrade rules failed, app={}", entity.getApp());
        }
        return Result.ofSuccess(entity);
    }

    @PutMapping("/rule/{id}")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result<DegradeRuleEntity> apiUpdateRule(@PathVariable("id") Long id,
                                                   @RequestBody DegradeRuleEntity entity) {
        if (id == null || id <= 0) {
            return Result.ofFail(-1, "id can't be null or negative");
        }
        DegradeRuleEntity oldEntity = repository.findById(id);
        if (oldEntity == null) {
            return Result.ofFail(-1, "Degrade rule does not exist, id=" + id);
        }
        entity.setApp(oldEntity.getApp());
        entity.setIp(oldEntity.getIp());
        entity.setPort(oldEntity.getPort());
        entity.setId(oldEntity.getId());
        Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
        if (checkResult != null) {
            return checkResult;
        }

        entity.setGmtCreate(oldEntity.getGmtCreate());
        entity.setGmtModified(new Date());
        try {
            entity = repository.save(entity);
            publishRules(entity.getApp());
        } catch (Throwable t) {
            logger.error("Failed to save degrade rule, id={}, rule={}", id, entity, t);
            return Result.ofThrowable(-1, t);
        }
        if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
            logger.warn("Publish degrade rules failed, app={}", entity.getApp());
        }
        return Result.ofSuccess(entity);
    }

    @DeleteMapping("/rule/{id}")
    @AuthAction(PrivilegeType.DELETE_RULE)
    public Result<Long> delete(@PathVariable("id") Long id) {
        if (id == null) {
            return Result.ofFail(-1, "id can't be null");
        }

        DegradeRuleEntity oldEntity = repository.findById(id);
        if (oldEntity == null) {
            return Result.ofSuccess(null);
        }

        try {
            repository.delete(id);
            publishRules(oldEntity.getApp());
        } catch (Throwable throwable) {
            logger.error("Failed to delete degrade rule, id={}", id, throwable);
            return Result.ofThrowable(-1, throwable);
        }
        if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
            logger.warn("Publish degrade rules failed, app={}", oldEntity.getApp());
        }
        return Result.ofSuccess(id);
    }

    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 <R> Result<R> checkEntityInternal(DegradeRuleEntity entity) {
        if (StringUtil.isBlank(entity.getApp())) {
            return Result.ofFail(-1, "app can't be blank");
        }
        if (StringUtil.isBlank(entity.getIp())) {
            return Result.ofFail(-1, "ip can't be null or empty");
        }
        if (entity.getPort() == null || entity.getPort() <= 0) {
            return Result.ofFail(-1, "invalid port: " + entity.getPort());
        }
        if (StringUtil.isBlank(entity.getLimitApp())) {
            return Result.ofFail(-1, "limitApp can't be null or empty");
        }
        if (StringUtil.isBlank(entity.getResource())) {
            return Result.ofFail(-1, "resource can't be null or empty");
        }
        Double threshold = entity.getCount();
        if (threshold == null || threshold < 0) {
            return Result.ofFail(-1, "invalid threshold: " + threshold);
        }
        Integer recoveryTimeoutSec = entity.getTimeWindow();
        if (recoveryTimeoutSec == null || recoveryTimeoutSec <= 0) {
            return Result.ofFail(-1, "recoveryTimeout should be positive");
        }
        Integer strategy = entity.getGrade();
        if (strategy == null) {
            return Result.ofFail(-1, "circuit breaker strategy cannot be null");
        }
        if (strategy < CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType()
                || strategy > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
            return Result.ofFail(-1, "Invalid circuit breaker strategy: " + strategy);
        }
        if (entity.getMinRequestAmount() == null || entity.getMinRequestAmount() <= 0) {
            return Result.ofFail(-1, "Invalid minRequestAmount");
        }
        if (entity.getStatIntervalMs() == null || entity.getStatIntervalMs() <= 0) {
            return Result.ofFail(-1, "Invalid statInterval");
        }
        if (strategy == RuleConstant.DEGRADE_GRADE_RT) {
            Double slowRatio = entity.getSlowRatioThreshold();
            if (slowRatio == null) {
                return Result.ofFail(-1, "SlowRatioThreshold is required for slow request ratio strategy");
            } else if (slowRatio < 0 || slowRatio > 1) {
                return Result.ofFail(-1, "SlowRatioThreshold should be in range: [0.0, 1.0]");
            }
        } else if (strategy == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
            if (threshold > 1) {
                return Result.ofFail(-1, "Ratio threshold should be in range: [0.0, 1.0]");
            }
        }
        return null;
    }

    private void publishRules(/*@NonNull*/ String app) throws Exception {
        List<DegradeRuleEntity> rules = repository.findAllByApp(app);
        publisher.publish(app, rules);
    }
}

6. 构建启动DashboardApplication

7.效果展示

  • 同步前:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 同步后(服务本地配置与控制面板、Nacos配置):

    • 控制面板
      在这里插入图片描述
    • 服务本地在这里插入图片描述
    • Nacos持久化
      在这里插入图片描述
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值