SpringCloudAlibabaSentinel实现网关动态限流

目录

1.SpringCloudAlibabaSentinel实现网关动态限流

1.概念和来历

2.概览及控制台搭建

3.控制台有哪些能力

4.功能及设计理念

5.限流的几种方法

2.SpringCloud Alibaba Sentinel 的降级功能

1.yml中添加配置

2.编写配置类

3.编写兜底工具类

3.Sentinel还对Feigin实现了适配,支持Fenig的容错降级

3.1启动类添加注解

3.2编写feign接口

3.3编写Sentinel 对 OpenFeign 接口的降级策略

4.Sentinel结合Nacos实现限流规则持久化

4.1sentinel存储在nacos中限流数据结构

4.2添加依赖

4.3在限流资源添加限流规则

4.4在yml文件中添加配置

5.GeteWay集成Sentinel实现网关限流

5.1最简单、也是常用的测试方式:在网关内硬编码实现对请求的限流

5.2配置文件的方式编写限流规则

5.3Gateway集成Nacos+Sentiel实现网关动态限流

6.为什么需要限流


1.SpringCloudAlibabaSentinel实现网关动态限流

1.概念和来历

Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。
Sentinel的来历
1.2012年,Sentinel 诞生,主要功能为入口流量控制
2.2013-2017 年,Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心场景
3.2018 年,Sentinel 开源,并持续演进
​
SpringCloud Alibaba Sentinel 的基本概念
资源:可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码
方法签名 URL 服务名
规则:围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则:且所有规则可以动态实时调整

2.概览及控制台搭建

Sentinel提供一个轻量级的开源控制台(单机和集群),规则管理和推送的功能
获取并启动 Sentinel Dashboard (控制台
​
1.下载控制台 Jar 包: https://github.com/alibaba/Sentinel/releases
# 创建命令
mkdir -p /usr/local/sentinel
​
cd  /usr/local/sentinel
#下载1.8.0版本
wget https://github.com/alibaba/Sentinel/releases/download/1.8.1/sentinel-dashboard-1.8.1.jar
​
2.nohup  java -Dserver.port=7777 -Dcsp.sentinel.dashboard.server=localhost:7777 -Dproject.name=butool-sentinel-dashboard -jar /usr/local/sentinel/sentinel-dashboard-1.8.1.jar &
​
3.从Sentinel 1.6.0 起,Sentinel Dashboard 引入了基本的登录功能,默认的用户名密码都是 sentinel
​
4.打开防火墙端口
firewall-cmd --zone=public --add-port=7777/tcp --permanent
firewall-cmd --reload
​
4.访问地址
ip:7777

3.控制台有哪些能力

1.查看机器列表以及健康情况: 收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线
​
2.监控(单机和集群聚合): 通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控
​
3.规则管理和推送:统一管理推送规则

4.功能及设计理念

4.1流量控制

流量控制在网络传输中是一个常用的概念,
它用于调整网络包的发送数据。
然而,从系统稳定性角度考虑,
在处理请求的速度上,也有非常多的讲究。
任意时间到来的请求往往是随机不可控的,
而系统的处理能力是有限的。
我们需要根据系统的处理能力对流量进行控制。
Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,
如下图所示:

SpringCloudAlibabaSentinel实现网关动态限流_第1张图片

4.2流量控制设计理念

流量控制有以下几个角度:
​
1.资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
​
2.运行指标,例如 QPS、线程池、系统负载等;
​
3.控制的效果,例如直接限流、冷启动、排队等。
​
Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

5.限流的几种方法

1.硬编码方式

1.yml文件里添加sentinel服务端地址
2.在资源方法上添加注解@SentinelResource(value="方法名")
3.配置初始化方法指定资源为SentinelResource.value
4.设置一秒请求几次
5.完成请求
6.控制台可以看到流控资源列表,看不到可能懒加载就请求一次

2.设置自定义返回信息

1.在controller中添加方法,返回值和Request方法一致,入参为BlockException
2.获取错误信息BlockException.getRuleLimitApp()
3.@SentinelResource注解中添加属性flowHandle值为方法名称
4.连续请求两次会看到结果

3.自定义通用的限流逻辑

1.创建类类中需要写静态方法,sentinel不会对对象进行new操作 
2.方法返回值和Request方法一致,入参为BlockException
3.获取错误信息BlockException.getRuleLimitApp()
4.@SentinelResource注解中添加属性flowHandleClass值为类名,@SentinelResource.bolckHandler值为静态方法名称

4.基于sentinel控制台配置流控规则,根据资源名称

1.sentinel懒加载需要请求一次就会在控制台上看到资源
2.定义controller方法在控制台新增流控规则根据资源名称
@SentinelResource(
value ="byResource",blockHandler ="qinyiHandleBlockException"blockHandlerClass = ButoolBlockHandler.class
public CommonResponse byResource() {}
请求一次后在控制台配置限流规则

5.在“簇点链路”中给 url 添加流控规则

在“簇点链路”中给 url 添加流控规则
@SentinelResource(value = "byUrl")public CommonResponse byUrl{}
在控制台簇点链路中新增流控规则

2.SpringCloud Alibaba Sentinel 的降级功能

1.Sentinel 支持对 RestTemplate 服务调用进行保护,实现流控降级和异常降级
2.在构造RestTempplate这bean上添加@SentinelRestTemplate注解

SpringCloudAlibabaSentinel实现网关动态限流_第2张图片

1.yml中添加配置

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

2.编写配置类

package cn.butool.conf;
​
import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
​
/**
 * 

开启服务间的调用保护, 需要给 RestTemplate 做一些包装

* */ @Slf4j @Configuration public class SentinelConfig { ​    /**     *

包装 RestTemplate

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

3.编写兜底工具类

package cn.butool.conf;
​
import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import com.imooc.ecommerce.vo.JwtToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
​
/**
 * 

RestTemplate 在限流或异常时的兜底方法

* */ @Slf4j public class RestTemplateExceptionUtil { ​    /**     *

限流后的处理方法

    * */    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("butool-block"))       );   } ​    /**     *

异常降级之后的处理方法

    * */    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("butool-block"))       );   } }

3.Sentinel还对Feigin实现了适配,支持Fenig的容错降级

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

3.1启动类添加注解

@EnableFeignClients

3.2编写feign接口

/**
 * 

通过 Sentinel 对 OpenFeign 实现熔断降级

* */ @FeignClient(        value = "e-commerce-butool",        fallback = SentinelFeignClientFallback.class ) public interface SentinelFeignClient { ​    @RequestMapping(value = "busl", method = RequestMethod.GET)    CommonResponse getResultByFeign(@RequestParam Integer code); } ​

3.3编写Sentinel 对 OpenFeign 接口的降级策略

import cn.butool.vo.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
​
/**
 * 

Sentinel 对 OpenFeign 接口的降级策略

* */ @Slf4j @Component public class SentinelFeignClientFallback implements SentinelFeignClient { ​    @Override    public CommonResponse getResultByFeign(Integer code) { ​        log.error("request supply for test has some error: [{}]", code);        return new CommonResponse<>(                -1,                "sentinel feign fallback",                "input code: "+ code       );   } }

4.Sentinel结合Nacos实现限流规则持久化

1.Sentinel Dashboard 将规则保存在内存中,重启之后就会丢失,所以,考虑使用外部持久化方案
2.在Nacos 中创建规则,Nacos 会推送到客户端,Sentinel Dashboard 也会从 Nacos 去获取配置信息(远程配置中心(e.g. Nacos, ZooKeeper))

4.1sentinel存储在nacos中限流数据结构

[
  {
    "resource": "byResource", # 资源名
    "limitApp": "default", # 流控针对的调用来源
    "grade": 1, # 限流的阈值类型 1 QPS ,0 并发线程数
    "count": 3, # 每1秒中能通过几个请求
    "strategy": 0, # 0 直接限流 1 关联 2 链路
    "controlBehavior": 0, # 控制效果:0 快速失败 1 warm Up 2 排队等待
    "clusterMode": false # 是否集群效果
  }
]

SpringCloudAlibabaSentinel实现网关动态限流_第3张图片

4.2添加依赖

 
        
            com.alibaba.csp
            sentinel-datasource-nacos
        

4.3在限流资源添加限流规则

/**
     * 

在 dashboard 中 "流控规则" 中按照资源名称新增流控规则

    * */    @GetMapping("/by-resource")    @SentinelResource(            value = "byResource",            blockHandler = "ButoolHandleBlockException",            blockHandlerClass = ButoolBlockHandler.class   )    public CommonResponse byResource() {        log.info("coming in rate limit controller by resource");        return new CommonResponse<>(0, "", "byResource");   } package cn.butool.block_handler; ​ import cn.butool.vo.CommonResponse; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; ​ /** *

自定义通用的限流处理逻辑

* */ @Slf4j public class ButoolBlockHandler { ​    /**     *

通用限流处理方法

    * 这个方法必须是 static 的     * */    public static CommonResponse ButoolHandleBlockException(BlockException exception) { ​        log.error("trigger qinyi block handler: [{}], [{}]",                JSON.toJSONString(exception.getRule()), exception.getRuleLimitApp());        return new CommonResponse<>(                -1,                "flow rule trigger block exception",                null       );   } }

4.4在yml文件中添加配置

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
      # 服务启动直接建立心跳连接
      eager: true

5.GeteWay集成Sentinel实现网关限流

5.1最简单、也是常用的测试方式:在网关内硬编码实现对请求的限流

[
​
  {
    "resource": "nacos-client-api",
    "resourceMode": 1, # 规则与resource相绑定
    "count": 1, # 限流阈值
    "Grade": 1, # 限流的阈值类型 1 QPS ,0 并发线程数
    "intervalSec": 60 # 统计范围 60秒内允许1个请求
  }
]

SpringCloudAlibabaSentinel实现网关动态限流_第4张图片

1网关服务添加依赖


        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-sentinel
        
        
            com.alibaba.cloud
            spring-cloud-alibaba-sentinel-gateway
        
        
        
            com.alibaba.csp
            sentinel-datasource-nacos
        

2yml中添加配置

sentinel: # 与nacos属性平齐
      # 配置 sentinel dashboard 地址
      transport:
        dashboard: 192.168.1.11:7777
        clientIp: 192.168.1.7
        port: 8719 # 会在应用对应的机器上启动一个 Http Server, 该 Server 会与 Sentinel 控制台做交互
  

3sentinel服务端启动命令修改

# 支持网关
nohup java -Dcsp.sentinel.app.type=1 -Dserver.port=7777 -Dcsp.sentinel.dashboard.server=localhost:7777 -Dproject.name=butool-sentinel-gateway -jar /usr/local/sentinel/sentinel-dashboard-1.8.1.jar &

4网关集成配置类

package cn.butool.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.*;
​
/**
 * 

Gateway 集成 Sentinel 实现限流

* */ @Slf4j @Configuration public class SentinelGatewayConfiguration { ​    /** 视图解析器 */    private final List viewResolvers;    /** HTTP 请求和响应数据的编解码配置 */    private final ServerCodecConfigurer serverCodecConfigurer; ​    /**     *

构造方法

    * */    public SentinelGatewayConfiguration(            ObjectProvider> viewResolversProvider,            ServerCodecConfigurer serverCodecConfigurer   ) {        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);        this.serverCodecConfigurer = serverCodecConfigurer;   } ​    /**     *

限流异常处理器, 限流异常出现时, 执行到这个 handler

    * */    @Bean    @Order(Ordered.HIGHEST_PRECEDENCE)    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {        // 默认会返回错误 message, code 429        return new SentinelGatewayBlockExceptionHandler(                this.viewResolvers,                this.serverCodecConfigurer       );   } ​    /**     *

限流过滤器, 是 Gateway 全局过滤器, 优先级定义为最高

    * */    @Bean    @Order(Ordered.HIGHEST_PRECEDENCE)    public GlobalFilter sentinelGatewayFilter() {        return new SentinelGatewayFilter();   } ​    /**     *     * 初始化限流规则     * */    @PostConstruct    public void doInit(){ ​        log.info("--------------------------------------");        log.info("load sentinel gateway rules (code define)");        initGatewayRules();        log.info("--------------------------------------");   }    /**     * 硬编码网关限流规则     */    private void initGatewayRules(){        Set 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); ​              // 加载到网关中        GatewayRuleManager.loadRules(rules); ​         } } ​

4请求指定的服务查看限流情况

 // 指定 route_id -> service id rule.setResource("e-commerce-nacos-client"); 60秒内请求三次以上报下面错误

SpringCloudAlibabaSentinel实现网关动态限流_第5张图片

5自定义返回错误信息

/**
     *
     * 初始化限流规则
     * */
    @PostConstruct
    public void doInit(){
​
        log.info("--------------------------------------");
        log.info("load sentinel gateway rules (code define)");
        initGatewayRules();
        log.info("--------------------------------------");
​
        // 加载自定义限流异常处理器
        initBlockHandler();
    }
​
​
/**
     * 

自定义限流异常处理器

    * */    private void initBlockHandler() { ​        // 自定义 BlockRequestHandler        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {            @Override            public Mono handleRequest(ServerWebExchange serverWebExchange,                                                      Throwable throwable) {                log.error("------------- trigger gateway sentinel rule -------------");                Map 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);   }

6.自定义分组限流

​
    
/**
     * 硬编码网关限流规则
     */
    private void initGatewayRules(){
        Set rules = new HashSet<>();
        // 限流分组, 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();
    }
​
   
​
    /**
     * 

硬编码网关限流分组

    * 1. 最大限制 - 演示     * 2. 具体的分组     * */    private void initCustomizedApis() { ​        Set definitions = new HashSet<>(); ​        // nacos-client-api 组, 最大的限制        ApiDefinition api = new ApiDefinition("nacos-client-api")               .setPredicateItems(new HashSet() {{                    // 模糊匹配 /butool/ecommerce-nacos-client/ 及其子路径的所有请求                    add(new ApiPathPredicateItem()                           .setPattern("/butool/ecommerce-nacos-client/**")                            // 根据前缀匹配                           .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));               }}); ​        // nacos-client-api-1 分组        ApiDefinition api1 = new ApiDefinition("nacos-client-api-1")               .setPredicateItems(new HashSet() {{                    add(new ApiPathPredicateItem()                            // 精确匹配 /butool/ecommerce-nacos-client/nacos-client/service-instance                           .setPattern("/butool/ecommerce-nacos-client/nacos-client/service-instance"));               }}); ​        // nacos-client-api-2 分组        ApiDefinition api2 = new ApiDefinition("nacos-client-api-2")               .setPredicateItems(new HashSet() {{                    add(new ApiPathPredicateItem()                            // 精确匹配 /butool/ecommerce-nacos-client/nacos-client/project-config                           .setPattern("/butool/ecommerce-nacos-client" +                                    "/nacos-client/project-config"));               }}); ​        definitions.add(api1);        definitions.add(api2); ​        // 加载限流分组        GatewayApiDefinitionManager.loadApiDefinitions(definitions);   }

5.2配置文件的方式编写限流规则

1.yml文件

硬编码工作较多,相对来说比较繁琐;熟悉之后可以进一步使用配置文件的形式
1.resources目录下存放文件
2.yml文件中配置
    sentinel:
      # 配置 sentinel dashboard 地址
      transport:
        dashboard: 192.168.1.11:7777
        clientIp: 192.168.1.7
        port: 8719 # 会在应用对应的机器上启动一个 Http Server, 该 Server 会与 Sentinel 控制台做交互
      datasource:
       #通过本地文件方式, 基于服务级别的配置
        dsl.file:
          file: classpath:gateway-flow-rule-sentinel.json
          # 代表服务级别的限流, 一步步点进去看, 文件类型
          ruleType: gw-flow
        # 通过本地文件方式, 细粒度对指定 api 进行配置
        ds2.file:
          file: classpath:gateway-flow-rule-api-sentinel.json
          # 代表 API 分组, 一步步点进去看, 文件类型
          ruleType: gw-api-group  

2.json文件

## 文件名 gateway-flow-rule-api-sentinel.json
[
  {
    "apiName": "nacos-client-api",
    "predicateItems": [
      {
        "pattern": "/butool/ecommerce-nacos-client/nacos-client/project-config"
      },
      {
        "pattern": "/butool/ecommerce-nacos-client/**",
        "matchStrategy": 1
      }
    ]
  }
]
​
## 文件名 gateway-flow-rule-sentinel.json
[
  {
    "resource": "e-commerce-nacos-client",
    "resourceMode": 0,
    "count": 3,
    "intervalSec": 60
  },
  {
    "resource": "nacos-client-api",
    "resourceMode": 1,
    "count": 1,
    "intervalSec": 60
  }
]
​

5.配置类

package cn.butool.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.*;
​
/**
 * 

Gateway 集成 Sentinel 实现限流

* */ @Slf4j @Configuration public class SentinelGatewayConfiguration { ​    /** 视图解析器 */    private final List viewResolvers;    /** HTTP 请求和响应数据的编解码配置 */    private final ServerCodecConfigurer serverCodecConfigurer; ​    /**     *

构造方法

    * */    public SentinelGatewayConfiguration(            ObjectProvider> viewResolversProvider,            ServerCodecConfigurer serverCodecConfigurer   ) {        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);        this.serverCodecConfigurer = serverCodecConfigurer;   } ​    /**     *

限流异常处理器, 限流异常出现时, 执行到这个 handler

    * */    @Bean    @Order(Ordered.HIGHEST_PRECEDENCE)    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {        // 默认会返回错误 message, code 429        return new SentinelGatewayBlockExceptionHandler(                this.viewResolvers,                this.serverCodecConfigurer       );   } ​    /**     *

限流过滤器, 是 Gateway 全局过滤器, 优先级定义为最高

    * */    @Bean    @Order(Ordered.HIGHEST_PRECEDENCE)    public GlobalFilter sentinelGatewayFilter() {        return new SentinelGatewayFilter();   } }

5.3Gateway集成Nacos+Sentiel实现网关动态限流

1.nacos中添加配置

2.json内容

## dataId gateway-flow-rule-api-sentinel
[
  {
    "apiName": "nacos-client-api",
    "predicateItems": [
      {
        "pattern": "/butool/ecommerce-nacos-client/nacos-client/project-config"
      },
      {
        "pattern": "/butool/ecommerce-nacos-client/**",
        "matchStrategy": 1
      }
    ]
  }
]
​
## dataId gateway-flow-rule-sentinel
[
  {
    "resource": "e-commerce-nacos-client",
    "resourceMode": 0,
    "count": 3,
    "intervalSec": 60
  },
  {
    "resource": "nacos-client-api",
    "resourceMode": 1,
    "count": 1,
    "intervalSec": 60
  }
]

6.为什么需要限流

1.平台用户增长过快 
​2.热点事件、热点接口、热点 Key ​ 
3.恶意请求
​

1.实现原理

Sentinel 通过实现 Filter,对路由/API分组匹配、请求属性解析和参数组装实现限流

SpringCloudAlibabaSentinel实现网关动态限流_第6张图片

你可能感兴趣的:(Sentinel,springcloud,java,开发语言)