微服务架构下,服务间调用失败是常态而非异常。网络抖动、下游过载、依赖超时都可能引发级联故障。熔断器(Circuit Breaker)是防止故障扩散的核心组件。这篇文章用Resilience4j在Spring Boot项目中实现熔断降级,从配置到生产踩坑全覆盖。
Resilience4j vs Hystrix:为什么迁移
Hystrix已停止维护,Spring Cloud 2021+默认集成Resilience4j。核心差异:
- Resilience4j基于函数式编程,以装饰器模式包装调用,比Hystrix的继承体系轻量
- 熔断状态机逻辑一致(Closed→Open→HalfOpen→Closed),但Resilience4j的滑动窗口实现更精细
- Resilience4j原生支持响应式(Reactor/RxJava),Hystrix对响应式支持差
依赖引入与基础配置
Maven依赖:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-circuitbreaker</artifactId>
<version>2.2.0</version>
</dependency>
application.yml核心配置:
resilience4j:
circuitbreaker:
configs:
default:
sliding-window-type: COUNT_BASED
sliding-window-size: 100
failure-rate-threshold: 50
slow-call-rate-threshold: 80
slow-call-duration-threshold: 3s
permitted-number-of-calls-in-half-open-state: 10
minimum-number-of-calls: 20
wait-duration-in-open-state: 30s
instances:
orderService:
base-config: default
failure-rate-threshold: 60
paymentService:
base-config: default
slow-call-duration-threshold: 5s
参数解读:
sliding-window-size: 100:统计最近100次调用failure-rate-threshold: 50:失败率超过50%触发熔断minimum-number-of-calls: 20:至少20次调用后才开始计算失败率,避免样本太少误判wait-duration-in-open-state: 30s:熔断30秒后进入半开状态
熔断+降级的代码实现
用注解方式最简洁:
@Service
public class OrderServiceClient {
@CircuitBreaker(name = "orderService", fallbackMethod = "getOrderFallback")
@TimeLimiter(name = "orderService")
public CompletableFuture<Order> getOrder(Long orderId) {
return CompletableFuture.supplyAsync(() ->
restTemplate.getForObject(
"http://order-service/api/orders/" + orderId,
Order.class
)
);
}
private CompletableFuture<Order> getOrderFallback(Long orderId, Exception e) {
// 降级逻辑:返回缓存或默认值
Order cached = orderCache.get(orderId);
if (cached != null) {
return CompletableFuture.completedFuture(cached);
}
Order defaultOrder = new Order();
defaultOrder.setId(orderId);
defaultOrder.setStatus("SERVICE_UNAVAILABLE");
return CompletableFuture.completedFuture(defaultOrder);
}
}
注意fallback方法签名必须和原方法参数一致,末尾追加Throwable参数。
限流配置:防止下游被打崩
熔断保护自己不被下游拖垮,限流保护下游不被自己打崩:
resilience4j:
ratelimiter:
configs:
default:
limit-for-period: 100
limit-refresh-period: 1s
timeout-duration: 5s
instances:
orderService:
base-config: default
limit-for-period: 50
代码中使用:
@RateLimiter(name = "orderService", fallbackMethod = "rateLimitFallback")
public Order createOrder(OrderRequest request) {
return orderClient.create(request);
}
重试策略:可恢复错误的自动处理
resilience4j:
retry:
configs:
default:
max-attempts: 3
wait-duration: 500ms
retry-exceptions:
- java.io.IOException
- java.util.concurrent.TimeoutException
ignore-exceptions:
- com.example.BusinessException
instances:
orderService:
base-config: default
max-attempts: 2
@Retry(name = "orderService", fallbackMethod = "retryFallback")
@CircuitBreaker(name = "orderService")
public Order queryOrder(Long id) {
return orderClient.query(id);
}
监控指标暴露
Resilience4j自动注册Micrometer指标,接入Prometheus:
management:
endpoints:
web:
exposure:
include: health, prometheus
metrics:
export:
prometheus:
enabled: true
resilience4j:
circuitbreaker:
configs:
default:
register-health-indicator: true
关键监控指标:
resilience4j_circuitbreaker_state:熔断器状态(0=CLOSED, 1=OPEN, 2=HALF_OPEN)resilience4j_circuitbreaker_failure_rate:当前失败率resilience4j_circuitbreaker_slow_call_rate:慢调用比例
告警规则示例:
# 熔断器打开超过2分钟
resilience4j_circuitbreaker_state{instance="orderService"} == 1
# 失败率超过阈值
resilience4j_circuitbreaker_failure_rate{instance="orderService"} > 0.4
生产环境踩坑记录
Q: 熔断器半天不恢复?
检查wait-duration-in-open-state和permitted-number-of-calls-in-half-open-state。半开状态下放行的请求如果全部失败,会立即回到OPEN状态,导致看起来一直没恢复。建议半开状态的放行数设为10-20,确保有足够的探测样本。
Q: fallback没生效,异常直接抛出?
常见原因:fallback方法签名不匹配。参数类型和数量必须与原方法一致,最后一个参数是Exception(或其子类)。另外,如果是checked exception,需要在fallback方法上声明throws。
Q: 并发场景下限流不准?
Resilience4j的RateLimiter基于Semaphore实现,分布式场景下每个实例各自限流。如果需要全局限流,用Redis + Lua脚本或Sentinel集群限流。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springboot-wei-fu-wu-rong-duan-jiang-ji-shi-zhan/