Sentinel规则持久化改造(pull+push+Ahas)

Sentinel规则持久化改造(pull+push+Ahas)

每天多学一点点~
话不多说,这就开始吧…

1.前言

之前学习过阿里的sentinel组件,但是重启之后,配置的规则都消失了。于是乎上网找了点资料,自己也来对sentinel持久化改造一下,这里记录一下过程。
以sentinel 1.7.0 版本 为例

sentinel git地址

2. 官网参考

在生产环境中使用 Sentinel

在这里插入图片描述

官网上提供了三种方式。根据官网提供资料,一个个来

3. 原生模式

Dashboard的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存
优缺点:这种做法的好处是简单,无依赖;坏处是应用重启规则就会消失,仅用
于简单测试,不能用于生产环境

4. PULL 拉模式

在这里插入图片描述
首先 Sentinel 控制台通过 API 将规则推送至客户端并更新到内存中,接着注册
的写数据源会将新的规则保存到本地的文件中。使用 pull 模式的数据源时一般
不需要对 Sentinel 控制台进行改造。
这种实现方法好处是简单,不引入新的依赖,坏处是无法保证监控数据的一致性。
(定时功能周期默认3s)
seninel源码

代码改造
官网示例

  1. 通过SPI扩展机制进行扩展,写一个拉模式的实现类
    在微服务共工程 resources 目录下 新建
    在 工程下创建META-INF 下创建services目录
    文件名称是 com.alibaba.csp.sentinel.init.InitFunc
    内容 com.zjq.persistence.PullModeByFileDataSource # 指向自己的类

  2. PullModeByFileDataSource 类,实现InitFunc 接口
    这里就是和官网上的例子差不多,拿过来改一改
    这里以 流控规 为例

PullModeByFileDataSource

@Slf4j
public class PullModeByFileDataSource implements InitFunc {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
@Override
    public void init() throws Exception {
        log.info("time:{}读取配置",sdf.format(new Date()));

        try {

            //创建文件存储目录(若路径不存在就创建路径)
            RuleFileUtils.mkdirIfNotExits(PersistenceRuleConstant.storePath);

            //创建规则文件()
            RuleFileUtils.createFileIfNotExits(PersistenceRuleConstant.rulesMap);

            //  处理流控规则逻辑
            dealFlowRules();

            //  处理降级规则
            dealDegradeRules();

            //  处理系统规则
            dealSystemRules();

            // 热点参数规则
            dealParamFlowRules();

            dealAuthRules();
        }catch (Exception e) {
            log.error("错误原因:{}",e);
        }

    }

      /**
     * 方法实现说明:处理流控规则逻辑
     * @author:zjq
     * @return: void
     * @exception: FileNotFoundException
     * @date:2020/05/3013:26
     */
    private void dealFlowRules() throws FileNotFoundException {
        String ruleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.FLOW_RULE_PATH).toString();

        //创建流控规则的可读数据源
        ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource(
                ruleFilePath,RuleListParserUtils.flowRuleListParser
        );

        // 将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
        FlowRuleManager.register2Property(flowRuleRDS.getProperty());


        WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<List<FlowRule>>(
                ruleFilePath, RuleListParserUtils.flowFuleEnCoding
        );

        // 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
        // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
        WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
    }
	
。。。。。 其他 规则差不多

}

PersistenceRuleConstant Sentinel 规则持久化 常量配置类

public class PersistenceRuleConstant {

    /**
     * 存储文件路径
     */
    public static final String storePath = System.getProperty("user.home")+"\\sentinel\\rules\\";

    /**
     * 各种存储sentinel规则映射map
     */
    public static final Map rulesMap = new HashMap<String,String>();

    //流控规则文件
    public static final String FLOW_RULE_PATH = "flowRulePath";

    //降级规则文件
    public static final String DEGRAGE_RULE_PATH = "degradeRulePath";

    //授权规则文件
    public static final String AUTH_RULE_PATH = "authRulePath";

    //系统规则文件
    public static final String SYSTEM_RULE_PATH = "systemRulePath";

    //热点参数文件
    public static final String HOT_PARAM_RULE = "hotParamRulePath";

    static {
        rulesMap.put(FLOW_RULE_PATH,storePath+"flowRule.json");
        rulesMap.put(DEGRAGE_RULE_PATH,storePath+"degradeRule.json");
        rulesMap.put(SYSTEM_RULE_PATH,storePath+"systemRule.json");
        rulesMap.put(AUTH_RULE_PATH,storePath+"authRule.json");
        rulesMap.put(HOT_PARAM_RULE,storePath+"hotParamRule.json");
    }
}

RuleFileUtils sentinel 规则文件存储工具类

@Slf4j
public class RuleFileUtils {
    /**
     * 方法实现说明:若路径不存在就创建路径
     * @author:zjq
     * @param filePath:文件存储路径
     * @return: void
     * @exception: IOException
     * @date:2020/05/3016:32
     */
    public static void mkdirIfNotExits(String filePath) throws IOException {
        File file = new File(filePath);
        if(!file.exists()) {
            log.info("创建Sentinel规则目录:{}",filePath);
            file.mkdirs();
        }
    }


    /**
     * 方法实现说明:若文件不存在就创建路径
     * @author:zjq
     * @param ruleFileMap 规则存储文件
     * @return: void
     * @exception: IOException
     * @date:2020/05/3016:32
     */
    public static void createFileIfNotExits(Map<String,String> ruleFileMap) throws IOException {

        Set<String> ruleFilePathSet = ruleFileMap.keySet();

        Iterator<String> ruleFilePathIter = ruleFilePathSet.iterator();

        while (ruleFilePathIter.hasNext()) {
            String ruleFilePathKey = ruleFilePathIter.next();
            String ruleFilePath  = PersistenceRuleConstant.rulesMap.get(ruleFilePathKey).toString();
            File ruleFile = new File(ruleFilePath);
            if(ruleFile.exists()) {
                log.info("创建Sentinel 规则文件:{}",ruleFile);
                ruleFile.createNewFile();
            }
        }
    }
}

RuleListParserUtils 规则列表解析工具类

public class RuleListParserUtils {

    /**
     * 流控列表解析器
     */
    public static final Converter<String, List<FlowRule>> flowRuleListParser = new Converter<String, List<FlowRule>>() {
        @Nullable
        @Override
        public List<FlowRule> convert(String source) {
            return JSON.parseObject(source, new TypeReference<List<FlowRule>>() {});
        }
    };
    
    /**
     *  流控列表  编码器
     */
    public static final Converter<List<FlowRule>,String>  flowFuleEnCoding= new Converter<List<FlowRule>,String>() {
        @Nullable
        @Override
        public String convert(List<FlowRule> source) {
            return JSON.toJSONString(source);
        }
    };
...... 其他同理
}

这样,会在我们的 配置的路径地下生成json文件
在这里插入图片描述
json文件

[{
	"clusterConfig": {
		"fallbackToLocalWhenFail": true,
		"sampleCount": 10,
		"strategy": 0,
		"thresholdType": 0,
		"windowIntervalMs": 1000
	},
	"clusterMode": false,
	"controlBehavior": 0,
	"count": 1.0,
	"grade": 1,
	"limitApp": "default",
	"maxQueueingTimeMs": 500,
	"resource": "/selectOrderInfoById/1",
	"strategy": 0,
	"warmUpPeriodSec": 10
}]

这样,pull模式的持久化改造就完成了。
但是也如上文说的,pull 模式的自身缺点 :因为有定时任务 ,若 时间太短,服务器受不了;时间太长,有延迟

5. push 推模式

这边已nacos为例,也是官网推荐的 生产环境 使用

在这里插入图片描述
大体原理如下:

  1. 控制台推送规则:
    将规则推送到Nacos或其他远程配置中心。Sentinel客户端链接Nacos,获取规则配置;并监听Nacos配置变化,如发生变化,就更新本地缓存(从而让本地缓存总是和Nacos一致)

  2. 控制台监听Nacos配置变化,如发生变化就更新本地缓存(从而让控制台本地缓存总是和Nacos一致)

这里用sentinel1.7.0 版本为例

代码改造:

  1. 去掉 sentinel-dashboard 工程的pom中 test
    在这里插入图片描述
  2. 控制台源码改造
    DynamicRuleProvider:从Nacos上读取配置
    DynamicRulePublisher:将规则推送到Nacos上

    在sentinel-dashboard工程目录com.alibaba.csp.sentinel.dashboard.rule 下创建一个Nacos的包,
    然后把我们的各个场景的配置规则类写道该包下,如下图
    各个规则类
    在这里插入图片描述

2.1 将test下的NacosConfig 复制到 nacos包下 ,写入我们自己的nacos地址
其实源码中的 com.alibaba.csp.sentinel.dashboard.rule.nacos 目录下 已经帮我们写了示例,copy一下改一改就行。
NacosConfig

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
@Configuration
public class NacosConfig {

    /**
     * 流控规则
     * @return
     */
    @Bean
    public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, FlowRuleEntity.class);
    }

    /**
     *   授权规则
     * @return
     */
    @Bean
    public Converter<List<AuthorityRuleEntity>, String> authorRuleEntityEncoder() {
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<AuthorityRuleEntity>> authorRuleEntityDecoder() {
        return s -> JSON.parseArray(s, AuthorityRuleEntity.class);
    }

    /**
     *  降级规则
     * @return
     */
    @Bean
    public Converter<List<DegradeRuleEntity>, String> degradeRuleEntityEncoder() {
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
        return s -> JSON.parseArray(s, DegradeRuleEntity.class);
    }

    /**
     *   热点参数 规则
     * @return
     */
    @Bean
    public Converter<List<ParamFlowRuleEntity>, String> paramRuleEntityEncoder() {
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<ParamFlowRuleEntity>> paramRuleEntityDecoder() {
        return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
    }

    /**
     * 系统规则
     * @return
     */
    @Bean
    public Converter<List<SystemRuleEntity>, String> systemRuleEntityEncoder() {
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<SystemRuleEntity>> systemRuleEntityDecoder() {
        return s -> JSON.parseArray(s, SystemRuleEntity.class);
    }

    /**
     * 网关API
     * @return
     * @throws Exception
     */
    @Bean
    public Converter<List<ApiDefinitionEntity>,String> apiDefinitionEntityEncoder() {
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String , List<ApiDefinitionEntity>> apiDefinitionEntityDecoder(){
        return  s -> JSON.parseArray(s,ApiDefinitionEntity.class);
    }

    /**
     * 网关flowRule
     * @return
     * @throws Exception
     */
    @Bean
    public Converter<List<GatewayFlowRuleEntity>,String> gatewayFlowRuleEntityEncoder() {
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String , List<GatewayFlowRuleEntity>> gatewayFlowRuleEntityDecoder(){
        return  s -> JSON.parseArray(s,GatewayFlowRuleEntity.class);
    }
    @Bean
    public ConfigService nacosConfigService() throws Exception {
        return ConfigFactory.createConfigService("47.111.191.111");
    }
}

2.2 以FlowRule为例,配置Publisher和Provider
将test下的FlowRuleNacosPublisher 和 FlowRuleNacosProvider 复制到 nacos 包下

2.3 修改流控规则 FlowControllerV1

2.3.1 添加我们刚才复制来的 Publisher 和 Provider

    //添加我们自己写的ruleProvider
    @Autowired
    @Qualifier("flowRuleNacosProvider")
    private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;

    //添加我们自己写的 publisher
    @Autowired
    @Qualifier("flowRuleNacosPublisher")
    private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

2.3.2 新增推送到nacos的方法

   /**
     *  原方法
     * @param app
     * @param ip
     * @param port
     * @return
     */
    private boolean publishRules(String app, String ip, Integer port) {
        List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
        return sentinelApiClient.setFlowRuleOfMachine(app, ip, port, rules);
    }

    /**
     *  我们自己的publishRules ,将规则推送到 nacos
     * @param app
     * @throws Exception
     */
    private void publishRules(String app) throws Exception {
        List<FlowRuleEntity> rules = repository.findAllByApp(app);
        rulePublisher.publish(app,rules);
    }

2.3.4 修改FlowControllerV1
1 将原来的 List rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port); 换成从nacos中获取
2 将 保存后的会泽推送到nacos 即 publishRules(entity.getApp());

    @RestController
@RequestMapping(value = "/v1/flow")
public class FlowControllerV1 {

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

    @Autowired
    private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;
    @Autowired
    private AuthService<HttpServletRequest> authService;

    //添加我们自己写的ruleProvider
    @Autowired
    @Qualifier("flowRuleNacosProvider")
    private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;

    //添加我们自己写的 publisher
    @Autowired
    @Qualifier("flowRuleNacosPublisher")
    private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;


    @Autowired
    private SentinelApiClient sentinelApiClient;

    @GetMapping("/rules")
    public Result<List<FlowRuleEntity>> apiQueryMachineRules(HttpServletRequest request,
                                                             @RequestParam String app,
                                                             @RequestParam String ip,
                                                             @RequestParam Integer port) {
        AuthUser authUser = authService.getAuthUser(request);
        authUser.authTarget(app, PrivilegeType.READ_RULE);

        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<FlowRuleEntity> rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);
            // 去nacos上获取配置规则
            List<FlowRuleEntity> rules = ruleProvider.getRules(app);
            rules = repository.saveAll(rules);
            return Result.ofSuccess(rules);
        } catch (Throwable throwable) {
            logger.error("Error when querying flow rules", throwable);
            return Result.ofThrowable(-1, throwable);
        }
    }

    private <R> Result<R> checkEntityInternal(FlowRuleEntity entity) {
        if (StringUtil.isBlank(entity.getApp())) {
            return Result.ofFail(-1, "app can't be null or empty");
        }
        if (StringUtil.isBlank(entity.getIp())) {
            return Result.ofFail(-1, "ip can't be null or empty");
        }
        if (entity.getPort() == null) {
            return Result.ofFail(-1, "port can't be null");
        }
        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");
        }
        if (entity.getGrade() == null) {
            return Result.ofFail(-1, "grade can't be null");
        }
        if (entity.getGrade() != 0 && entity.getGrade() != 1) {
            return Result.ofFail(-1, "grade must be 0 or 1, but " + entity.getGrade() + " got");
        }
        if (entity.getCount() == null || entity.getCount() < 0) {
            return Result.ofFail(-1, "count should be at lease zero");
        }
        if (entity.getStrategy() == null) {
            return Result.ofFail(-1, "strategy can't be null");
        }
        if (entity.getStrategy() != 0 && StringUtil.isBlank(entity.getRefResource())) {
            return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
        }
        if (entity.getControlBehavior() == null) {
            return Result.ofFail(-1, "controlBehavior can't be null");
        }
        int controlBehavior = entity.getControlBehavior();
        if (controlBehavior == 1 && entity.getWarmUpPeriodSec() == null) {
            return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
        }
        if (controlBehavior == 2 && entity.getMaxQueueingTimeMs() == null) {
            return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
        }
        if (entity.isClusterMode() && entity.getClusterConfig() == null) {
            return Result.ofFail(-1, "cluster config should be valid");
        }
        return null;
    }

    @PostMapping("/rule")
    public Result<FlowRuleEntity> apiAddFlowRule(HttpServletRequest request, @RequestBody FlowRuleEntity entity) {
        AuthUser authUser = authService.getAuthUser(request);
        authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);

        Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
        if (checkResult != null) {
            return checkResult;
        }
        entity.setId(null);
        Date date = new Date();
        entity.setGmtCreate(date);
        entity.setGmtModified(date);
        entity.setLimitApp(entity.getLimitApp().trim());
        entity.setResource(entity.getResource().trim());
        try {
            entity = repository.save(entity);
            //推送规则并保存
            publishRules(entity.getApp());
        } catch (Throwable throwable) {
            logger.error("Failed to add flow rule", throwable);
            return Result.ofThrowable(-1, throwable);
        }
       if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
            logger.error("Publish flow rules failed after rule add");
        }
        return Result.ofSuccess(entity);
    }

    @PutMapping("/save.json")
    public Result<FlowRuleEntity> updateIfNotNull(HttpServletRequest request, Long id, String app,
                                                  String limitApp, String resource, Integer grade,
                                                  Double count, Integer strategy, String refResource,
                                                  Integer controlBehavior, Integer warmUpPeriodSec,
                                                  Integer maxQueueingTimeMs) {
        AuthUser authUser = authService.getAuthUser(request);
        authUser.authTarget(app, PrivilegeType.WRITE_RULE);

        if (id == null) {
            return Result.ofFail(-1, "id can't be null");
        }
        FlowRuleEntity entity = repository.findById(id);
        if (entity == null) {
            return Result.ofFail(-1, "id " + id + " dose not exist");
        }
        if (StringUtil.isNotBlank(app)) {
            entity.setApp(app.trim());
        }
        if (StringUtil.isNotBlank(limitApp)) {
            entity.setLimitApp(limitApp.trim());
        }
        if (StringUtil.isNotBlank(resource)) {
            entity.setResource(resource.trim());
        }
        if (grade != null) {
            if (grade != 0 && grade != 1) {
                return Result.ofFail(-1, "grade must be 0 or 1, but " + grade + " got");
            }
            entity.setGrade(grade);
        }
        if (count != null) {
            entity.setCount(count);
        }
        if (strategy != null) {
            if (strategy != 0 && strategy != 1 && strategy != 2) {
                return Result.ofFail(-1, "strategy must be in [0, 1, 2], but " + strategy + " got");
            }
            entity.setStrategy(strategy);
            if (strategy != 0) {
                if (StringUtil.isBlank(refResource)) {
                    return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
                }
                entity.setRefResource(refResource.trim());
            }
        }
        if (controlBehavior != null) {
            if (controlBehavior != 0 && controlBehavior != 1 && controlBehavior != 2) {
                return Result.ofFail(-1, "controlBehavior must be in [0, 1, 2], but " + controlBehavior + " got");
            }
            if (controlBehavior == 1 && warmUpPeriodSec == null) {
                return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
            }
            if (controlBehavior == 2 && maxQueueingTimeMs == null) {
                return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
            }
            entity.setControlBehavior(controlBehavior);
            if (warmUpPeriodSec != null) {
                entity.setWarmUpPeriodSec(warmUpPeriodSec);
            }
            if (maxQueueingTimeMs != null) {
                entity.setMaxQueueingTimeMs(maxQueueingTimeMs);
            }
        }
        Date date = new Date();
        entity.setGmtModified(date);
        try {
            entity = repository.save(entity);
            /**
             * 自定义推送
             */
            publishRules(entity.getApp());
            if (entity == null) {
                return Result.ofFail(-1, "save entity fail");
            }
        } catch (Throwable throwable) {
            logger.error("save error:", throwable);
            return Result.ofThrowable(-1, throwable);
        }
        if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
            logger.info("publish flow rules fail after rule update");
        }
        return Result.ofSuccess(entity);
    }

    @DeleteMapping("/delete.json")
    public Result<Long> delete(HttpServletRequest request, Long id) {
        AuthUser authUser = authService.getAuthUser(request);
        if (id == null) {
            return Result.ofFail(-1, "id can't be null");
        }
        FlowRuleEntity oldEntity = repository.findById(id);
        if (oldEntity == null) {
            return Result.ofSuccess(null);
        }
        authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
        try {
            repository.delete(id);
            //删除nacos上的配置规则
            publishRules(oldEntity.getApp());
        } catch (Exception e) {
            return Result.ofFail(-1, e.getMessage());
        }
        if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
            logger.info("publish flow rules fail after rule delete");
        }
        return Result.ofSuccess(id);
    }

    /**
     *  原方法
     * @param app
     * @param ip
     * @param port
     * @return
     */
    private boolean publishRules(String app, String ip, Integer port) {
        List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
        return sentinelApiClient.setFlowRuleOfMachine(app, ip, port, rules);
    }

    /**
     *  我们自己的publishRules ,将规则推送到 nacos
     * @param app
     * @throws Exception
     */
    private void publishRules(String app) throws Exception {
        List<FlowRuleEntity> rules = repository.findAllByApp(app);
        rulePublisher.publish(app,rules);
    }
}

其他规则 同理。

2.4 微服务工程改造
2.4.1 增加 sentinel与nacos整合后的依赖

<!-- sentilen用 nacos 做 持久化-->
<dependency>
   <groupId>com.alibaba.csp</groupId>
   <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

2.4.2 yml配置

spring:
  datasource:
      druid:
        ......   # 省略db配置
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:9999
        #namespace: bc7613d2-2e22-4292-a748-48b78170f14c  #指定namespace的id
      datasource:
        # 名称随意
        flow:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-flow-rules  # 都是在 sentinel源码持久化改造中的规则名称
            groupId: SENTINEL_GROUP
            rule-type: flow
        degrade:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-degrade-rules # 都是在 sentinel源码持久化改造中的规则名称
            groupId: SENTINEL_GROUP
            rule-type: degrade
        system:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-system-rules # 都是在 sentinel源码持久化改造中的规则名称
            groupId: SENTINEL_GROUP
            rule-type: system
        authority:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-authority-rules # 都是在 sentinel源码持久化改造中的规则名称
            groupId: SENTINEL_GROUP
            rule-type: authority
        param-flow:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-param-flow-rules # 都是在 sentinel源码持久化改造中的规则名称
            groupId: SENTINEL_GROUP
            rule-type: param-flow

  application:
    name: order-center
server:
  port: 8080

#是否开启@SentinelRestTemplate注解
resttemplate:
  sentinel:
    enabled: true
management:
  endpoints:
    web:
      exposure:
        include: '*'

这样到此为止就改造好了
这样无论是重启 nacos也好,sentinel也罢,业务工程也罢,都会实例化~

在这里插入图片描述

6. 阿里云Ahas

能用钱解决的事,都不是事情~
ahas开通地址

阿里云ahas文档

在这里插入图片描述
选择sdk接入—>springboot接入
在这里插入图片描述
在这里插入图片描述
随便起一个工程,接入ahas,访问接口
在这里插入图片描述

跟sentinel一样的操作
在这里插入图片描述

7.结语

世上无难事,只怕有心人,每天积累一点点,fighting!!!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值