SpringBoot 限流与熔断降级实战

知识库
知识库文档
/tech-stacks/sentinel/examples/SpringBoot 限流与熔断降级实战.md

文档

目标

演示 Spring Boot 应用接入 Sentinel,实现 QPS 限流 + 熔断降级 + 自定义 fallback,通过控制台实时下发规则。

完整代码

1. pom.xml

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2023.0.1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. application.yml

server:
  port: 8080
spring:
  application:
    name: sentinel-demo
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719
      eager: true
      # 规则持久化(Nacos)
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: ${spring.application.name}-flow-rules
            group-id: DEFAULT_GROUP
            data-type: json
            rule-type: flow

3. 控制器(限流 + 熔断)

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    // ===== QPS 限流 =====
    @GetMapping("/hello")
    @SentinelResource(value = "hello", blockHandler = "helloBlock")
    public String hello() {
        return "Hello, Sentinel!";
    }

    public String helloBlock(BlockException ex) {
        return "Too many requests! Please try later. " + ex.getClass().getSimpleName();
    }

    // ===== 热点参数限流 =====
    @GetMapping("/item/{id}")
    @SentinelResource(value = "getItem", blockHandler = "itemBlock")
    public String getItem(@PathVariable Long id) {
        return "Item detail for ID: " + id;
    }

    public String itemBlock(@PathVariable Long id, BlockException ex) {
        return "Item " + id + " is hot! Rate limited.";
    }

    // ===== 熔断降级 =====
    @GetMapping("/risky")
    @SentinelResource(value = "risky", fallback = "riskyFallback")
    public String risky() {
        // 模拟 >50% 异常率触发熔断
        if (System.currentTimeMillis() % 3 == 0) {
            throw new RuntimeException("Simulated error");
        }
        return "OK from risky API";
    }

    public String riskyFallback(Throwable t) {
        return "Fallback: Service degraded. " + t.getMessage();
    }

    // ===== 系统自适应保护 =====
    @GetMapping("/heavy")
    public String heavy() {
        // 模拟 CPU 密集型操作
        for (int i = 0; i < 1000000; i++) {
            Math.sqrt(i);
        }
        return "Heavy computation done!";
    }
}

4. 流控规则定义(Nacos 持久化)

[
  {
    "resource": "hello",
    "grade": 1,
    "count": 5,
    "strategy": 0,
    "controlBehavior": 0
  },
  {
    "resource": "getItem",
    "grade": 1,
    "count": 10,
    "strategy": 0,
    "controlBehavior": 1,
    "paramIdx": 0
  }
]

运行步骤

# 1. 启动 Sentinel Dashboard
java -jar sentinel-dashboard-1.8.7.jar

# 2. 启动应用
mvn spring-boot:run

# 3. 触发请求(让应用出现在 Dashboard)
curl http://localhost:8080/hello

# 4. 打开 Sentinel Dashboard → 簇点链路
# 设置 hello 资源的 QPS 限流为 5

# 5. 压测验证限流
ab -n 100 -c 10 http://localhost:8080/hello
# 部分请求返回: Too many requests! Please try later. FlowException

# 6. 验证热点参数限流
for i in {1..20}; do curl http://localhost:8080/item/42; done
# 热点 key=42 被限流

# 7. 验证熔断降级
# 在 Dashboard 配置 risky 资源:
#   熔断策略: 异常比例
#   比例阈值: 0.5
#   最小请求数: 5
#   统计时长: 1000ms
#   熔断时长: 10s
for i in {1..20}; do curl http://localhost:8080/risky; done

预期输出

# 限流后
Too many requests! Please try later. FlowException

# 热点参数限流
Item 42 is hot! Rate limited.

# 熔断降级
Fallback: Service degraded. RuntimeException: Simulated error
# 连续触发后直接快速失败(不再调用原方法)

关键点

  • blockHandler 处理限流/熔断异常(BlockException)
  • fallback 处理业务异常(Throwable)
  • Sentinel Dashboard 实时推送规则,无需重启
  • 熔断半开状态:一段时间后尝试放行少量请求探测恢复

信息

路径
/tech-stacks/sentinel/examples/SpringBoot 限流与熔断降级实战.md
更新时间
2026/5/31