本文目录导读:

接口熔断机制是一种防止服务雪崩的自我保护策略,通常通过熔断框架(如 Hystrix、Resilience4j、Sentinel)来实现。
要实现接口熔断,需要在项目中引入相应的库,并对其进行配置,以下是基于目前主流的 Resilience4j(Spring Cloud 官方推荐)和 Sentinel(阿里系常用)的两种开启方式详解。
核心原理
熔断器主要有三个状态:
- Closed(关闭):正常状态,请求通过。
- Open(打开):当失败率达到阈值,熔断器打开,直接拒绝请求(快速失败)。
- Half-Open(半开):经过一段时间(等待窗口)后,允许少量请求尝试,如果成功,则关闭熔断器;如果失败,则继续保持打开。
使用 Resilience4j(Spring Boot 项目)
这是目前 Spring Cloud 的最新生态推荐方案(替代了已停更的 Hystrix)。
引入依赖
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>最新版本</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
配置文件
在 application.yml 中定义熔断器规则(以调用 userService 接口为例):
resilience4j:
circuitbreaker:
configs:
default:
# 熔断器关闭时,请求数超过该值才开始计算失败率
sliding-window-size: 10
# 最小请求数(防止起始阶段波动大)
minimum-number-of-calls: 5
# 失败率达到 50% 时开启熔断
failure-rate-threshold: 50
# 熔断开启后,等待 10 秒尝试进入半开状态
wait-duration-in-open-state: 10s
# 半开状态下允许通过的请求数
permitted-number-of-calls-in-half-open-state: 3
# 记录异常的滑动窗口类型(基于时间或计数)
sliding-window-type: COUNT_BASED
instances:
# 自定义熔断器名称,用于绑定接口
userServiceApi:
base-config: default
业务代码中使用
在需要保护的 Service 或 Controller 方法上添加 @CircuitBreaker 注解:
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
@Service
public class UserService {
// name 对应配置文件中的熔断器实例名称
// fallbackMethod 指定熔断后调用的备用方法
@CircuitBreaker(name = "userServiceApi", fallbackMethod = "getUserFallback")
public User getUserById(Long id) {
// 这里调用远程接口(可能失败)
return restTemplate.getForObject("http://remote-service/user/" + id, User.class);
}
// 备用方法:返回默认值或兜底数据(注意参数和返回值要匹配)
public User getUserFallback(Long id, Throwable t) {
return new User("默认用户");
}
}
使用 Sentinel(阿里系,功能更强)
Sentinel 除了熔断,还支持限流、系统保护等,配置方式分为控制台和代码两种。
引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置文件
spring:
cloud:
sentinel:
enabled: true
transport:
# 连接 Sentinel 控制台(可选,简化情况下可以不用)
dashboard: localhost:8080
# 熔断规则可以写死在代码中,也可以通过控制台推送
代码配置熔断规则(核心方式)
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
@Component
public class SentinelConfig {
@PostConstruct
public void initDegradeRule() {
// 创建熔断规则列表
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
// 资源名称(必须与要保护的接口名一致)
rule.setResource("getUserById");
// 熔断策略:1 表示平均响应时间(RT),0 表示异常比例
rule.setGrade(0);
// 异常比例阈值:0.5 表示 50%
rule.setCount(0.5);
// 触发熔断的最小请求数
rule.setMinRequestAmount(5);
// 统计时长(单位:毫秒)
rule.setStatIntervalMs(1000);
// 熔断后恢复的时间(秒)
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
业务代码中使用
import com.alibaba.csp.sentinel.annotation.SentinelResource;
@Service
public class UserService {
// value 必须与上面规则的 resource 一致
@SentinelResource(value = "getUserById", fallback = "getUserFallback")
public User getUserById(Long id) {
// 业务逻辑
return remoteClient.getUser(id);
}
public User getUserFallback(Long id, Throwable e) {
return new User("降级用户");
}
}
手动实现一个简单的熔断器(不依赖框架)
如果项目过于老旧或不想引入外部框架,可以基于状态机手动实现(原理参考):
@Component
public class SimpleCircuitBreaker {
private AtomicInteger failureCount = new AtomicInteger(0);
private AtomicInteger successCount = new AtomicInteger(0);
private volatile CircuitBreakerState state = CircuitBreakerState.CLOSED;
private long lastFailureTime;
private final int threshold = 5; // 失败次数阈值
private final long timeout = 5000; // 半开恢复窗口(毫秒)
public boolean allowRequest() {
switch (state) {
case OPEN:
// 检查时间窗口是否已到,尝试半开
if (System.currentTimeMillis() - lastFailureTime > timeout) {
state = CircuitBreakerState.HALF_OPEN;
return true;
}
return false;
case HALF_OPEN:
return true;
default:
return true;
}
}
public void recordSuccess() {
if (state == CircuitBreakerState.HALF_OPEN) {
// 半开后成功,则关闭熔断器
state = CircuitBreakerState.CLOSED;
failureCount.set(0);
successCount.set(0);
} else if (state == CircuitBreakerState.CLOSED) {
// 按需实现滑动窗口
}
}
public void recordFailure() {
if (state == CircuitBreakerState.HALF_OPEN) {
state = CircuitBreakerState.OPEN;
lastFailureTime = System.currentTimeMillis();
} else if (state == CircuitBreakerState.CLOSED) {
failureCount.incrementAndGet();
if (failureCount.get() >= threshold) {
state = CircuitBreakerState.OPEN;
lastFailureTime = System.currentTimeMillis();
}
}
}
enum CircuitBreakerState {
OPEN, HALF_OPEN, CLOSED
}
}
使用时,在调用接口前后调用 allowRequest、recordSuccess、recordFailure 即可。
如何选择?
| 场景 | 推荐工具 | 理由 |
|---|---|---|
| Spring Boot / Cloud 新项目 | Resilience4j | 轻量、无外部依赖、官方维护 |
| 需要强大的限流、熔断、监控 | Sentinel | 控制台可视化、动态规则、支持热点参数 |
| 旧项目、不想加依赖 | 手动实现 | 高度定制、简单场景够用 |
| 已经用 Feign 调用接口 | Resilience4j + Feign | 配合 @FeignClient 的 fallback 属性,配置更简单 |
关键操作步骤通用逻辑:
- 引入框架依赖。
- 定义熔断阈值(失败比例、响应时间、错误数量)。
- 定义熔断恢复策略(等待多久尝试恢复)。
- 在业务方法上标注注解或配置资源点。
- 提供降级方法(fallback),作为熔断后的备用逻辑。
标签: Sentinel
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。