SpringCloud-Hystrix

核心价值

容错

降级 fallback

出现程序运行异常、超时等情况的时候给客户端一个友好的提示,而不是抛出异常堆栈信息或者长时间等待,从而导致服务雪崩

服务提供者使用方式

服务提供者增加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

启动类增加注解@EnableHystrix

@SpringBootApplication
@EnableHystrix
public class Application8002 {
    public static void main(String[] args) {
        SpringApplication.run(Application8002.class, args);
    }
}

方法增加@HystrixCommand注解并新增兜底方案

@Slf4j
@Service
@RequiredArgsConstructor
@DefaultProperties(defaultFallback = "defaultHystrixHandler")
public class UserService implements IUserService {
    @Override
    @HystrixCommand(
        fallbackMethod = "findByIdTimeOutHystrixHandler",
        commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
        }
    )
    public User findByIdTimeOutHystrix(Long id) {
        log.debug("id={}", id);
        try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {throw new RuntimeException(e);}
        log.debug("sleep over"); // 熔断以后不会执行
        return null;
    }

    @Override
    @HystrixCommand
    public User findByIdTimeOutHystrix2(Long id) {
        log.debug("id={}", id);
        try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {throw new RuntimeException(e);}
        log.debug("sleep over"); // 熔断以后不会执行
        return null;
    }

    /**
     * Hystrix兜底方法
     *
     * @param id id
     * @return {@link User}
     */
    private User findByIdTimeOutHystrixHandler(Long id) {
        log.error("服务端降级, id={}, ", id);
        return new User();
    }

    /**
     * Hystrix默认兜底方法
     */
    private User defaultHystrixHandler() {
        log.error("服务端降级 默认方法");
        return User.builder().remark("😭").build();
    }

@HystrixCommand中

fallbackMethod指定兜底方法,兜底方法如果入参、返回值不一致会报异常

commandProperties指定超时时间等

findByIdTimeOutHystrix方法发生异常或者超时的时候,就会调用findByIdTimeOutHystrixHandler

@DefaultProperties(defaultFallback = "defaultHystrixHandler")表示默认降级方法,如果@HystrixCommand没指定则默认用这个

findByIdTimeOutHystrix方法降级后,异常发生处后续方法不会执行

输出结果

 INFO 16776 --- [nio-8002-exec-1] m.y.s.s.controller.UserController        : 接收请求, id=1
DEBUG 16776 --- [x-UserService-1] m.y.s.s.service.impl.UserService         : id=1
ERROR 16776 --- [ HystrixTimer-1] m.y.s.s.service.impl.UserService         : 服务端降级, id=1, 

可以看到执行原始方法跟兜底的方法使用的不同线程池

服务消费者使用方式

服务提供者增加依赖

启动类增加注解@EnableHystrix

配置文件开启Hystrix

feign:
  hystrix:
    enabled: true

定义服务的降级

@Component
@FeignClient(value = "PAYMENT-SERVICE", fallback = UserServiceFallback.class)
public interface IUserService {
    @GetMapping("/provider/user/findByIdTimeOut}")
    CommonResult<User> findByIdTimeOut();
}

服务消费者是在@FeignClient的fallback中指定降级类

创建降级处理类,实现服务接口IUserService

@Slf4j
@Component
public class UserServiceFallback implements IUserService {
    @Override
    public CommonResult<User> findByIdTimeOut() {
        return CommonResult.<User>builder().code(HttpStatus.HTTP_INTERNAL_ERROR).message("客户端降级兜底").build();
    }
}

熔断

拒绝访问,等检测到恢复以后才恢复

熔断状态

  1. Closed(闭合态):
    • 默认正常状态,请求正常通过
    • 持续统计失败率(默认时间窗口10秒)
    • 当失败率达到阈值(默认50%)时跳转到Open状态
  2. Open(熔断态):
    • 所有请求立即失败(快速失败)
    • 经过休眠时间(默认5秒)后自动进入HalfOpen状态
  3. HalfOpen(半开态):
    • 允许有限数量的试探请求通过
    • 若请求成功率达到恢复阈值,则进入Closed状态
    • 若任一请求失败,则立即返回Open状态
stateDiagram-v2 state "关闭" as 关闭 state "打开" as 打开 state "半开" as 半开 半开 --> 打开: 试探失败 半开 --> 关闭: 试探成功 关闭 --> 打开: 错误率 >= 阈值\n 且\n 请求数 >= 最小请求数 打开 --> 半开: 熔断时间窗已结束

核心熔断配置参数

配置项 默认值 说明
circuitBreaker.enabled true 是否启用熔断器
circuitBreaker.requestVolumeThreshold 20 触发熔断的最小请求数(统计窗口内)
circuitBreaker.errorThresholdPercentage 50(%) 触发熔断的失败率阈值
circuitBreaker.sleepWindowInMilliseconds 5000(ms) 熔断后的休眠时间(OPEN→HALF_OPEN)
circuitBreaker.forceOpen false 强制打开熔断器(测试用)
circuitBreaker.forceClosed false 强制关闭熔断器(忽略熔断逻辑)
metrics.rollingStats.timeInMilliseconds 10000(ms) 统计窗口时长(10秒)

全局配置方式

hystrix:
  command:
    default:  # 全局默认配置
      circuitBreaker:
        enabled: true
        requestVolumeThreshold: 10
        errorThresholdPercentage: 40
        sleepWindowInMilliseconds: 3000
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2000

方法级配置

@Service
public class UserService {
    @HystrixCommand(
        fallbackMethod = "fallbackMethod",
        commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000"),
            @HystrixProperty(name = "circuitBreaker.enable", value = "true"),
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"),
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "25")
        }
    )
    public String riskyMethod() {
        // 业务逻辑
    }

    private String fallbackMethod() {
        return "降级响应";
    }
}

限流

隔离

Hystrix的隔离策略有两种:线程隔离、信号量隔离。
THREAD(线程隔离):HystrixCommand将会在单独的线程上执行,并发请求受线程池中线程数量的限制。
SEMAPHORE(信号量隔离):HystrixCommand将会在调用线程上执行,开销相对较小,并发请求受信号量的个数的限制。

线程隔离

配置方式:

hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: THREAD  # 显式指定线程隔离(默认)
          thread:
            coreSize: 10          # 线程池核心线程数(默认 10)
            maxQueueSize: 100     # 线程池最大队列长度(默认 -1,无界队列)
            queueSizeRejectionThreshold: 50  # 队列满时的拒绝阈值(默认 50)
            keepAliveTimeMinutes: 1  # 空闲线程存活时间(分钟,默认 1)

工作原理

  • ​线程池分配:Hystrix 为每个命令(HystrixCommand)或任务创建一个独立的线程池(HystrixThreadPool),线程池的大小可配置。
  • ​任务提交​​:任务被提交到线程池后,由线程池中的工作线程执行,主线程(调用方)不会阻塞。
  • ​超时与中断​​:若任务执行超时(通过 execution.isolation.thread.timeoutInMilliseconds配置),Hystrix 会中断线程并触发降级逻辑。

信号量隔离

配置方式

hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE  # 显式指定信号量隔离
          semaphore:
            maxConcurrentRequests: 20  # 最大并发请求数(默认 10)

工作原理

  • 信号量控制​​:Hystrix 为任务分配一个信号量(计数器),初始值为配置的最大并发数(maxConcurrentRequests)。
  • 任务执行​:任务在调用方线程中执行,每启动一个任务消耗一个信号量;任务完成或失败后释放信号量。
  • 并发限制​:当信号量耗尽时,新任务会被拒绝(触发 HystrixSemaphoreRejectedExecutionException),并直接执行降级逻辑。

监控工具

hystrix dashboard

解析

posted @ 2025-08-10 14:54  一只盐桔鸡  阅读(7)  评论(0)    收藏  举报