Spring Cloud 熔断器详解:Sentinel 与 Resilience4j ⭐⭐⭐

面试题:什么是熔断器?如何实现熔断降级?

核心回答

熔断器是一种保护机制,当下游服务出现故障时,自动切断请求,防止故障蔓延。熔断器通过状态机实现 Closed(关闭)、Open(打开)、Half Open(半开)三种状态的转换,结合限流、降级策略,保障系统的高可用。

一、熔断器原理

1.1 为什么需要熔断器?

┌─────────────────────────────────────────────────────────────┐
│                     雪崩效应                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  正常情况:                                                   │
│                                                             │
│  服务 A → 服务 B → 服务 C                                    │
│    ↓        ↓        ↓                                      │
│   10ms    20ms     15ms                                     │
│                                                             │
│  服务 C 故障:                                               │
│                                                             │
│  服务 A → 服务 B → 服务 C(故障)                             │
│    ↓        ↓        ↓                                      │
│  等待...  等待...   超时                                     │
│    ↓        ↓                                               │
│  线程阻塞  线程阻塞                                          │
│    ↓        ↓                                               │
│  资源耗尽  资源耗尽                                          │
│    ↓                                                        │
│  整个系统崩溃!                                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                    熔断器保护                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  服务 A → 服务 B → [熔断器] → 服务 C                          │
│                      ↓                                      │
│                检测到故障                                    │
│                      ↓                                      │
│                 打开熔断                                     │
│                      ↓                                      │
│            快速返回降级响应                                  │
│                      ↓                                      │
│             保护系统稳定                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 熔断器三状态模型

┌─────────────────────────────────────────────────────────────┐
│                   熔断器状态机                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│                     请求成功                                 │
│           ┌────────────────────────────┐                   │
│           │                            │                   │
│           ▼                            │                   │
│   ┌───────────────┐                    │                   │
│   │               │                    │                   │
│   │    Closed     │                    │                   │
│   │   (关闭状态)   │                    │                   │
│   │               │                    │                   │
│   │  所有请求正常  │                    │                   │
│   │  通过执行      │                    │                   │
│   │               │                    │                   │
│   └───────┬───────┘                    │                   │
│           │                            │                   │
│           │ 失败率 > 阈值              │                   │
│           │ (如 50%)                   │                   │
│           ▼                            │                   │
│   ┌───────────────┐                    │                   │
│   │               │                    │                   │
│   │     Open      │                    │                   │
│   │   (打开状态)   │                    │                   │
│   │               │                    │                   │
│   │  所有请求直接  │                    │                   │
│   │  返回降级响应  │                    │                   │
│   │               │                    │                   │
│   └───────┬───────┘                    │                   │
│           │                            │                   │
│           │ 等待时间到                  │                   │
│           │ (如 30秒)                  │                   │
│           ▼                            │                   │
│   ┌───────────────┐                    │                   │
│   │               │                    │                   │
│   │  Half Open    │                    │                   │
│   │  (半开状态)    │                    │                   │
│   │               │                    │                   │
│   │  放行部分请求  │────────────────────┘                   │
│   │  探测服务恢复  │                                        │
│   │               │  探测失败                              │
│   └───────────────┘─────────────────────────┐              │
│                                             │              │
│                                             ▼              │
│                                        返回 Open           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.3 熔断器核心参数

┌─────────────────────────────────────────────────────────────┐
│                    熔断器核心参数                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  统计窗口参数:                                               │
│  ├── slidingWindowSize:滑动窗口大小(请求数/时间)          │
│  ├── minimumNumberOfCalls:最小调用次数                      │
│  └── failureRateThreshold:失败率阈值(如 50%)             │
│                                                             │
│  状态转换参数:                                               │
│  ├── waitDurationInOpenState:Open 状态等待时间             │
│  ├── permittedNumberOfCallsInHalfOpenState:半开状态允许请求数│
│  └── slowCallDurationThreshold:慢调用时间阈值              │
│                                                             │
│  降级参数:                                                   │
│  ├── fallbackMethod:降级方法                               │
│  └── fallbackResult:降级返回值                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

二、Sentinel 详解

2.1 Sentinel 简介

Sentinel 是阿里巴巴开源的流量控制和熔断降级组件,具有以下特点:

2.2 Sentinel 核心概念

┌─────────────────────────────────────────────────────────────┐
│                   Sentinel 核心概念                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  资源 (Resource):                                           │
│  ├── 可以是方法、代码块、接口                                 │
│  └── Sentinel 保护的基本单位                                 │
│                                                             │
│  规则 (Rule):                                               │
│  ├── 流控规则:FlowRule                                     │
│  ├── 降级规则:DegradeRule                                  │
│  ├── 系统规则:SystemRule                                   │
│  ├── 热点规则:ParamFlowRule                                │
│  └── 授权规则:AuthorityRule                                │
│                                                             │
│  Entry:                                                     │
│  ├── 资源访问的入口                                         │
│  └── SphU.entry("resourceName")                             │
│                                                             │
│  Context:                                                   │
│  ├── 上下文环境                                              │
│  └── 每次资源调用创建一个 Context                            │
│                                                             │
│  ProcessorSlot:                                             │
│  ├── 责任链模式的处理槽                                      │
│  ├── NodeSelectorSlot:选择节点                              │
│  ├── ClusterBuilderSlot:构建集群节点                       │
│  ├── FlowSlot:流控检查                                     │
│  ├── DegradeSlot:熔断检查                                  │
│  └── StatisticSlot:统计数据                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.3 滑动时间窗口算法

┌─────────────────────────────────────────────────────────────┐
│                  滑动时间窗口算法                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  时间轴:                                                    │
│  ──────────────────────────────────────────────→            │
│                                                             │
│  窗口大小:1秒,分为 2 个样本窗口                             │
│                                                             │
│  ┌────────────────┬────────────────┐                       │
│  │  Window 0      │  Window 1      │                       │
│  │  (0-500ms)     │  (500-1000ms)  │                       │
│  │  请求数: 10    │  请求数: 15    │                       │
│  └────────────────┴────────────────┘                       │
│        ↑              ↑                                     │
│        │              │                                     │
│       当前时间 (750ms)                                       │
│                                                             │
│  当前窗口统计:                                              │
│  Window 0 已过期,Window 1 是当前窗口                        │
│  统计结果:15 (当前) + 10 (重置前的旧数据)                    │
│                                                             │
│  窗口滑动:                                                  │
│  时间流逝,窗口向右滑动,旧窗口数据被重置                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.4 Sentinel 规则详解

2.4.1 流控规则(FlowRule)

// 流控规则配置
FlowRule rule = new FlowRule();
rule.setResource("getUser");              // 资源名
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 限流阈值类型
rule.setCount(100);                       // 阈值:100 QPS
rule.setStrategy(RuleConstant.STRATEGY_DIRECT); // 流控策略
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); // 流控效果
FlowRuleManager.loadRules(Collections.singletonList(rule));
# Spring Cloud Alibaba 配置
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: sentinel-flow-rules
            rule-type: flow

流控策略

策略 说明
DIRECT 直接拒绝(默认)
ASSOCIATE 关联限流(关联资源达到阈值时限流)
CHAIN 链路限流(只记录从入口资源进来的流量)

流控效果

效果 说明
DEFAULT 直接拒绝,抛出 FlowException
WARM_UP 预热模式,从阈值/3 逐渐增加到阈值
RATE_LIMITER 匀速排队,请求在队列中等待
WARM_UP_RATE_LIMITER 预热 + 匀速排队

2.4.2 降级规则(DegradeRule)

// 降级规则配置
DegradeRule rule = new DegradeRule("getUser");
rule.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType()); // 熔断策略
rule.setCount(0.5);                 // 阈值:50% 错误率
rule.setTimeWindow(30);             // 熔断时长:30秒
rule.setMinRequestAmount(10);       // 最小请求数
rule.setStatIntervalMs(10000);      // 统计时长:10秒
DegradeRuleManager.loadRules(Collections.singletonList(rule));

熔断策略

策略 说明 阈值
ERROR_RATIO 错误比例 0.0 - 1.0
ERROR_COUNT 错误数 整数
SLOW_REQUEST_RATIO 慢调用比例 0.0 - 1.0

2.4.3 系统规则(SystemRule)

// 系统规则配置
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(3.0);     // 系统 Load 阈值
rule.setHighestCpuUsage(0.8);       // CPU 使用率阈值
rule.setAvgRt(1000);                // 平均响应时间阈值
rule.setMaxThread(500);             // 最大并发线程数
rule.setQps(1000);                  // 系统 QPS 阈值
SystemRuleManager.loadRules(Collections.singletonList(rule));

2.4.4 热点规则(ParamFlowRule)

// 热点参数限流
ParamFlowRule rule = new ParamFlowRule();
rule.setResource("getUser");
rule.setCount(10);                  // 每秒最多 10 次
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setParamIdx(0);                // 第一个参数

// 特定参数例外
ParamFlowItem item = new ParamFlowItem();
item.setObject("VIP_USER");
item.setCount(100);                 // VIP 用户 100 次
rule.setParamFlowItemList(Collections.singletonList(item));

ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
// 使用示例
@GetMapping("/user/{id}")
@SentinelResource(value = "getUser", blockHandler = "handleBlock")
public User getUser(@PathVariable String id) {
    return userService.findById(id);
}

// 热点参数限流:对 id 参数限流
// 普通 id:10 QPS
// VIP_USER:100 QPS

2.4.5 授权规则(AuthorityRule)

// 授权规则配置
AuthorityRule rule = new AuthorityRule();
rule.setResource("protectedApi");
rule.setStrategy(RuleConstant.AUTHORITY_WHITE); // 白名单模式
rule.setLimitApp("appA,appB");       // 允许的应用
AuthorityRuleManager.loadRules(Collections.singletonList(rule));

2.5 Sentinel 注解使用

@RestController
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/user/{id}")
    @SentinelResource(
        value = "getUser",                    // 资源名
        blockHandler = "getUserBlockHandler", // 限流降级处理
        blockHandlerClass = UserBlockHandler.class, // 限流处理类
        fallback = "getUserFallback",         // 异常降级处理
        fallbackClass = UserFallback.class,   // 降级处理类
        exceptionsToIgnore = {IllegalArgumentException.class} // 忽略的异常
    )
    public Result<User> getUser(@PathVariable Long id) {
        return Result.success(userService.findById(id));
    }
    
    // 限流/熔断降级方法(必须与原方法参数一致 + BlockException)
    public Result<User> getUserBlockHandler(Long id, BlockException ex) {
        return Result.error("系统繁忙,请稍后再试");
    }
    
    // 异常降级方法(必须与原方法参数一致 + Throwable)
    public Result<User> getUserFallback(Long id, Throwable ex) {
        return Result.error("服务异常: " + ex.getMessage());
    }
}

2.6 Sentinel 控制台

# 启动 Sentinel Dashboard
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
# 应用配置
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080  # 控制台地址
        port: 8719                 # 与控制台通信的端口
      eager: true                  # 应用启动时立即初始化
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: ${spring.application.name}-flow-rules
            group-id: SENTINEL_GROUP
            rule-type: flow

2.7 Sentinel 集成 Spring Cloud

<!-- 依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
# application.yml
spring:
  application:
    name: user-service
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719
      eager: true
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: ${spring.application.name}-flow-rules
            rule-type: flow
        degrade:
          nacos:
            server-addr: localhost:8848
            data-id: ${spring.application.name}-degrade-rules
            rule-type: degrade

# OpenFeign 集成 Sentinel
feign:
  sentinel:
    enabled: true
// OpenFeign 降级配置
@FeignClient(name = "order-service", fallbackFactory = OrderServiceFallbackFactory.class)
public interface OrderServiceClient {
    
    @GetMapping("/order/{userId}")
    Result<List<Order>> getOrders(@PathVariable Long userId);
}

@Component
public class OrderServiceFallbackFactory implements FallbackFactory<OrderServiceClient> {
    
    @Override
    public OrderServiceClient create(Throwable cause) {
        return new OrderServiceClient() {
            @Override
            public Result<List<Order>> getOrders(Long userId) {
                return Result.error("订单服务不可用,请稍后再试");
            }
        };
    }
}

2.8 Sentinel 核心源码

// SphU.entry() 核心流程
public static Entry entry(String name) throws BlockException {
    return Env.sph.entry(name, EntryType.OUT, 1, OBJECTS0);
}

// CtSph.entry()
public Entry entry(String name, EntryType type, int count, Object... args) throws BlockException {
    // 创建资源包装器
    StringResourceWrapper resource = new StringResourceWrapper(name, type);
    return entry(resource, count, args);
}

// 核心处理链
private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args) throws BlockException {
    // 创建 Context
    Context context = ContextUtil.getContext();
    
    // 创建 ProcessorSlotChain
    ProcessorSlot<Object> chain = lookProcessChain(resourceWrapper);
    
    // 创建 Entry
    Entry e = new CtEntry(resourceWrapper, chain, context);
    
    // 执行处理链
    chain.entry(context, resourceWrapper, null, count, prioritized, args);
    
    return e;
}

// ProcessorSlotChain 结构
public class DefaultProcessorSlotChain extends ProcessorSlotChain {
    
    AbstractLinkedProcessorSlot<?> first = new AbstractLinkedProcessorSlot<Object>() {};
    AbstractLinkedProcessorSlot<?> end = first;
    
    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, Object param, int count, boolean prioritized, Object... args) throws Throwable {
        // 依次执行各个 Slot
        first.transformEntry(context, resourceWrapper, param, count, prioritized, args);
    }
}

// Slot 执行顺序
// NodeSelectorSlot → ClusterBuilderSlot → LogSlot → StatisticSlot → 
// AuthoritySlot → SystemSlot → FlowSlot → DegradeSlot

三、Resilience4j 详解

3.1 Resilience4j 简介

Resilience4j 是一个轻量级的容错库,灵感来自 Netflix Hystrix,但设计更加轻量和模块化。

核心模块

模块 功能
CircuitBreaker 熔断器
RateLimiter 限流器
Retry 重试
Bulkhead 舱壁隔离
Cache 缓存
Timelimiter 超时控制

3.2 Resilience4j 熔断器

3.2.1 配置方式

# application.yml
resilience4j:
  circuitbreaker:
    configs:
      default:
        slidingWindowType: COUNT_BASED        # 滑动窗口类型
        slidingWindowSize: 10                 # 滑动窗口大小
        minimumNumberOfCalls: 5               # 最小调用次数
        failureRateThreshold: 50              # 失败率阈值
        waitDurationInOpenState: 10s          # Open 状态等待时间
        permittedNumberOfCallsInHalfOpenState: 3  # 半开状态允许请求数
        slowCallDurationThreshold: 2s         # 慢调用时间阈值
        slowCallRateThreshold: 50             # 慢调用率阈值
        automaticTransitionFromOpenToHalfOpenEnabled: true  # 自动转半开
    instances:
      userService:
        baseConfig: default
      orderService:
        slidingWindowSize: 20
        failureRateThreshold: 30

3.2.2 注解使用

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    // 熔断器
    @CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")
    public User getUser(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new UserNotFoundException("用户不存在"));
    }
    
    // 降级方法(参数需与原方法一致 + Exception)
    private User getUserFallback(Long id, Exception ex) {
        log.warn("获取用户失败,使用降级数据: {}", id);
        return User.builder()
            .id(id)
            .name("默认用户")
            .build();
    }
}

3.2.3 编程式使用

@Service
public class UserService {
    
    private final CircuitBreaker circuitBreaker;
    
    public UserService(CircuitBreakerRegistry registry) {
        this.circuitBreaker = registry.circuitBreaker("userService");
    }
    
    public User getUser(Long id) {
        return circuitBreaker.executeSupplier(() -> {
            return userRepository.findById(id)
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        });
    }
    
    // 带降级的调用
    public User getUserWithFallback(Long id) {
        Supplier<User> supplier = CircuitBreaker.decorateSupplier(
            circuitBreaker, 
            () -> userRepository.findById(id).orElse(null)
        );
        
        return Try.ofSupplier(supplier)
            .recover(throwable -> User.builder().id(id).name("默认用户").build())
            .get();
    }
}

3.3 Resilience4j 限流器

# application.yml
resilience4j:
  ratelimiter:
    configs:
      default:
        limitForPeriod: 10            # 每个周期允许的请求数
        limitRefreshPeriod: 1s        # 刷新周期
        timeoutDuration: 0            # 等待获取许可的超时时间
    instances:
      userService:
        baseConfig: default
@Service
public class UserService {
    
    // 限流器
    @RateLimiter(name = "userService", fallbackMethod = "rateLimitFallback")
    public User getUser(Long id) {
        return userRepository.findById(id).orElse(null);
    }
    
    private User rateLimitFallback(Long id, RequestNotPermitted ex) {
        throw new RuntimeException("请求过于频繁,请稍后再试");
    }
}

3.4 Resilience4j 重试

# application.yml
resilience4j:
  retry:
    configs:
      default:
        maxAttempts: 3                # 最大尝试次数(包括首次)
        waitDuration: 500ms           # 重试等待时间
        exponentialBackoffMultiplier: 2  # 指数退避因子
        retryExceptions:              # 触发重试的异常
          - java.io.IOException
          - java.net.SocketTimeoutException
        ignoreExceptions:             # 不重试的异常
          - java.lang.IllegalArgumentException
    instances:
      userService:
        baseConfig: default
@Service
public class UserService {
    
    @Retry(name = "userService", fallbackMethod = "getUserFallback")
    public User getUser(Long id) {
        return callRemoteService(id);
    }
    
    private User getUserFallback(Long id, Exception ex) {
        return User.builder().id(id).name("默认用户").build();
    }
}

3.5 Resilience4j 舱壁隔离

# application.yml
resilience4j:
  bulkhead:
    configs:
      default:
        maxConcurrentCalls: 25        # 最大并发数
        maxWaitDuration: 0            # 等待获取许可的时间
    instances:
      userService:
        baseConfig: default

  # 信号量隔离
  thread-pool-bulkhead:
    configs:
      default:
        maxThreadPoolSize: 10         # 最大线程数
        coreThreadPoolSize: 5         # 核心线程数
        queueCapacity: 20             # 队列容量
        keepAliveDuration: 20s        # 空闲线程存活时间
@Service
public class UserService {
    
    // 舱壁隔离
    @Bulkhead(name = "userService", fallbackMethod = "bulkheadFallback")
    public User getUser(Long id) {
        return userRepository.findById(id).orElse(null);
    }
    
    private User bulkheadFallback(Long id, BulkheadFullException ex) {
        throw new RuntimeException("系统繁忙,请稍后再试");
    }
    
    // 线程池隔离
    @Bulkhead(name = "userService", type = Bulkhead.Type.THREADPOOL)
    public CompletableFuture<User> getUserAsync(Long id) {
        return CompletableFuture.supplyAsync(() -> 
            userRepository.findById(id).orElse(null)
        );
    }
}

3.6 组合使用

@Service
public class UserService {
    
    // 组合多个容错机制
    @CircuitBreaker(name = "userService", fallbackMethod = "fallback")
    @RateLimiter(name = "userService")
    @Retry(name = "userService")
    @Bulkhead(name = "userService")
    @TimeLimiter(name = "userService")
    public CompletableFuture<User> getUser(Long id) {
        return CompletableFuture.supplyAsync(() -> 
            userRepository.findById(id).orElse(null)
        );
    }
    
    private CompletableFuture<User> fallback(Long id, Exception ex) {
        return CompletableFuture.completedFuture(
            User.builder().id(id).name("默认用户").build()
        );
    }
}
# 完整配置
resilience4j:
  timelimiter:
    configs:
      default:
        timeoutDuration: 2s           # 超时时间
        cancelRunningFuture: true     # 超时是否取消运行中的 Future
    instances:
      userService:
        baseConfig: default

3.7 Resilience4j 监控

@Configuration
public class Resilience4jConfig {
    
    @Bean
    public CircuitBreaker circuitBreaker(CircuitBreakerRegistry registry) {
        CircuitBreaker circuitBreaker = registry.circuitBreaker("userService");
        
        // 注册事件监听器
        circuitBreaker.getEventPublisher()
            .onSuccess(event -> log.info("调用成功: {}", event))
            .onError(event -> log.error("调用失败: {}", event))
            .onStateTransition(event -> log.info("状态转换: {}", event))
            .onSlowCall(event -> log.warn("慢调用: {}", event));
        
        return circuitBreaker;
    }
}
# Actuator 配置
management:
  endpoints:
    web:
      exposure:
        include: health,circuitbreakers,circuitbreakerevents
  endpoint:
    health:
      show-details: always
  health:
    circuitbreakers:
      enabled: true

四、Sentinel vs Hystrix vs Resilience4j 对比

4.1 功能对比

┌─────────────────────────────────────────────────────────────┐
│              三种熔断器功能对比                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────┬──────────┬───────────┬─────────────┐  │
│  │     功能         │ Hystrix  │ Sentinel  │ Resilience4j│  │
│  ├─────────────────┼──────────┼───────────┼─────────────┤  │
│  │ 熔断器          │    ✅    │    ✅     │     ✅      │  │
│  │ 限流            │    ❌    │    ✅     │     ✅      │  │
│  │ 热点参数限流     │    ❌    │    ✅     │     ❌      │  │
│  │ 系统自适应保护   │    ❌    │    ✅     │     ❌      │  │
│  │ 重试            │    ❌    │    ❌     │     ✅      │  │
│  │ 舱壁隔离        │    ✅    │    ✅     │     ✅      │  │
│  │ 控制台          │    ✅    │    ✅     │     ❌      │  │
│  │ 实时监控        │    ✅    │    ✅     │     ✅      │  │
│  │ 动态配置        │    ✅    │    ✅     │     ✅      │  │
│  │ Spring Cloud集成│    ✅    │    ✅     │     ✅      │  │
│  │ 维护状态        │  停止维护 │   活跃    │     活跃    │  │
│  └─────────────────┴──────────┴───────────┴─────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.2 性能对比

特性 Hystrix Sentinel Resilience4j
实现语言 Java Java Java
隔离策略 线程池/信号量 信号量 信号量/线程池
熔断策略 异常比例 异常比例/慢调用 异常比例/慢调用
限流算法 滑动窗口/令牌桶 令牌桶
性能开销 较高
内存占用 较高

4.3 选型建议

┌─────────────────────────────────────────────────────────────┐
│                     选型建议                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  选择 Sentinel:                                             │
│  ├── 需要完善的控制台和可视化监控                            │
│  ├── 需要热点参数限流                                       │
│  ├── 需要系统自适应保护                                     │
│  ├── 已有 Spring Cloud Alibaba 生态                         │
│  └── 需要丰富的限流场景                                     │
│                                                             │
│  选择 Resilience4j:                                         │
│  ├── 需要轻量级解决方案                                     │
│  ├── 需要重试功能                                           │
│  ├── 需要模块化组合使用                                     │
│  ├── 已有 Spring Cloud 生态(非 Alibaba)                   │
│  └── 不需要控制台                                           │
│                                                             │
│  不推荐 Hystrix:                                            │
│  └── 已停止维护,建议迁移到 Sentinel 或 Resilience4j        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

五、熔断降级在 Spring Cloud 中的集成

5.1 Gateway + Sentinel

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20

5.2 OpenFeign + Sentinel

feign:
  sentinel:
    enabled: true
@FeignClient(name = "user-service", fallback = UserServiceFallback.class)
public interface UserServiceClient {
    
    @GetMapping("/user/{id}")
    User getUser(@PathVariable Long id);
}

@Component
public class UserServiceFallback implements UserServiceClient {
    
    @Override
    public User getUser(Long id) {
        return User.builder().id(id).name("默认用户").build();
    }
}

5.3 RestTemplate + Sentinel

@Configuration
public class RestTemplateConfig {
    
    @Bean
    @LoadBalanced
    @SentinelRestTemplate(
        blockHandler = "handleBlock",
        blockHandlerClass = SentinelExceptionHandler.class,
        fallback = "handleFallback",
        fallbackClass = SentinelExceptionHandler.class
    )
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

public class SentinelExceptionHandler {
    
    public static ResponseEntity<String> handleBlock(HttpRequest request, 
                                                     byte[] body, 
                                                     ClientHttpRequestExecution execution, 
                                                     BlockException ex) {
        return ResponseEntity.status(429).body("请求被限流");
    }
    
    public static ResponseEntity<String> handleFallback(HttpRequest request, 
                                                        byte[] body, 
                                                        ClientHttpRequestExecution execution, 
                                                        Throwable ex) {
        return ResponseEntity.status(500).body("服务降级");
    }
}

📖 高频面试题

Q1: 熔断器的三种状态是如何转换的?

答:

1. Closed(关闭)状态

2. Open(打开)状态

3. Half Open(半开)状态

Closed --[失败率>阈值]--> Open --[等待时间到]--> Half Open
   ↑                                                      |
   |                                                      |
   +------------------[探测成功]---------------------------+
   |
   +------------------[探测失败]--------------------------> Open

Q2: Sentinel 和 Resilience4j 的区别?

答:

特性 Sentinel Resilience4j
控制台 完善
热点参数限流 支持 不支持
系统自适应保护 支持 不支持
重试机制 不支持 支持
轻量级 一般 更轻量
学习曲线 较陡 较平缓
社区活跃度

选择建议

Q3: 如何实现服务降级?

答:

1. Sentinel 方式

@SentinelResource(value = "getUser", 
                  fallback = "getUserFallback")
public User getUser(Long id) {
    return userRepository.findById(id);
}

public User getUserFallback(Long id, Throwable ex) {
    return User.builder().id(id).name("默认用户").build();
}

2. Resilience4j 方式

@CircuitBreaker(name = "userService", 
                fallbackMethod = "getUserFallback")
public User getUser(Long id) {
    return userRepository.findById(id);
}

private User getUserFallback(Long id, Exception ex) {
    return User.builder().id(id).name("默认用户").build();
}

3. OpenFeign 降级

@FeignClient(name = "user-service", 
             fallback = UserServiceFallback.class)
public interface UserServiceClient { }

@Component
public class UserServiceFallback implements UserServiceClient {
    @Override
    public User getUser(Long id) {
        return User.builder().id(id).name("默认用户").build();
    }
}

Q4: Sentinel 的滑动窗口算法原理?

答:

滑动窗口算法将时间划分为多个时间片(样本窗口),统计最近 N 个窗口内的请求数据。

1. 窗口结构

2. 统计过程

时间轴:──[Window0]──[Window1]──[Window2]──[Window3]──→

当前时间:Window2
统计窗口:Window0 + Window1(最近 2 个样本)

当时间进入 Window3:
统计窗口:Window1 + Window2
Window0 被重置,存储新数据

3. 优势

Q5: 如何防止雪崩效应?

答:

1. 熔断降级

2. 限流

3. 超时控制

4. 舱壁隔离

5. 重试机制


参考链接: