熔断与降级
问题
什么是熔断和降级?Sentinel 与 Resilience4j 有什么区别?
答案
为什么需要熔断和降级
微服务之间存在调用链,如果某个服务出现故障,可能引起雪崩效应——一个服务超时导致调用方线程被阻塞,进而影响上游所有服务。
| 概念 | 说明 |
|---|---|
| 熔断 | 断路器模式,当下游故障率超过阈值时直接快速失败,不再发起调用 |
| 降级 | 服务不可用时返回兜底响应(缓存数据、默认值、友好提示) |
| 限流 | 控制进入服务的请求速率(令牌桶、滑动窗口) |
断路器状态机
Sentinel(阿里开源)
Sentinel 是面向分布式服务架构的流量控制组件:
Sentinel 使用
@RestController
public class OrderController {
// 资源名、降级方法、异常处理
@SentinelResource(value = "createOrder",
blockHandler = "createOrderBlock",
fallback = "createOrderFallback")
@PostMapping("/api/orders")
public Order createOrder(@RequestBody OrderDTO dto) {
return orderService.create(dto);
}
// 限流/熔断触发时的处理(BlockException)
public Order createOrderBlock(OrderDTO dto, BlockException ex) {
return new Order("系统繁忙,请稍后重试");
}
// 业务异常降级
public Order createOrderFallback(OrderDTO dto, Throwable ex) {
return new Order("服务暂不可用");
}
}
Sentinel 配置方式(控制台或代码):
application.yml — Sentinel 配置
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel 控制台地址
port: 8719
eager: true # 饥饿加载,启动时注册
Sentinel 核心功能
| 功能 | 说明 |
|---|---|
| 流量控制 | QPS 限流、线程数限流、关联限流、链路限流 |
| 熔断降级 | 慢调用比例、异常比例、异常数 |
| 热点参数 | 对特定参数值限流(如商品 ID) |
| 系统保护 | CPU、负载、入口 QPS |
| 集群限流 | Token Server 统一限流 |
Resilience4j
Resilience4j 是轻量级容错库,基于函数式编程风格:
Resilience4j 使用
@Service
public class OrderService {
// 熔断器
@CircuitBreaker(name = "orderService", fallbackMethod = "fallback")
// 限流
@RateLimiter(name = "orderService")
// 重试
@Retry(name = "orderService", fallbackMethod = "fallback")
// 超时
@TimeLimiter(name = "orderService")
public CompletableFuture<Order> createOrder(OrderDTO dto) {
return CompletableFuture.supplyAsync(() -> remoteCall(dto));
}
public CompletableFuture<Order> fallback(OrderDTO dto, Throwable ex) {
return CompletableFuture.completedFuture(new Order("降级响应"));
}
}
application.yml — Resilience4j 配置
resilience4j:
circuitbreaker:
instances:
orderService:
sliding-window-size: 10 # 滑动窗口大小
failure-rate-threshold: 50 # 失败率阈值 50%
wait-duration-in-open-state: 10s # Open 状态等待时间
permitted-number-of-calls-in-half-open-state: 3 # 半开放行数
ratelimiter:
instances:
orderService:
limit-for-period: 100 # 每个周期允许的请求数
limit-refresh-period: 1s # 刷新周期
retry:
instances:
orderService:
max-attempts: 3 # 最大重试次数
wait-duration: 500ms # 重试间隔
Sentinel vs Resilience4j
| 对比 | Sentinel | Resilience4j |
|---|---|---|
| 出品 | 阿里巴巴 | 社区开源 |
| 控制台 | 实时控制台(动态规则推送) | 无(需集成 Prometheus) |
| 规则配置 | 运行时动态修改 | 配置文件或代码 |
| 限流算法 | 滑动窗口、令牌桶 | 令牌桶 |
| 热点参数 | 支持 | 不支持 |
| 集群限流 | 支持 | 不支持 |
| 编程模型 | 注解 + 控制台 | 函数式 + 注解 |
| 适用场景 | 大规模微服务、需要控制台 | 轻量级、Spring Boot 新项目 |
常见面试问题
Q1: 什么是服务雪崩?如何防止?
答案:
一个服务超时/故障导致调用方的线程阻塞,进而耗尽线程池,影响上游所有服务,最终整个调用链瘫痪。防止措施:
- 熔断:检测到故障率超阈值直接快速失败
- 限流:控制请求速率,保护服务不被压垮
- 降级:返回兜底结果,避免级联失败
- 超时控制:设置合理的超时时间,避免线程长时间阻塞
- 线程隔离:不同服务使用独立线程池
Q2: 断路器的三种状态?
答案:
- Closed(关闭):正常状态,请求正常通过,同时统计失败率
- Open(打开):失败率超过阈值,直接拒绝请求并返回降级结果
- Half-Open(半开):经过等待时间后,放行少量请求探测下游是否恢复
Q3: Sentinel 和 Hystrix 的区别?
答案:
Hystrix 采用线程池隔离(每个服务一个线程池),资源消耗大,已停止维护。Sentinel 采用信号量隔离,基于滑动窗口统计,资源开销小,提供实时控制台,支持热点参数限流和集群限流。Sentinel 是 Hystrix 的替代方案。
Q4: 限流和熔断的区别?
答案:
- 限流:控制入口流量,防止服务被过多请求压垮(保护自己)
- 熔断:检测下游服务的健康状态,故障时快速失败(保护调用链)
限流是事前预防,熔断是事后止损。
相关链接
- Sentinel 官方文档
- Resilience4j 官方文档
- 注册中心 - 服务发现
- 服务网关 - 网关层限流