文档
目标
演示 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 实时推送规则,无需重启
- 熔断半开状态:一段时间后尝试放行少量请求探测恢复