SpringCloudAlibabaSentinel实现网关动态限流

news2024/11/19 6:37:49

目录

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 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,
如下图所示:

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<String> byResource() {}
请求一次后在控制台配置限流规则

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

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

2.SpringCloud Alibaba Sentinel 的降级功能

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

 

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;
​
/**
 * <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();  // 可以对其做一些业务相关的配置
    }
}

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

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

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

3.1启动类添加注解

@EnableFeignClients

3.2编写feign接口

/**
 * <h1>通过 Sentinel 对 OpenFeign 实现熔断降级</h1>
 * */
@FeignClient(
        value = "e-commerce-butool",
        fallback = SentinelFeignClientFallback.class
)
public interface SentinelFeignClient {
​
    @RequestMapping(value = "busl", method = RequestMethod.GET)
    CommonResponse<String> getResultByFeign(@RequestParam Integer code);
}
​

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

import cn.butool.vo.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
​
/**
 * <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.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 # 是否集群效果
  }
]

 

4.2添加依赖

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

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

/**
     * <h2>在 dashboard 中 "流控规则" 中按照资源名称新增流控规则</h2>
     * */
    @GetMapping("/by-resource")
    @SentinelResource(
            value = "byResource",
            blockHandler = "ButoolHandleBlockException",
            blockHandlerClass = ButoolBlockHandler.class
    )
    public CommonResponse<String> 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;
​
/**
 * <h1>自定义通用的限流处理逻辑</h1>
 * */
@Slf4j
public class ButoolBlockHandler {
​
    /**
     * <h2>通用限流处理方法</h2>
     * 这个方法必须是 static 的
     * */
    public static CommonResponse<String> 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个请求
  }
]

 

1网关服务添加依赖

<!-- 集成 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>

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.*;
​
/**
 * <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 doInit(){
​
        log.info("--------------------------------------");
        log.info("load sentinel gateway rules (code define)");
        initGatewayRules();
        log.info("--------------------------------------");
    }
    /**
     * 硬编码网关限流规则
     */
    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);
​
       
        // 加载到网关中
        GatewayRuleManager.loadRules(rules);
​
       
    }
}
​

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

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

 

5自定义返回错误信息

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

6.自定义分组限流

​
    
/**
     * 硬编码网关限流规则
     */
    private void initGatewayRules(){
        Set<GatewayFlowRule> 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();
    }
​
   
​
    /**
     * <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>() {{
                    // 模糊匹配 /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<ApiPredicateItem>() {{
                    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<ApiPredicateItem>() {{
                    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.*;
​
/**
 * <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();
    }
}

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分组匹配、请求属性解析和参数组装实现限流

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/157223.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码整洁之道,好的代码就是为了更美好的生活

概述 美国童子军有一条简单的军规&#xff1a;让营地比你来时更干净。当梳理代码时&#xff0c;坚守此军规&#xff1a;每次 review 代码&#xff0c;让代码比你发现它时更整洁。 一位大神说过&#xff1a;“衡量代码质量的唯一有效标准&#xff1a;WTF/min”&#xff0c;并配…

14.Isaac教程--Jetbot应用示例

Jetbot应用示例 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 本节介绍如何将 Isaac SDK 与 NVIDIA 新的高性能模拟平台 Omniverse 集成&#xff0c;以让 Jetbot 在模拟中跟随球。 本节作为使用三个 Jetbot 应用程序进入 Omniverse 和 Isaac …

国产的蓝光存储设备能算信创产品吗?

这个问题是客户前几天问我的&#xff0c;笔者只能实事求是的告诉他&#xff1a;目前还不能算&#xff01;首先蓝光存储产品暂时未被列入信创名录&#xff0c;其次蓝光存储中最核心的读写设备&#xff08;蓝光光驱&#xff09;的技术专利和生产工艺基本被日本企业&#xff08;索…

LeetCode 101. 对称二叉树

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 101. 对称二叉树&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 LeetCode 1…

高端运动耳机哪个品牌最好、公认最好的跑步耳机品牌排名

在健身、运动的时候&#xff0c;过程往往是很枯燥的&#xff0c;这时候&#xff0c;如果能有动感的音乐在旁&#xff0c;调动我们的积极性&#xff0c;就再好不过了&#xff0c;所以很多人在运动的时候都会选择佩戴一款运动蓝牙耳机。不过适合运动的蓝牙耳机少之又少&#xff0…

七、MySQL 多表查询详解(附练习题及答案----超详细)

文章目录一、笛卡尔积&#xff08;或交叉连接&#xff09;的理解二、多表查询分类讲解2.1 分类1&#xff1a;等值连接 vs 非等值连接2.2 分类2&#xff1a;自连接 vs 非自连接2.3 分类3&#xff1a;内连接 vs 外连接2.4 SQL99语法实现多表查询2.4.1 内连接2.4.2 左连接2.4.3 右…

System Description 步骤

纲要&#xff1a; 在有了Composition以后&#xff0c;下一步就是把它分配到ECU里面。 1. Create System Description Import DBC file, select ECUs and CAN Frames under the DBC. Then it will create "SystemDescription.arxml" file. [1] 2. Check the content…

地图下载器代码结构设计及功能实现

jcef包引入表结构设计后台关键代码结构前端关键代码结构功能展示启动页底图切换绘制选择下载区域行政区划切换选择下载区域下载关键代码import { InnerMqClient } from ../../rx/inner-mq.service;import { SubmitService } from ../../service/submit.service;import { MapBas…

马蹄集 字符判断

字符判断 难度&#xff1a;白银 时间限制&#xff1a;1秒 巴占用内存&#xff1a;64M 输入一个字符&#xff0c;判断是数字字符、大写字母、小写字母、算术运算符、 关系运算符、逻辑运算符&#xff0c;还是其他字符&#xff0c;分别输出Number?”, "Capital letter?”,…

Springboot集成knife4j文档时,接口信息没有显示

我使用的 SpringBoot、knife4j 版本jar包如下所示&#xff1a;<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.5.RELEASE</version><relativePath/> …

kube-bench初体验

kube-bench是一个通过运行CIS Kubernetes benchmark中记录的checker来检查Kubernetes是否安全部署的工具。测试&#xff0c;找gap&#xff0c;audit&#xff0c;都可以啊关于CIS k8s benchmark 参见 CIS Kubernetes Benchmarks (cisecurity.org)就是说&#xff0c;想做k8s加固&…

再学C语言32:函数——多源代码文件程序及其编译

使用多个函数时&#xff0c;最简单的方法是将所有函数放在同一文件中&#xff0c;就像编译单个函数的文件一样对该文件进行编译 具体的编译过程根据操作系统不同而具有差异性 Window系统下的编译器是面向工程的 工程&#xff08;project&#xff09;&#xff1a;描述了一个特…

【Linux】项目自动化构建工具—make/makefile

文章目录1. 什么是make/makefile&#xff1f;2. make/makefile的使用2.1 实例代码2.2 依赖关系和依赖方法2.3 项目清理2.4 make是如何确定是否编译的3. Linux第一个小程序—进度条3.1 \r 和 \n3.2 进度条小程序1. 什么是make/makefile&#xff1f; make是一个命令工具&#xf…

【Spring6源码・IOC】Bean的初始化 - 终结篇

前面两篇&#xff0c;我们着重讲解了一下《BeanDefinition的加载》和《bean的实例化》。 这一篇我们来讲解一下bean的初始化。 我们这里的案例依旧是以SpringBoot3.0、JDK17为前提&#xff0c;案例代码如下&#xff1a; Component public class A {Autowiredprivate B b;}Com…

Windows+iis+php+mysql搭建wordpress

准备工作 WindowsServer一台 IIS&#xff0c;在Server上开启 PHP:PHP: Downloads Mysql:MySQL :: MySQL Downloads wordpress下载 | WordPress.org China 简体中文 PHP程序在IIS上以fastcgi方式运行&#xff0c;在安装mysql和php之前确保vc库已安装。 IIS确保开启CGI模块…

JAVA开发(AOP之ProceedingJoinPoint)

我们在开发过程中经常使用到自定义注解来实现在一些类或者方法执行过程中切面&#xff0c;统一实现某些业务操作。例如自定义注解import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang…

YOLOv7:面向实时检测的目标检测器 | 附结构图

YOLOv7 在 5 FPS 到 160 FPS 范围内的速度和准确度都超过了所有已知的目标检测器&#xff0c;并且在 GPU V100 上 30 FPS 或更高的所有已知实时目标检测器中具有最高的准确度 56.8% AP。 YOLOv7-E6 目标检测器&#xff08;56 FPS V100&#xff0c;55.9% AP&#xff09;比基于Tr…

小孩护眼灯什么牌子的好?分享四款最好的台灯品牌

最近发现&#xff0c;在接送我家神兽上下学时&#xff0c;小朋友们会揉眼睛&#xff0c;眼睛始终没睁开的感觉&#xff0c;还有不少小学就戴上了眼镜&#xff0c;我深知戴眼镜&#xff0c;真的很麻烦&#xff0c;所以更加看重孩子的护眼工作。市面上越来越多护眼灯&#xff0c;…

Java高手速成 | 实现人物拼图游戏

拼图游戏指将一幅图片分割成若干拼块&#xff0c;并随机打乱顺序&#xff0c;当将所有拼块都放回原位置时就完成了拼图(游戏结束)。 01、游戏介绍 在游戏中&#xff0c;拼块以随机顺序排列&#xff0c;网格上有一个位置是空的。完成拼图的方法是利用这个空位置移动拼块&#xf…

服务搭建常见问题

怎么将myeclipse项目部署到tomcat服务器 https://www.laike.net/article-162-238315-0.html eclipse提示错误&#xff1a;save could not be completed Dynamic Web Module 4.0 requires Java 1.8 or newer. https://blog.csdn.net/xixihaha_coder/article/details/118345378 …