SpringCloud整合sentinel

1.SpringCloudGateWay整合sentinel

1.网关pom文件加入 sentinel 依赖

<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<--数据持久化-->
<dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

2.bootstrap 文件添加配置


spring:
    profiles:
        active: ${DEPLOY_ENV:dev}
    aop:
        proxy-target-class: true
    application:
        name: oppc.gateway
    cloud:
        sentinel:
          #心跳启动
          eager: true
          transport:
            #sentinel控制台访问路径
            dashboard: xxxxxx:8080
            port: 8719
			<--读取nacos流控配置-->
		  datasource:
            gw-flow:
              nacos:
                server-addr: ${NACOS_ADDR:xxxxx:8848}
                dataId: ${spring.application.name}-gateway-flow
                namespace: ${NACOS_NAMESPACE:oppc}
                groupId: SENTINEL_GROUP
                #            namespace: public
                # 规则类型,取值见:
                # org.springframework.cloud.alibaba.sentinel.datasource.RuleType
                data-type: json
                rule-type: gw-flow
            gw-api-group:
              nacos:
                server-addr: ${NACOS_ADDR:xxxxx:8848}
                dataId: ${spring.application.name}-gateway-api
                groupId: SENTINEL_GROUP
                data-type: json
                rule-type: gw-api-group

3.添加网关配置类 设置限流与降级处理的回调函数

@Configuration
public class GatewayConfig {
    @PostConstruct
    public void doInit(){
        //设置限流或降级的回调函数
        GatewayCallbackManager.setBlockHandler((serverWebExchange, throwable) -> ServerResponse.status(500).syncBody("系统繁忙请稍后"));
    }

}

4.特别注意的地方是 sentinel初始化加载的逻辑中有一个服务类型的参数appType默认为 0 ,0代表是普通的服务,只有设置为1 的时候才是针对网关的。后台页面会有不同,需要在网关服务中添加 参数设置

@SpringBootApplication
@RestController
@EnableDiscoveryClient
@EnableAsync(proxyTargetClass = true)
@EnableFeignClients
public class GatewayApplication {


    public static void main(String[] args) {
        //sentinel 接入网关 设置类型为 1 不设置的话 按普通服务
        System.setProperty("csp.sentinel.app.type", "1");
        SpringApplication.run(GatewayApplication.class, args);
    }


}

2.应用服务整合sentinel

1.服务pom文件添加依赖

<!--    sentinel    -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>0.9.0.RELEASE</version>
        </dependency>
		<--数据持久化-->
		<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

2.bootstrap文件在cloud节点下添加配置

spring:
  application:
    name: xxx.user
  profiles:
    active: ${DEPLOY_ENV:dev}
  devtools:
    restart:
      enabled: true
  main:
    allow-bean-definition-overriding: true
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
  servlet:
    multipart:
      maxFileSize: 5MB  #单位必须大写MB或不写(即为B)
      maxRequestSize: 10MB
  cloud:
    sentinel:
      transport:
        dashboard: xxxxxx:8080
      eager: true
	  <--读取nacos流控配置-->
	  datasource:
        flow:
          nacos:
            server-addr: ${NACOS_ADDR:xxxxx:8848}
            dataId: ${spring.application.name}-flow-rules
            namespace: ${NACOS_NAMESPACE:oppc}
            groupId: SENTINEL_GROUP
#            namespace: public
            # 规则类型,取值见:
            # org.springframework.cloud.alibaba.sentinel.datasource.RuleType
            data-type: json
            rule-type: flow
        degrade:
          nacos:
            server-addr: ${NACOS_ADDR:xxxxx:8848}
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: degrade
        system:
          nacos:
            server-addr: ${NACOS_ADDR:xxxxx:8848}
            dataId: ${spring.application.name}-system-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: system
        authority:
          nacos:
            server-addr: ${NACOS_ADDR:xxxxx:8848}
            dataId: ${spring.application.name}-authority-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: authority
        param-flow:
          nacos:
            server-addr: ${NACOS_ADDR:xxxxx:8848}
            dataId: ${spring.application.name}-param-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: param-flow 

3.添加流控异常处理类

@Service
public class BlockHandler implements UrlBlockHandler {

    @Override
    public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
        httpServletResponse.setHeader("Content-Type","application/json;chartset=UTF-8");
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.getWriter().write(new Gson().toJson(R.error("当前访问人数过多,请稍后重试")));
    }
}

3.sentinel 源码改造实现流控规则数据持久化

sentinel流控规则通过推送与拉取模式实现与nacos同步,在sentinel控制台和nacos控制台对规则的修改都可互相同步各微服务通过配置nacos数据源,监听nacos配置的变化,拉取nacos的配置并更新到应用的内存中,具体改造步骤如下:

1.去掉SENTINEL-DASHBOARD 工程的POM中TEST

<!-- 去掉test -->
<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-datasource-nacos</artifactId>
   <!-- <scope>test</scope>-->
</dependency>

2.找到 sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos目录,将整个目录拷贝到 sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos下,如下图所示:

3.修改流控规则Controller,到com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2类的源码中找到这一段:

@Autowired
@Qualifier("flowRuleDefaultProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleDefaultPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

修改@Qualifier注解的内容,将其修改为:

@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

4.打开sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html文件,找到一段被注释的代码,如下:

<li ui-sref-active="active" ng-if="!entry.isGateway">
    <a ui-sref="dashboard.flowV1({app: entry.app})">
    <i class="glyphicon glyphicon-filter"></i>流控规则</a>
</li>

把V1去掉,即改为:

 <li ui-sref-active="active" ng-if="!entry.isGateway">
       <a ui-sref="dashboard.flow({app: entry.app})">
       <i class="glyphicon glyphicon-filter"></i>流控规则</a>
 </li>

源码中的添加接口回去调用V1接口,此接口是保存规则数据到内存中,我们要改造成调用源码中的V2接口,同步数据到nacos中

5.添加限流,降级等各个功能的拉取与推送类

代码示例:其余各功能类似

推送:

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.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * @author wanggeng
 */
@Component("degradeRuleNacosProvider")
public class DegradeRuleNacosProvider implements DynamicRuleProvider<List<DegradeRuleEntity>> {
    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<DegradeRuleEntity>> converter;

    @Override
    public List<DegradeRuleEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX,
                NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }
}

拉取:

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.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author wanggeng
 */
@Component("degradeRuleNacosPublisher")
public class DegradeRuleNacosPublisher implements DynamicRulePublisher<List<DegradeRuleEntity>> {
    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<DegradeRuleEntity>, String> converter;

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

  1. 修改nacos配置类:

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

import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
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 org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

/**
 * @author wanggeng
 */
@Configuration
public class NacosConfig {

    @Value("${nacos.addr}")
    private String nacosAddr;
    @Value("${nacos.namespace}")
    private String nacosNameSpace;
    @Value("${nacos.username}")
    private String nacosUsername;
    @Value("${nacos.password}")
    private String nacosPassword;

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

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

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

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

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

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


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

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


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

    @Bean
    public Converter<String, List<SystemRuleEntity>> systemRuleEntityDecoder() {
        return s -> JSON.parseArray(s, SystemRuleEntity.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);
    }
    /**
     * 网关flowRule
     *
     * @return
     * @throws Exception
     */
    @Bean
    public Converter<List<ApiDefinitionEntity>, String> gatewayApiRuleEntityEncoder() {
        return JSON::toJSONString;
    }

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

    @Bean
    public ConfigService nacosConfigService() throws Exception {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR,nacosAddr);
        properties.put(PropertyKeyConst.NAMESPACE,nacosNameSpace);
        properties.put(PropertyKeyConst.USERNAME,nacosUsername);
        properties.put(PropertyKeyConst.PASSWORD,nacosPassword);
        return ConfigFactory.createConfigService(properties);
    }
}

7.修改nacos配置工具类NacosConfigUtil


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

/**
 * @author wanggeng
 */
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 DEGRADE_DATA_ID_POSTFIX = "-degrade-rules";
    public static final String SYSTEM_DATA_ID_POSTFIX = "-system-rules";
    public static final String DASHBOARD_POSTFIX = "-dashboard";
    public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-flow-rules";
    public static final String AUTHORITY_DATA_ID_POSTFIX = "-authority-rules";
    public static final String GETWAY_API_DATA_ID_POSTFIX = "-getway-api";
    public static final String GETWAY_FLOW_DATA_ID_POSTFIX = "-getway-flow";


//    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() {}
}

  1. 修改V2各个Controller中的代码:不再一一列举

例如:
各controller添加:

/**
     *  推送 到 nacos
     * @param app
     * @throws Exception
     */
    private void publishApis(String app) throws Exception {
        List<ApiDefinitionEntity> rules = repository.findAllByApp(app);
        rulePublisher.publish(app,rules);
    }

具体代码如下:


package com.alibaba.csp.sentinel.dashboard.controller.gateway;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiPredicateItemEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.AddApiReqVo;
import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.ApiPredicateItemVo;
import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.UpdateApiReqVo;
import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemApiDefinitionStore;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
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.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*;

/**
 * @author wanggeng
 */
@RestController
@RequestMapping(value = "/gateway/api")
public class GatewayApiController {

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

    @Autowired
    private InMemApiDefinitionStore repository;

    @Autowired
    private SentinelApiClient sentinelApiClient;
    @Autowired
    @Qualifier("gateWayApiNacosProvider")
    private DynamicRuleProvider<List<ApiDefinitionEntity>> ruleProvider;

    @Autowired
    @Qualifier("gateWayApiNacosPublisher")
    private DynamicRulePublisher<List<ApiDefinitionEntity>> rulePublisher;
    @GetMapping("/list.json")
    @AuthAction(AuthService.PrivilegeType.READ_RULE)
    public Result<List<ApiDefinitionEntity>> queryApis(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<ApiDefinitionEntity> apis = sentinelApiClient.fetchApis(app, ip, port).get();
            List<ApiDefinitionEntity> apis = ruleProvider.getRules(app);
            repository.saveAll(apis);
            return Result.ofSuccess(apis);
        } catch (Throwable throwable) {
            logger.error("queryApis error:", throwable);
            return Result.ofThrowable(-1, throwable);
        }
    }

    @PostMapping("/new.json")
    @AuthAction(AuthService.PrivilegeType.WRITE_RULE)
    public Result<ApiDefinitionEntity> addApi(HttpServletRequest request, @RequestBody AddApiReqVo reqVo) {

        String app = reqVo.getApp();
        if (StringUtil.isBlank(app)) {
            return Result.ofFail(-1, "app can't be null or empty");
        }

        ApiDefinitionEntity entity = new ApiDefinitionEntity();
        entity.setApp(app.trim());

        String ip = reqVo.getIp();
        if (StringUtil.isBlank(ip)) {
            return Result.ofFail(-1, "ip can't be null or empty");
        }
        entity.setIp(ip.trim());

        Integer port = reqVo.getPort();
        if (port == null) {
            return Result.ofFail(-1, "port can't be null");
        }
        entity.setPort(port);

        // API名称
        String apiName = reqVo.getApiName();
        if (StringUtil.isBlank(apiName)) {
            return Result.ofFail(-1, "apiName can't be null or empty");
        }
        entity.setApiName(apiName.trim());

        // 匹配规则列表
        List<ApiPredicateItemVo> predicateItems = reqVo.getPredicateItems();
        if (CollectionUtils.isEmpty(predicateItems)) {
            return Result.ofFail(-1, "predicateItems can't empty");
        }

        List<ApiPredicateItemEntity> predicateItemEntities = new ArrayList<>();
        for (ApiPredicateItemVo predicateItem : predicateItems) {
            ApiPredicateItemEntity predicateItemEntity = new ApiPredicateItemEntity();

            // 匹配模式
            Integer matchStrategy = predicateItem.getMatchStrategy();
            if (!Arrays.asList(URL_MATCH_STRATEGY_EXACT, URL_MATCH_STRATEGY_PREFIX, URL_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
                return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
            }
            predicateItemEntity.setMatchStrategy(matchStrategy);

            // 匹配串
            String pattern = predicateItem.getPattern();
            if (StringUtil.isBlank(pattern)) {
                return Result.ofFail(-1, "pattern can't be null or empty");
            }
            predicateItemEntity.setPattern(pattern);

            predicateItemEntities.add(predicateItemEntity);
        }
        entity.setPredicateItems(new LinkedHashSet<>(predicateItemEntities));

        // 检查API名称不能重复
        List<ApiDefinitionEntity> allApis = repository.findAllByMachine(MachineInfo.of(app.trim(), ip.trim(), port));
        if (allApis.stream().map(o -> o.getApiName()).anyMatch(o -> o.equals(apiName.trim()))) {
            return Result.ofFail(-1, "apiName exists: " + apiName);
        }

        Date date = new Date();
        entity.setGmtCreate(date);
        entity.setGmtModified(date);

        try {
            entity = repository.save(entity);
        } catch (Throwable throwable) {
            logger.error("add gateway api error:", throwable);
            return Result.ofThrowable(-1, throwable);
        }
        try{
            // 修改 推送到nacos
            publishApis(entity.getApp());
        }catch (Exception e){
            logger.warn("publish gateway flow rules fail after add");
        }
		//此处为推送到应用内存中
//        if (!publishApis(app, ip, port)) {
//            logger.warn("publish gateway apis fail after add");
//        }

        return Result.ofSuccess(entity);
    }

    @PostMapping("/save.json")
    @AuthAction(AuthService.PrivilegeType.WRITE_RULE)
    public Result<ApiDefinitionEntity> updateApi(@RequestBody UpdateApiReqVo reqVo) {
        String app = reqVo.getApp();
        if (StringUtil.isBlank(app)) {
            return Result.ofFail(-1, "app can't be null or empty");
        }

        Long id = reqVo.getId();
        if (id == null) {
            return Result.ofFail(-1, "id can't be null");
        }

        ApiDefinitionEntity entity = repository.findById(id);
        if (entity == null) {
            return Result.ofFail(-1, "api does not exist, id=" + id);
        }

        // 匹配规则列表
        List<ApiPredicateItemVo> predicateItems = reqVo.getPredicateItems();
        if (CollectionUtils.isEmpty(predicateItems)) {
            return Result.ofFail(-1, "predicateItems can't empty");
        }

        List<ApiPredicateItemEntity> predicateItemEntities = new ArrayList<>();
        for (ApiPredicateItemVo predicateItem : predicateItems) {
            ApiPredicateItemEntity predicateItemEntity = new ApiPredicateItemEntity();

            // 匹配模式
            int matchStrategy = predicateItem.getMatchStrategy();
            if (!Arrays.asList(URL_MATCH_STRATEGY_EXACT, URL_MATCH_STRATEGY_PREFIX, URL_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
                return Result.ofFail(-1, "Invalid matchStrategy: " + matchStrategy);
            }
            predicateItemEntity.setMatchStrategy(matchStrategy);

            // 匹配串
            String pattern = predicateItem.getPattern();
            if (StringUtil.isBlank(pattern)) {
                return Result.ofFail(-1, "pattern can't be null or empty");
            }
            predicateItemEntity.setPattern(pattern);

            predicateItemEntities.add(predicateItemEntity);
        }
        entity.setPredicateItems(new LinkedHashSet<>(predicateItemEntities));

        Date date = new Date();
        entity.setGmtModified(date);

        try {
            entity = repository.save(entity);
        } catch (Throwable throwable) {
            logger.error("update gateway api error:", throwable);
            return Result.ofThrowable(-1, throwable);
        }
        try{
            //修改 推送到nacos
            publishApis(entity.getApp());
        }catch (Exception e){
            logger.warn("publish gateway flow rules fail after add");
        }
//        if (!publishApis(app, entity.getIp(), entity.getPort())) {
//            logger.warn("publish gateway apis fail after update");
//        }

        return Result.ofSuccess(entity);
    }

    @PostMapping("/delete.json")
    @AuthAction(AuthService.PrivilegeType.DELETE_RULE)

    public Result<Long> deleteApi(Long id) {
        if (id == null) {
            return Result.ofFail(-1, "id can't be null");
        }

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

        try {
            repository.delete(id);
        } catch (Throwable throwable) {
            logger.error("delete gateway api error:", throwable);
            return Result.ofThrowable(-1, throwable);
        }
        try{
            //推送到nacos
            publishApis(oldEntity.getApp());
        }catch (Exception e){
            logger.warn("publish gateway flow rules fail after add");
        }
//        if (!publishApis(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
//            logger.warn("publish gateway apis fail after delete");
//        }

        return Result.ofSuccess(id);
    }
    /**
     *  api 推送 到 nacos
     * @param app
     * @throws Exception
     */
    private void publishApis(String app) throws Exception {
        List<ApiDefinitionEntity> rules = repository.findAllByApp(app);
        rulePublisher.publish(app,rules);
    }
	// 此处为推送到内存中
//    private boolean publishApis(String app, String ip, Integer port) {
//        List<ApiDefinitionEntity> apis = repository.findAllByMachine(MachineInfo.of(app, ip, port));
//        return sentinelApiClient.modifyApis(app, ip, port, apis);
//    }
}

需要源码的可发邮件至314503256@qq.com

有不尽之处,欢迎大神指正,转发请标明出处,谢谢

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值