Usage of SpringCloud Alibaba Sentinel and Persistence of Current Limiting Rules

Table of contents

1. Overview of SpringCloud Alibaba Sentinel and the construction of the console

1. Overview of Spring Cloud Alibaba Sentinel

2. Construction of Sentinel console

2.1. Download address

2.2, start sentinel

2.3, visit sentinel

3. What capabilities does the SpringCloud Alibaba Sentinel console have?

2. The current limiting function of sentinel is used in the project 

1. Add dependencies

2. yml configuration (under spring:cloud)

3. Write the current limiting controller interface

4. Write custom general current limiting processing logic

3. Use sentinel to protect calls between RestTemplate services

1, placement RestTemplate 

1.1, yml configuration file configuration

1.2, code configuration

2. Configure the processing method after the service is abnormally degraded and the processing method after the current limit

3. Use Sentinel to protect calls between RestTemplate services

4. Use sentinel to support fegin fuse downgrade

1. Configure fegin

2. Write fegin client 

3. Write Sentinel's downgrade strategy for OpenFeign interface

4. Write a controller test using fegin's fusing downgrade

5. Use sentinel to support RestTemplate fuse downgrade 

1. Write the strategy after the service fuse and downgrade (the method in the fallback in the controller and the method parameters in the class must be consistent)

2. Write a controller test to use RestTemplate's fuse degradation

5. Sentinel combines Nacos to realize the persistence of current limiting rules

1. Spring Cloud Alibaba Sentinel configuration information

2. Integrate nacos to realize the persistence of current limiting rules

2.1. Add dependencies

2.2. Writing a current-limiting interface

2.3, yml configuration (under spring:cloud)

2.4. Write the configuration of the specified current-limiting interface on nacos

6. Gateway integrates Sentinel to realize gateway current limiting

1. Introduce dependencies

2. Write the configuration file (under spring:cloud)

3. Hard-coded way to achieve

4. Local file implementation

4.1. Writing routing rules

4.2, write routing rule grouping 

4.3. Writing configuration files

5. Nacos implementation

5.1. Write routing rules on nacos

5.2. Write routing rule groups on nacos 

5.3, write yml configuration file


1. Overview of SpringCloud Alibaba Sentinel and the construction of the console

1. Overview of Spring Cloud Alibaba Sentinel

2. Construction of Sentinel console

2.1. Download address

        Releases · alibaba/Sentinel · GitHub

2.2, start sentinel

java -Dserver.port=7777 -Dcsp.sentinel.dashboard.server=localhost:77
77 -Dproject.name=zhangkechen-sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar

2.3, visit sentinel

Address: http://localhost:7777/

3. What capabilities does the SpringCloud Alibaba Sentinel console have?

2. The current limiting function of sentinel is used in the project 

1. Add dependencies

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

2. yml configuration (under spring:cloud)

    sentinel:
      # 配置 sentinel dashboard 地址
      transport:
        dashboard: 127.0.0.1:7777
        port: 8719 # 会在应用对应的机器上启动一个 Http Server, 该 Server 会与 Sentinel 控制台做交互
      # 服务启动直接建立心跳连接
      eager: true
      datasource:

3. Write the current limiting controller interface

/**
 * <h1>基于 Sentinel 控制台配置流控规则</h1>
 * Sentinel 是懒加载的, 先去访问一下, 就可以在 Sentinel Dashboard 看到了
 * */
@Slf4j
@RestController
@RequestMapping("/dashboard")
public class RateLimitController {

    /**
     * <h2>在 dashboard 中 "流控规则" 中按照资源名称新增流控规则</h2>
     * */
    @GetMapping("/by-resource")
    @SentinelResource(
            value = "byResource",
            blockHandler = "qinyiHandleBlockException",
            blockHandlerClass = QinyiBlockHandler.class
    )
    public CommonResponse<String> byResource() {
        log.info("coming in rate limit controller by resource");
        return new CommonResponse<>(0, "", "byResource");
    }

    /**
     * <h2>在 "簇点链路" 中给 url 添加流控规则</h2>
     * */
    @GetMapping("/by-url")
    @SentinelResource(value = "byUrl")
    public CommonResponse<String> byUrl() {
        log.info("coming in rate limit controller by url");
        return new CommonResponse<>(0, "", "byUrl");
    }
}

4. Write custom general current limiting processing logic

/**
 * <h1>自定义通用的限流处理逻辑</h1>
 * */
@Slf4j
public class QinyiBlockHandler {

    /**
     * <h2>通用限流处理方法</h2>
     * 这个方法必须是 static 的
     * */
    public static CommonResponse<String> qinyiHandleBlockException(BlockException exception) {

        log.error("trigger qinyi block handler: [{}], [{}]",
                JSON.toJSONString(exception.getRule()), exception.getRuleLimitApp());
        return new CommonResponse<>(
                -1,
                "flow rule trigger block exception",
                null
        );
    }
}

3. Use sentinel to protect calls between RestTemplate services

1, placement RestTemplate 

1.1, yml configuration file configuration

# 开启或关闭 @SentinelRestTemplate 注解
resttemplate:
  sentinel:
    enabled: true

1.2, code configuration

/**
 * <h1>开启服务间的调用保护, 需要给 RestTemplate 做一些包装</h1>
 * */
@Slf4j
@Configuration
public class SentinelConfig {

    /**
     * <h2>包装 RestTemplate</h2>
     * */
    @Bean
    @SentinelRestTemplate(
            fallback = "handleFallback", fallbackClass = RestTemplateExceptionUtil.class,
            blockHandler = "handleBlock", blockHandlerClass = RestTemplateExceptionUtil.class
    )
    public RestTemplate restTemplate() {
        return new RestTemplate();  // 可以对其做一些业务相关的配置
    }
}

2. Configure the processing method after the service is abnormally degraded and the processing method after the current limit

/**
 * <h1>RestTemplate 在限流或异常时的兜底方法</h1>
 * */
@Slf4j
public class RestTemplateExceptionUtil {

    /**
     * <h2>限流后的处理方法</h2>
     * */
    public static SentinelClientHttpResponse handleBlock(HttpRequest request,
                                                         byte[] body,
                                                         ClientHttpRequestExecution execution,
                                                         BlockException ex) {
        log.error("Handle RestTemplate Block Exception: [{}], [{}]",
                request.getURI().getPath(), ex.getClass().getCanonicalName());
        return new SentinelClientHttpResponse(
                JSON.toJSONString(new JwtToken("qinyi-imooc-block"))
        );
    }

    /**
     * <h2>异常降级之后的处理方法</h2>
     * */
    public static SentinelClientHttpResponse handleFallback(HttpRequest request,
                                                            byte[] body,
                                                            ClientHttpRequestExecution execution,
                                                            BlockException ex) {
        log.error("Handle RestTemplate Fallback Exception: [{}], [{}]",
                request.getURI().getPath(), ex.getClass().getCanonicalName());
        return new SentinelClientHttpResponse(
                JSON.toJSONString(new JwtToken("qinyi-imooc-block"))
        );
    }
}

3. Use Sentinel to protect calls between RestTemplate services

/**
 * <h1>使用 Sentinel 保护 RestTemplate 服务间调用</h1>
 * */
@Slf4j
@RestController
@RequestMapping("/sentinel-rest-template")
public class SentinelRestTemplateController {

    private final RestTemplate restTemplate;

    public SentinelRestTemplateController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * <h2>从授权服务中获取 JwtToken</h2>
     * 1. 流控降级:
     * 是针对于簇点链路中的 http://127.0.0.1:7000/ecommerce-authority-center/authority/token
     * 2. 容错降级: 对于服务不可用时不能生效
     * */
    @PostMapping("/get-token")
    public JwtToken getTokenFromAuthorityService(
            @RequestBody UsernameAndPassword usernameAndPassword) {

        String requestUrl =
                "http://127.0.0.1:7000/ecommerce-authority-center/authority/token";
        log.info("RestTemplate request url and body: [{}], [{}]",
                requestUrl, JSON.toJSONString(usernameAndPassword));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return restTemplate.postForObject(
                requestUrl,
                new HttpEntity<>(JSON.toJSONString(usernameAndPassword), headers),
                JwtToken.class
        );
    }
}

4. Use sentinel to support fegin fuse downgrade

1. Configure fegin

# 打开 Sentinel 对 Feign 的支持
feign:
  sentinel:
    enabled: true

2. Write fegin client 

/**
 * <h1>通过 Sentinel 对 OpenFeign 实现熔断降级</h1>
 * */
@FeignClient(
        value = "e-commerce-imooc",
        fallback = SentinelFeignClientFallback.class
)
public interface SentinelFeignClient {

    @RequestMapping(value = "qinyi", method = RequestMethod.GET)
    CommonResponse<String> getResultByFeign(@RequestParam Integer code);
}

3. Write Sentinel's downgrade strategy for OpenFeign interface


/**
 * <h1>Sentinel 对 OpenFeign 接口的降级策略</h1>
 * */
@Slf4j
@Component
public class SentinelFeignClientFallback implements SentinelFeignClient {

    @Override
    public CommonResponse<String> getResultByFeign(Integer code) {

        log.error("request supply for test has some error: [{}]", code);
        return new CommonResponse<>(
                -1,
                "sentinel feign fallback",
                "input code: "+ code
        );
    }
}

4. Write a controller test using fegin's fusing downgrade

/**
 * <h1>OpenFeign 集成 Sentinel 实现熔断降级</h1>
 * */
@Slf4j
@RestController
@RequestMapping("/sentinel-feign")
public class SentinelFeignController {

    private final SentinelFeignClient sentinelFeignClient;

    public SentinelFeignController(SentinelFeignClient sentinelFeignClient) {
        this.sentinelFeignClient = sentinelFeignClient;
    }

    /**
     * <h2>通过 Feign 接口去获取结果</h2>
     * */
    @GetMapping("/result-by-feign")
    public CommonResponse<String> getResultByFeign(@RequestParam Integer code) {
        log.info("coming in get result by feign: [{}]", code);
        return sentinelFeignClient.getResultByFeign(code);
    }
}

5. Use sentinel to support RestTemplate fuse downgrade 

1. Write the strategy after the service fuse and downgrade (the method in the fallback in the controller and the method parameters in the class must be consistent)

/**
 * <h1>Sentinel 回退降级的兜底策略</h1>
 * 都需要是静态方法 fallback中的方法和类中的方法参数必须一致
 * */
@Slf4j
public class QinyiFallbackHandler {

    /**
     * <h2>getTokenFromAuthorityService 方法的 fallback</h2>
     * */
    public static JwtToken getTokenFromAuthorityServiceFallback(
            UsernameAndPassword usernameAndPassword
    ) {
        log.error("get token from authority service fallback: [{}]",
                JSON.toJSONString(usernameAndPassword));
        return new JwtToken("imooc-qinyi-fallback");
    }

    /**
     * <h2>ignoreException 方法的 fallback</h2>
     * */
    public static JwtToken ignoreExceptionFallback(Integer code) {
        log.error("ignore exception input code: [{}] has trigger exception", code);
        return new JwtToken("imooc-qinyi-fallback");
    }
}

2. Write a controller test to use RestTemplate's fuse degradation

package com.imooc.ecommerce.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.fastjson.JSON;
import com.imooc.ecommerce.fallback_handler.QinyiFallbackHandler;
import com.imooc.ecommerce.vo.JwtToken;
import com.imooc.ecommerce.vo.UsernameAndPassword;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

/**
 * <h1>Sentinel 提供容错降级的功能 服务未启动(容错了)</h1>
 * */

@SuppressWarnings("all")
@Slf4j
@RestController
@RequestMapping("/sentinel-fallback")
public class SentinelFallbackController {

    /** 注入没有增强的 RestTemplate */
    private final RestTemplate restTemplate;

    public SentinelFallbackController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @PostMapping("/get-token")
    @SentinelResource(
            value = "getTokenFromAuthorityService",
            fallback = "getTokenFromAuthorityServiceFallback",
            fallbackClass = { QinyiFallbackHandler.class }
    )
    public JwtToken getTokenFromAuthorityService(
            @RequestBody UsernameAndPassword usernameAndPassword) {

        String requestUrl =
                "http://127.0.0.1:7000/ecommerce-authority-center/authority/token";
        log.info("RestTemplate request url and body: [{}], [{}]",
                requestUrl, JSON.toJSONString(usernameAndPassword));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return restTemplate.postForObject(
                requestUrl,
                new HttpEntity<>(JSON.toJSONString(usernameAndPassword), headers),
                JwtToken.class
        );
    }

    /**
     * <h2>让 Sentinel 忽略一些异常</h2>
     * */
    @GetMapping("/ignore-exception")
    @SentinelResource(
            value = "ignoreException",
            fallback = "ignoreExceptionFallback",
            fallbackClass = { QinyiFallbackHandler.class },
            exceptionsToIgnore = { NullPointerException.class }
    )
    public JwtToken ignoreException(@RequestParam Integer code) {

        if (code % 2 == 0) {
            throw new NullPointerException("yout input code is: " + code);
        }

        return new JwtToken("qinyi-imooc");
    }
}

5. Sentinel combines Nacos to realize the persistence of current limiting rules

1. Spring Cloud Alibaba Sentinel configuration information

2. Integrate nacos to realize the persistence of current limiting rules

2.1. Add dependencies

        <!-- Sentinel 使用 Nacos 存储规则 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

2.2. Writing a current-limiting interface

    /**
     * <h2>在 dashboard 中 "流控规则" 中按照资源名称新增流控规则</h2>
     * */
    @GetMapping("/by-resource")
    @SentinelResource(
            value = "byResource",
            blockHandler = "qinyiHandleBlockException",
            blockHandlerClass = QinyiBlockHandler.class
    )
    public CommonResponse<String> byResource() {
        log.info("coming in rate limit controller by resource");
        return new CommonResponse<>(0, "", "byResource");
    }

2.3, yml configuration (under spring:cloud)

    sentinel:
      # 配置 sentinel dashboard 地址
      transport:
        dashboard: 127.0.0.1:7777
        port: 8719 # 会在应用对应的机器上启动一个 Http Server, 该 Server 会与 Sentinel 控制台做交互
      # 服务启动直接建立心跳连接
      eager: true
      datasource:
        # 名称任意, 代表数据源
        ds:
          nacos:
            # NacosDataSourceProperties.java 中定义
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            dataId: ${spring.application.name}-sentinel
            namespace: ${spring.cloud.nacos.discovery.namespace}
            groupId: DEFAULT_GROUP
            data-type: json
            # 规则类型: com.alibaba.cloud.sentinel.datasource.RuleType
            # FlowRule 就是限流规则
            rule-type: flow

2.4. Write the configuration of the specified current-limiting interface on nacos

[
  {
    "resource": "byresource",
    "limitApp": "default",
    "grade": 1,
    "count": 1,
    "strategy": 0,
    "controlBehavior": 0,
    "clusterMode": false
  }
]

6. Gateway integrates Sentinel to realize gateway current limiting (no matter which way the boilerplate code in hard coding must be added to Gateway)

1. Introduce dependencies

        <!-- 集成 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>
        <!-- Sentinel 使用 Nacos 存储规则 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

2. Write the configuration file (under spring:cloud)

    sentinel:
      # 配置 sentinel dashboard 地址
      transport:
        dashboard: 127.0.0.1:7777
        port: 8719 # 会在应用对应的机器上启动一个 Http Server, 该 Server 会与 Sentinel 控制台做交互
      # 服务启动直接建立心跳连接
      eager: true

3. Hard-coded way to achieve

package com.imooc.ecommerce.config;

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * <h1>Gateway 集成 Sentinel 实现限流</h1>
 * */
@Slf4j
@Configuration
public class SentinelGatewayConfiguration {
    //=====================================================样板间式代码开始=====================================================

    /** 视图解析器 */
    private final List<ViewResolver> viewResolvers;
    /** HTTP 请求和响应数据的编解码配置 */
    private final ServerCodecConfigurer serverCodecConfigurer;

    /**
     * <h2>构造方法</h2>
     * */
    public SentinelGatewayConfiguration(
            ObjectProvider<List<ViewResolver>> viewResolversProvider,
            ServerCodecConfigurer serverCodecConfigurer
    ) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    /**
     * <h2>限流异常处理器, 限流异常出现时, 执行到这个 handler</h2>
     * */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // 默认会返回错误 message, code 429
        return new SentinelGatewayBlockExceptionHandler(
                this.viewResolvers,
                this.serverCodecConfigurer
        );
    }

    /**
     * <h2>限流过滤器, 是 Gateway 全局过滤器, 优先级定义为最高</h2>
     * */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
    /** 
     * 自定义限流异常返回
     */
    @PostConstruct
    public void initBlockHandlers() {
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map result = new HashMap();
                result.put("code","500016");
                result.put("msg","接口被限流了");
                return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject(result));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }

    //=====================================================样板间式代码结束=====================================================



    //=====================================================硬编码方式实现限流规则============================================//
    /**
     * <h2>初始化限流规则</h2>
     * */
//    @PostConstruct
    public void doInit() {

        log.info("---------------------------------------------------");

        // 加载网关限流规则
        log.info("load sentinel gateway rules (code define)");
        initGatewayRules();

        // 加载自定义限流异常处理器
        initBlockHandler();

        log.info("---------------------------------------------------");
    }

    /**
     * <h2>硬编码网关限流规则</h2>
     * */
    private void initGatewayRules() {

        Set<GatewayFlowRule> rules = new HashSet<>();

        GatewayFlowRule rule = new GatewayFlowRule();
        // 指定限流模式, 根据 route_id 做限流, 默认的模式
        rule.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID);
        // 指定 route_id -> service id
        rule.setResource("e-commerce-nacos-client");
        // 按照 QPS 限流
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 统计窗口和限流阈值
        rule.setIntervalSec(60);
        rule.setCount(3);

//        rules.add(rule);

        // 限流分组, Sentinel 先去找规则定义, 再去找规则中定义的分组
        rules.add(
                new GatewayFlowRule("nacos-client-api-1")
                        .setCount(3).setIntervalSec(60)
        );
        rules.add(
                new GatewayFlowRule("nacos-client-api-2")
                        .setCount(1).setIntervalSec(60)
        );

        // 加载到网关中
        GatewayRuleManager.loadRules(rules);

        // 加载限流分组
        initCustomizedApis();
    }

    /**
     * <h2>自定义限流异常处理器</h2>
     * */
    private void initBlockHandler() {

        // 自定义 BlockRequestHandler
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange,
                                                      Throwable throwable) {

                log.error("------------- trigger gateway sentinel rule -------------");

                Map<String, String> result = new HashMap<>();
                result.put("code", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
                result.put("message", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
                result.put("route", "e-commerce-nacos-client");

                return ServerResponse
                        .status(HttpStatus.TOO_MANY_REQUESTS)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue(result));
            }
        };

        // 设置自定义限流异常处理器
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }

    /**
     * <h2>硬编码网关限流分组</h2>
     * 1. 最大限制 - 演示
     * 2. 具体的分组
     * */
    private void initCustomizedApis() {

        Set<ApiDefinition> definitions = new HashSet<>();

        // nacos-client-api 组, 最大的限制
        ApiDefinition api = new ApiDefinition("nacos-client-api")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {
   
   {
                    // 模糊匹配 /imooc/ecommerce-nacos-client/ 及其子路径的所有请求
                    add(new ApiPathPredicateItem()
                            .setPattern("/imooc/ecommerce-nacos-client/**")
                            // 根据前缀匹配
                    .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});

        // nacos-client-api-1 分组
        ApiDefinition api1 = new ApiDefinition("nacos-client-api-1")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {
   
   {
                    add(new ApiPathPredicateItem()
                            // 精确匹配 /imooc/ecommerce-nacos-client/nacos-client/service-instance
                            .setPattern("/imooc/ecommerce-nacos-client" +
                                    "/nacos-client/service-instance"));
                }});

        // nacos-client-api-2 分组
        ApiDefinition api2 = new ApiDefinition("nacos-client-api-2")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {
   
   {
                    add(new ApiPathPredicateItem()
                            // 精确匹配 /imooc/ecommerce-nacos-client/nacos-client/project-config
                            .setPattern("/imooc/ecommerce-nacos-client" +
                                    "/nacos-client/project-config"));
                }});

        definitions.add(api1);
        definitions.add(api2);

        // 加载限流分组
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }
}

4. Local file implementation

4.1. Writing routing rules

gateway-flow-rule-sentinel.json (routing rules, resource can be interface name, microservice name, group name, resourceMode=1, resourceMode=0 means grouping)

[
  {
    "resource": "e-commerce-nacos-client",
    "resourceMode": 0,
    "count": 3,
    "intervalSec": 60
  },
  {
    "resource": "nacos-client-api",
    "resourceMode": 1,
    "count": 1,
    "intervalSec": 60
  }
]

4.2, write routing rule grouping 

gateway-flow-rule-api-sentinel.json (routing rule grouping, indicating that when the resource is apiname, the interface paths in the grouping follow the flow-limiting rules in the resource)

[
  {
    "apiName": "nacos-client-api",
    "predicateItems": [
      {
        "pattern": "/imooc/ecommerce-nacos-client/nacos-client/project-config"
      },
      {
        "pattern": "/imooc/ecommerce-nacos-client/**",
        "matchStrategy": 1
      }
    ]
  }
]

4.3. Writing configuration files

    sentinel:
      eager: true
      transport:
        client-ip: 8720
        dashboard: 127.0.0.1:7777
      datasource:
        dsl.file:
          file: classpath:gateway-flow-rule-sentinel.json
          ruleType: gw-flow
        ds2.file:
          file: classpath:gateway-flow-rule-api-sentinel.json
          ruleType: gw-api-group

5. Nacos implementation

 5.1. Write routing rules on nacos

gateway-flow-rule-sentinel.json (routing rules, resource can be interface name, microservice name, group name, resourceMode=0 is roteId, resourceMode=1 means api grouping)

[
  {
    "resource": "e-commerce-nacos-client",
    "resourceMode": 0,
    "count": 3,
    "intervalSec": 60
  },
  {
    "resource": "nacos-client-api",
    "resourceMode": 1,
    "count": 1,
    "intervalSec": 60
  }
]

5.2. Write routing rule groups on nacos 

gateway-flow-rule-api-sentinel.json (routing rule grouping, indicating that when the resource is apiname, the interface path in the grouping is changed according to the current limiting rule in the resource, matchStrategy=1 means fuzzy matching, and the default is exact matching )

[
  {
    "apiName": "nacos-client-api",
    "predicateItems": [
      {
        "pattern": "/imooc/ecommerce-nacos-client/nacos-client/project-config"
      },
      {
        "pattern": "/imooc/ecommerce-nacos-client/**",
        "matchStrategy": 1
      }
    ]
  }
]

5.3, write yml configuration file

    sentinel:
      eager: true
      transport:
        client-ip: 8720
        dashboard: 127.0.0.1:7777
      datasource:
        # 名称任意, 代表数据源
        ds1:
          nacos:
            # NacosDataSourceProperties.java 中定义
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            dataId: gateway-flow-rule-sentinel
            namespace: ${spring.cloud.nacos.discovery.namespace}
            groupId: DEFAULT_GROUP
            data-type: json
            # 规则类型: com.alibaba.cloud.sentinel.datasource.RuleType
            # FlowRule 就是限流规则
            rule-type: gw_flow
        # 名称任意, 代表数据源
        ds2:
          nacos:
            # NacosDataSourceProperties.java 中定义
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            dataId: gateway-flow-rule-api-sentinel
            namespace: ${spring.cloud.nacos.discovery.namespace}
            groupId: DEFAULT_GROUP
            data-type: json
            # 规则类型: com.alibaba.cloud.sentinel.datasource.RuleType
            # FlowRule 就是限流规则
            rule-type: gw_api_group

 
 
 
 

Guess you like

Origin blog.csdn.net/m0_52208135/article/details/128834698