SpringCloud Alibaba 改造Sentinel Dashboard將熔斷規則持久化到Nacos


Sentinel Dashboard集成Nacos目錄:

SpringCloud Alibaba 改造Sentinel Dashboard將流控規則持久化到Nacos

SpringCloud Alibaba 改造Sentinel Dashboard將熔斷規則持久化到Nacos  本文

 

《SpringCloud Alibaba 改造Sentinel Dashboard將流控規則持久化到Nacos》介紹了如何修改Sentinel Dashboard的源代碼,使得通過Sentinel Dashboard維護的流控規則自動持久化到Nacos上,應用程序通過訂閱Nacos上的配置實現流量控制。

本文接着介紹如何修改源碼實現熔斷規則的持久化。

二. Sentinel Dashboard集成Nacos實現熔斷規則持久化

同前文介紹的集成Nacos實現流控規則持久化類似,為了實現熔斷規則持久化,其大致實現步驟仍然是:

  1. 創建新的實現類,實現DynamicRuleProvider接口和DynamicRulePublisher接口。
  2. 修改對應的Controller,注入新的實現類。

2.1 准備工作

為了減少代碼,更加規范寫法,統一流控規則和熔斷規則的持久化的寫法,首先對之前流控規則的代碼予以部分修改,新的包結構如下:

 

 

 

以下是代碼明細:

NacosConfiguration.java

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

import java.util.Properties;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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;

/**
 * Nacos配置類
 * @author gang.wang
 * 2021年10月31日
 */
@EnableConfigurationProperties(NacosPropertiesConfiguration.class)
@Configuration
public class NacosConfiguration {
    
    @Bean
    public ConfigService nacosConfigService(NacosPropertiesConfiguration nacosPropertiesConfiguration) throws NacosException {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, nacosPropertiesConfiguration.getServerAddr());
        properties.put(PropertyKeyConst.NAMESPACE, nacosPropertiesConfiguration.getNamespace());
        return ConfigFactory.createConfigService(properties);
    }
}

 

NacosConstants.java

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

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;

import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;

/**
 * Nacos常量類
 * @author gang.wang
 * 2021年11月8日
 */
public class NacosConstants {
    
    private static Logger logger = LoggerFactory.getLogger(NacosConstants.class);
    
    public static final String GROUP_ID = "DEFAULT_GROUP";
    
    /**
     * 流控規則后綴
     */
    public static final String FLOW_DATA_ID_POSTFIX = "-sentinel-flow";
    
    /**
     * 熔斷規則后綴
     */
    public static final String DEGRADE_DATA_ID_POSTFIX = "-sentinel-degrade";
    
    /**
     * 從Nacos server中查詢響應規則,並將其反序列化成對應Rule實體
     *
     * @param configService nacos config service
     * @param groupId       組ID
     * @param dataId        Nacos DataId
     * @param clazz         類
     * @param <T>           泛型
     * @return 規則對象列表
     * @throws NacosException 異常
     */
    public static <T> List<T> getRuleEntitiesFromNacos(ConfigService configService, 
            String groupId, String dataId, Class<T> clazz) throws NacosException {
        String rules = configService.getConfig(dataId, groupId, 3000);
        
        logger.info("Pull Rule from Nacos Config : {}", rules);
        
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return JSON.parseArray(rules, clazz);
    }
    
    /**
     * 將規則序列化成為JSON信息,並發布到Nacos上
     * @param <T>
     * @param configService
     * @param groupId
     * @param dataId
     * @param ruleEntities
     * @return
     * @throws NacosException
     */
    @Bean
    public static <T> Boolean setRuleEntitiesFromNacos(ConfigService configService, 
            String groupId, String dataId, List<T> ruleEntities) throws NacosException {
        String ruleEntitiesStr = JSON.toJSONString(ruleEntities);
        logger.info("Push Rule to Nacos Config : {}", ruleEntitiesStr);
        
        return configService.publishConfig(dataId, groupId, ruleEntitiesStr);
    }
    
}

 

NacosPropertiesConfiguration.java的內容依然保持不變:

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

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 加載Nacos配置
 * @author gang.wang
 * 2021年10月31日
 */
@ConfigurationProperties(prefix="sentinel.nacos")
public class NacosPropertiesConfiguration {
    
    /**
     * Nacos服務地址
     */
    private String serverAddr;
    
    private String dataId;
    
    private String groupId = "DEFAULT_GROUP";
    
    private String namespace;

    public String getServerAddr() {
        return serverAddr;
    }

    public void setServerAddr(String serverAddr) {
        this.serverAddr = serverAddr;
    }

    public String getDataId() {
        return dataId;
    }

    public void setDataId(String dataId) {
        this.dataId = dataId;
    }

    public String getGroupId() {
        return groupId;
    }

    public void setGroupId(String groupId) {
        this.groupId = groupId;
    }

    public String getNamespace() {
        return namespace;
    }

    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }
    
}

 

FlowRuleNacosProvider.java

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

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConstants;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosPropertiesConfiguration;
import com.alibaba.nacos.api.config.ConfigService;

/**
 * 實現從Nacos配置中心獲取流控規則
 * @author gang.wang
 * 2021年11月8日
 */
@Service
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {
    
    @Autowired
    private NacosPropertiesConfiguration nacosConfigProperties;
    
    @Autowired
    private ConfigService configService;
    
    @Override
    public List<FlowRuleEntity> getRules(String appName) throws Exception {
        
        //定義dataId 應用名+固定后綴
        String dataId = new StringBuilder(appName).append(NacosConstants.FLOW_DATA_ID_POSTFIX).toString();
        
        List<FlowRuleEntity> list = NacosConstants.getRuleEntitiesFromNacos(configService, nacosConfigProperties.getGroupId(), dataId, FlowRuleEntity.class);
        
        return list;
    }
}

 

FlowRuleNacosPublisher.java

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

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConstants;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosPropertiesConfiguration;
import com.alibaba.nacos.api.config.ConfigService;

/**
 * 將通過Sentinel Dashboard上維護的流控規則數據持久化到Nacos中
 * @author gang.wang
 * 2021年11月8日
 */
@Service
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
    
    private static Logger logger = LoggerFactory.getLogger(FlowRuleNacosPublisher.class);
    
    @Autowired
    private NacosPropertiesConfiguration nacosConfigProperties;
    
    @Autowired
    private ConfigService configService;
    
    @Override
    public void publish(String appName, List<FlowRuleEntity> rules) throws Exception {
        
        if(StringUtils.isBlank(appName)) {
            logger.error("傳入的AppName為Null");
            return ;
        }
        
        if(null == rules) {
            logger.error("傳入的流控規則數據為null");
            return ;
        }
        
        String dataId = new StringBuilder(appName).append(NacosConstants.FLOW_DATA_ID_POSTFIX).toString();
        
        NacosConstants.setRuleEntitiesFromNacos(configService, nacosConfigProperties.getGroupId(), dataId, rules);
    }
}

 

2.2 熔斷規則持久化部分代碼

2.2.1 分別創建類實現DynamicRuleProvider接口和DynamicRulePublisher接口

實現熔斷規則持久化的代碼和之前流控規則的類似,都需要創建兩個類分別實現DynamicRuleProvider接口和DynamicRulePublisher接口,只不過接口的泛型不同,熔斷規則的為:List<FlowRuleEntity>

在com.alibaba.csp.sentinel.dashboard.rule.nacos包下創建degrade包。創建類:DegradeRuleNacosProvider.java和DegradeRuleNacosPublisher.java,分別實現<從Nacos拉取規則並展示在Dashboard上>和<將通過Dashboard維護的熔斷規則持久化到Nacos上>這兩個功能。

二者代碼實現也同流控規則中的代碼類似。

DegradeRuleNacosProvider.java

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

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConstants;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosPropertiesConfiguration;
import com.alibaba.nacos.api.config.ConfigService;

/**
 * 實現從Nacos配置中心獲取熔斷規則
 * @author gang.wang
 * 2021年11月15日
 */
@Service
public class DegradeRuleNacosProvider implements DynamicRuleProvider<List<DegradeRuleEntity>> {
    
    @Autowired
    private NacosPropertiesConfiguration nacosConfigProperties;
    
    @Autowired
    private ConfigService configService;
    
    @Override
    public List<DegradeRuleEntity> getRules(String appName) throws Exception {
        
        //定義dataId 應用名+固定后綴
        String dataId = new StringBuilder(appName).append(NacosConstants.DEGRADE_DATA_ID_POSTFIX).toString();
        
        List<DegradeRuleEntity> list = NacosConstants.getRuleEntitiesFromNacos(configService, nacosConfigProperties.getGroupId(), dataId, DegradeRuleEntity.class);
        
        return list;
    }
}

 

DegradeRuleNacosPublisher.java

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

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConstants;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosPropertiesConfiguration;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.flow.FlowRuleNacosPublisher;
import com.alibaba.nacos.api.config.ConfigService;

/**
 * 實現將熔斷規則持久化到Nacos中
 * @author gang.wang
 * 2021年11月15日
 */
@Service
public class DegradeRuleNacosPublisher implements DynamicRulePublisher<List<DegradeRuleEntity>> {

private static Logger logger = LoggerFactory.getLogger(FlowRuleNacosPublisher.class);
    
    @Autowired
    private NacosPropertiesConfiguration nacosConfigProperties;
    
    @Autowired
    private ConfigService configService;
    
    @Override
    public void publish(String appName, List<DegradeRuleEntity> rules) throws Exception {
        
        if(StringUtils.isBlank(appName)) {
            logger.error("傳入的AppName為Null");
            return ;
        }
        
        if(null == rules) {
            logger.error("傳入的熔斷規則數據為null");
            return ;
        }
        
        String dataId = new StringBuilder(appName).append(NacosConstants.DEGRADE_DATA_ID_POSTFIX).toString();
        
        NacosConstants.setRuleEntitiesFromNacos(configService, nacosConfigProperties.getGroupId(), dataId, rules);
    }

}

 

2.2.2 修改com.alibaba.csp.sentinel.dashboard.controller.DegradeController,注入新的實現類

此Controller中只需要修改兩個方法即可,分別是:

  1. com.alibaba.csp.sentinel.dashboard.controller.DegradeController.apiQueryMachineRules(String, String, Integer)
  2. com.alibaba.csp.sentinel.dashboard.controller.DegradeController.publishRules(String, String, Integer)

修改后的代碼如下:

/*
 * 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 java.util.Date;
import java.util.List;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
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 com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.domain.Result;

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.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 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);

    /**
     * 將規則加載到Sentinel Dashboard的內存中
     */
    @Autowired
    private RuleRepository<DegradeRuleEntity, Long> repository;
    
    @Autowired
    @Qualifier("degradeRuleNacosProvider")
    private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider;
    @Autowired
    @Qualifier("degradeRuleNacosPublisher")
    private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher;
    
    @Autowired
    private SentinelApiClient sentinelApiClient;

    @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);
            //修改為從Nacos中加載熔斷規則
            List<DegradeRuleEntity> rules = ruleProvider.getRules(app);
            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);
        } 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);
        } 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);
        } 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);
        try {
            rulePublisher.publish(app, rules);
            return true;
        } catch(Exception ex) {
            logger.error("Publish degrade rules failed", ex);
            return false;
        }
    }

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

 

 

2.3 測試通過Sentinel Dashboard維護的熔斷規則是否可以持久化到Nacos中

訪問Sentinel Dashboard,維護一條熔斷規則,示例如下:

為了后面驗證簡單,這里我們定義的熔斷規則的含義是:此接口在1000ms內當至少有3次訪問,並至少有2次異常,則此接口熔斷10秒。

 

刷新列表可以看到剛剛維護的信息:

 

 

 訪問Nacos,查看是否正常存儲:

 

 

 

 

 

 由上可見,通過Sentinel Dashboard維護的熔斷規則已經正常持久化到Nacos中了。

 

2.4 應用程序接入

應用程序需要訂閱Nacos上的對應DataId,當熔斷規則有變化時,Nacos會自動推送到已經接入的應用程序上。其具體接入的方式同之前介紹的流控規則類似。

首先在application.yml中添加對應的配置。application.yml中與Sentinel相關的配置如下:

spring:
    sentinel:
      transport: 
        dashboard: 127.0.0.1:8080
      datasource: 
        flow: 
          nacos: 
            server-addr: 127.0.0.1:8848
            namespace: 37c7c263-bdf1-41db-9f34-bf10948be752
            data-id: ${spring.application.name}-sentinel-flow
            group-id: DEFAULT_GROUP
            data-type: json
            rule-type: flow
        degrade: 
          nacos: 
            server-addr: 127.0.0.1:8848
            namespace: 37c7c263-bdf1-41db-9f34-bf10948be752
            data-id: ${spring.application.name}-sentinel-degrade
            group-id: DEFAULT_GROUP
            data-type: json
            rule-type: degrade

 

為了配合上面定義的基於異常數的熔斷規則,我們修改之前定義的接口,拋出任意異常即可。

@SentinelResource(value = "hello", blockHandler = "blockHandlerHello")
@GetMapping("/say")
public String hello() {
    int a = 10;
    int b = 0;
    int c = a / b;
    return "hello, Gary!";
}

 

啟動應用程序,並利用Postman並發訪問剛剛我們定義了熔斷規則的接口。

 

 

可以看到前兩次接口訪問報500錯誤,從第三次開始http code就開始等於200,responseBody的值為當前請求已被限流。所以可見我們定義的熔斷規則生效了。

 

至此熔斷規則持久化到Nacos的功能就已完成了!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM