Sentinel 搭建应用层面与网关层面的流控保护

发布于:2025-08-01 ⋅ 阅读:(18) ⋅ 点赞:(0)

源码:妖精的尾巴/spring-cloud-alibaba 

Nacos 和 Sentinel Dashboard 我这里全是使用window 本地运行的,需要自行下载运行

  1. 服务层面

    • 当你在某个具体的服务上使用Sentinel时,更多的是关注该服务内部资源的保护。例如,你可以针对服务中的某些方法或者接口进行流量控制、熔断降级等操作。
    • 在这个级别上应用Sentinel,可以直接影响到服务自身的稳定性和可用性,防止由于依赖的服务不可用导致的雪崩效应。
    • 可以使用注解的AOP方式,轻松实现资源的保护

具体做法在具体某个微服务单独引入 

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

 这里解释一下,为什么是必须是静态方法,底层原理是,通过切点对象获取方法上的注解@SentinelResource,然后getBlockHandlerClass () 拿到类名,最后直接通过类名调用方法,能被类直接调用的方法那必须是静态的。

2. 网关层面

  • 在网关层(如Spring Cloud Gateway或Zuul)使用Sentinel,可以帮助你对进入系统的请求进行流量控制和管理。这通常涉及到API级别的限流、熔断以及热点参数限流等。
  • 通过集成Sentinel的Gateway Filter,你可以为每个路由或全局设置限流规则,这样就可以根据需要限制到达后端服务的请求速率。
  • 网关层使用Sentinel的优势在于它可以作为整个系统的第一道防线,保护下游服务免受突发流量的影响。

后续补充:spring-cloud-alibaba-sentinel-gateway 如何从流量第一入口全局流控或者针对某个接口做流控

父工程pom,   注意 spring-boot + spring-cloud + spring-cloud-alibaba版本适配 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ldj.springcloud</groupId>
    <artifactId>spring-cloud-alibaba</artifactId>
    <version>1.0-SNAPSHOT</version>
    <description>父工程</description>

    <packaging>pom</packaging>

    <!--组件版本管理器-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <!--子工程-->
    <modules>
        <module>common</module>
        <module>order-service</module>
        <module>stock-service</module>
        <module>user-service</module>
        <module>gateway-service</module>
    </modules>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <fastjson.version>1.2.60</fastjson.version>
        <spring.cloud.version>Hoxton.SR8</spring.cloud.version>
        <spring.cloud.alibaba.version>2.2.5.RELEASE</spring.cloud.alibaba.version>
        <jsr305.version>3.0.2</jsr305.version>
        <commons-pool2.version>2.11.1</commons-pool2.version>
    </properties>

    <!--自定义全局版本控制-->
    <dependencyManagement>
        <dependencies>
            <!--spring-cloud-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring-cloud-alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.google.code.findbugs</groupId>
                <artifactId>jsr305</artifactId>
                <version>${jsr305.version}</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>${commons-pool2.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                        <exclude>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-configuration-processor</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>spring-cloud-alibaba</artifactId>
        <groupId>com.ldj.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.ldj</groupId>
    <artifactId>gateway-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway-service</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- Nacos注册中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- Nacos配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <!-- Spring Cloud Gateway -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <!-- Spring Cloud Sentinel-Gateway -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>

        <!-- 这是核心启动器,必须添加!-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <!-- 这个依赖是动态加载规则的关键! -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-extension</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 bootstrap.properties  (配置全部迁移到Nacos)

# Nacos注册中心(9100主动注册到nacos并发送心跳)
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.discovery.namespace=23437cd8-f0c8-4570-8a52-a0db8fd25027
spring.cloud.nacos.discovery.group=DEFAULT_GROUP

# Nacos配置中心
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.namespace=23437cd8-f0c8-4570-8a52-a0db8fd25027
# 主配置文件
spring.cloud.nacos.config.extension-configs[0].data-id=application.yml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
# 流控规则文件
spring.cloud.nacos.config.extension-configs[1].data-id=fcr.yml
spring.cloud.nacos.config.extension-configs[1].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[1].refresh=true

 application.yml

server:
  port: 9100

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
        - id: user_service_route
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1
    sentinel:
      filter:
        enabled: true  # 确保启用了网关适配
      transport:
        dashboard: localhost:8033 # Sentinel控制台地址
      datasource:
        # 限流规则
        flow-rules:
          nacos:
            server-addr: localhost:8848 # 使用已存在的Nacos服务器地址
            namespace: 23437cd8-f0c8-4570-8a52-a0db8fd25027 # 命名空间
            dataId: fcr.json # 确保这个dataId与Nacos中的限流规则配置文件名一致
            groupId: DEFAULT_GROUP
            rule-type: gw-flow # 规则类型:限流(gw-flow)
            data-type: json


# 除限流规则还有下面这些规则,这里不演示了

#        # 降级规则
#        degrade-rules:
#          nacos:
#            server-addr: localhost:8848
#            namespace: 23437cd8-f0c8-4570-8a52-a0db8fd25027
#            dataId: degrade-rules.json # Nacos中存储降级规则的文件名
#            groupId: DEFAULT_GROUP
#            rule-type: degrade # 规则类型:降级(degrade)
#
#        # 系统保护规则
#        system-rules:
#          nacos:
#            server-addr: localhost:8848
#            namespace: 23437cd8-f0c8-4570-8a52-a0db8fd25027
#            dataId: system-rules.json # Nacos中存储系统保护规则的文件名
#            groupId: DEFAULT_GROUP
#            rule-type: system # 规则类型:系统(system)
#
#        # 授权规则
#        authority-rules:
#          nacos:
#            server-addr: localhost:8848
#            namespace: 23437cd8-f0c8-4570-8a52-a0db8fd25027
#            dataId: authority-rules.json # Nacos中存储授权规则的文件名
#            groupId: DEFAULT_GROUP
#            rule-type: authority # 规则类型:授权(authority)
#
#        # 热点参数限流规则
#        param-flow-rules:
#          nacos:
#            server-addr: localhost:8848
#            namespace: 23437cd8-f0c8-4570-8a52-a0db8fd25027
#            dataId: param-flow-rules.json # Nacos中存储热点参数限流规则的文件名
#            groupId: DEFAULT_GROUP
#            rule-type: param-flow # 规则类型:热点参数限流(param-flow)

 fcr.json (流控规则配置文件) 这个json 使用nacos作为存储  ,它和你在可视化控制面板配置的数据是一样的

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

配置项说明: 

[
  {
    "resource": "/get/**",           // 要限流的资源,这里是匹配所有以 /get/ 开头的URL路径
    "count": 5,                      // 限流阈值,表示每秒最多允许5个请求通过
    "grade": 1,                      // 限流阈值类型:1 表示基于QPS(每秒请求数)进行限流
    "limitApp": "default",           // 限制的应用,default 表示对所有调用方生效
    "strategy": 0,                   // 限流策略:0 表示根据调用关系(直接)进行限流
    "controlBehavior": 0             // 流控效果:0 表示快速失败(请求超过阈值时直接拒绝)
  }
]

针对maven依赖说明:

1. 单独引入spring-cloud-starter-alibaba-sentinel 用于保护普通的 Spring MVC 控制器(Controller)。

2. spring-cloud-starter-alibaba-sentinel-gateway 是专门为 Spring Cloud Gateway 设计的,它利用了 Gateway 的过滤器机制来集成 Sentinel。

踩坑!!!!!!

对于普通应用,Sentinel 的限定资源通常是 Controller 的方法名或 URL 路径。

对于 Gateway 应用,Sentinel 的资源默认是 路由 ID (Route ID),而不是你配置的 Path 路径!

也就是说,Sentinel 看到的资源是 user_service_routeapplication.yml 里定义的 id),而不是 /api/user/**

所以 这样写是不生效的

[
  {
    "resource": "/api/user/**",  // 无效写法
    "count": 1,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0,
    "controlBehavior": 0
  }
]

方式一:针对 路由 ID (Route ID) 配置规则 

[
  {
    "resource": "user_service_route", // 改为你的路由ID
    "count": 1,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0,
    "controlBehavior": 0
  }
]
方式二(推荐):针对 自定义 API 分组 (API Definition Group) 配置规则(在控制面板操作)

这种方式更灵活,可以基于路径模式(Path)来限流,更符合你的初衷。

  1. 首先,在 Sentinel 控制台配置 API 管理

    • 登录 Sentinel 控制台。
    • 找到你的 gateway-service 应用。
    • 进入 "网关流控" -> "API 管理"
    • 点击 "新增API"
    • 填写:
      • API 名称: 例如 user-api
      • 匹配规则: 添加一条规则
        • 类型PATH
        • 匹配模式/api/user/** (选择 MATCH_STR 或 ANT 模式)
    • 保存。  
  2. 然后,配置针对该 API 分组的流控规则

    • 在 "网关流控" -> "网关流控规则" 页面。
    • 点击 "新增网关流控规则"
    • 填写:
      • 资源模式API 名称 (选择你刚创建的 user-api)
      • 资源名称user-api (下拉选择)
      • Burst: 0 (或根据需要)
      • 阈值类型QPS
      • 单机阈值1
      • 流控方式直接
    • 保存。

效果:这个规则会精确地限制所有匹配 /api/user/** 路径的请求,QPS 为 1。即使你有多个路由,只要路径符合,都会被这个规则限制。

注意!!!如果这里没展示出网关流控规则数据,一般是没开启gateway 的过滤器功能

注意!!! 或者是规则类型写错

测试效果:狂按发送请求 


网站公告

今日签到

点亮在社区的每一天
去签到