一、Hystrix是什么?

Hystrix是由Netflix开源的一个容错框架,主要用于处理分布式系统中的故障和延迟,以提高系统的弹性和稳定性。它通过服务降级、服务熔断、依赖隔离和实时监控等功能,在复杂的分布式系统中提供断路器模式来阻止级联失败,并提供回退机制来增强系统的弹性。

在微服务架构中,服务间的调用变得非常频繁和复杂。当某个服务出现故障时,如果不加以控制,很容易引发级联故障,导致整个系统崩溃。Hystrix通过服务降级、熔断和依赖隔离等机制,有效防止了这种情况的发生,提高了系统的稳定性和可靠性。

二、Hystrix的作用

Hystrix是Netflix开源的一个服务隔离组件,主要用于处理分布式系统的延迟和容错。它具备以下主要功能:

  1. 熔断器模式:当某个服务的失败率达到一定阈值时,Hystrix会自动触发熔断,阻止对该服务的进一步请求,从而避免系统资源的无谓消耗。
  2. 服务降级:在熔断器开启后,Hystrix会执行服务降级逻辑,返回预设的默认值或缓存数据,以保证服务的部分可用性。
  3. 资源隔离:通过线程池或信号量对服务调用进行隔离,限制任何一个依赖的影响范围,防止单个服务故障耗尽整个系统的资源。
  4. 实时监控与告警:提供近实时的监控和告警功能,帮助开发者及时发现并解决问题。

三、Spring Cloud整合Hystrix代码示例

3.1. 添加依赖

首先,需要在项目的构建文件(如Maven或Gradle)中添加Hystrix的依赖项。以Maven为例:

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

3.2. 启用Hystrix

在Spring Boot的主类或配置类上添加@EnableHystrix注解来启用Hystrix。

3.3. 定义服务调用

在服务调用时,使用@HystrixCommand注解来标记需要容错处理的方法,并指定一个回退方法(fallback method)。

@RestController  
@RequestMapping("/api")  
public class MyController {  
  
    @Autowired  
    private MyService myService;  
  
    @GetMapping("/user/test")  
    @HystrixCommand(fallbackMethod = "sayHelloFallBack")
    public String testUser(@RequestParam Integer userId) {  
        return myService.getUserInfo(userId);  
    }  
  
    public String sayHelloFallBack(Integer userId) {  
        return "Service is down, please try again later.";  
    }  
}  
  
@Service  
public class MyService {  
  
    @Autowired  
    private RestTemplate restTemplate;  
  
    public String getUserInfo(Integer userId) {  
        // 假设这里调用远程服务  
        String url = "http://example.com/api/users/{userId}";  
        return restTemplate.getForObject(url, String.class, userId);  
    }  
}

四、熔断器仪表盘

在Spring Cloud中整合Hystrix Dashboard来监控微服务中的Hystrix熔断器状态是一个常见的做法。以下是一个简单的示例,展示如何将Hystrix Dashboard与Spring Cloud应用整合起来。

4.1. 添加依赖

首先,确保你的Spring Boot项目中已经添加了Spring Cloud Starter Hystrix和Spring Cloud Starter Hystrix Dashboard的依赖。以下是一个Maven示例:

  
<!-- Spring Cloud Hystrix Dashboard -->  
<dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>  
    <version>2.2.5.RELEASE</version>  
</dependency>

注意:替换你的Spring Cloud版本为你项目中实际使用的Spring Cloud版本。

4.2. 启用Hystrix Dashboard

在你的Spring Boot应用的主类或配置类上添加@EnableHystrixDashboard注解来启用Hystrix Dashboard。
在这里插入图片描述

4.3. 访问Dashboard(仪表盘)

在Spring Cloud中,Hystrix会自动注册一个/hystrix.stream端点,启动你的Spring Boot应用,并访问Hystrix Dashboard的URL(通常是http://ip:port/hystrix)

在这里插入图片描述

在Dashboard页面上,输入你的Metrics Stream的URL(例如,http://ip:port/hystrix.stream),然后点击“Monitor Stream”按钮。

比如我的应用是127.0.0.1:8801/hystrix.stream
在这里插入图片描述

上述请求报错,是因为hystrix整合springBoot 2.0以及之后的版本需要额外配置一些东西(Hystrix 目前处于停更维护阶段,springCloud 整合限流组件更常见的是Sentinel)

配置yaml

指定哪些主机地址的Hystrix.stream可以被Hystrix Dashboard访问。这是出于安全考虑,防止未授权的访问尝试,从而保护系统的敏感信息和运行数据。

hystrix:
  dashboard:
    proxyStreamAllowList: localhost,127.0.0.1

注册Metric servlet

如果我们的SpringBoot是2.0以后版本,然后需要添加 ServletRegistrationBean 因为springboot的默认路径不是 “/hystrix.stream”。

  @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

接着请求业务接口,该stream就可以查看请求监控信息了。

在这里插入图片描述

五、Spring Cloud整合Hystrix原理

本篇博文是在使用Hystrix的版本为2.2.5.RELEASE + springCloud 版本Hoxton.SR8下分析得出,不同版本可能有所差异,请读者谨慎辨别

springCloud整合Hystrix的步骤有三个

  1. 引入依赖(分析原理方式:其引入的依赖的自动装配类)
  2. 启动类使用**@EnableHystrix**(分析原理的方式:@EnableHystrix做了哪些操作)
  3. 需要配置熔断、降级的方式添加**@HystrixCommand** (分析原理的方式:@HystrixCommand做了哪些操作)

5.1. 整合入口

  • @EnableHystrix

@EnableHystrix注解来启用Hystrix。这个注解会触发Spring Cloud的自动配置机制,加载与Hystrix相关的配置和Bean。

  • 自动装配类
自动装配类实例化的bean作用
HystrixAutoConfigurationHystrixHealthIndicator用于监控Hystrix的健康状态,比如断路器状态,请求的成功率
HystrixWebfluxEndpoint为基于响应式编程模型的Spring Boot应用提供了Hystrix的端点,Hystrix主要设计用于同步的阻塞式调用,而WebFlux是基于响应式的非阻塞模型,使用过程中可能会有限制
HystrixStreamEndpoint这是一个用于暴露Hystrix实时指标的端点,实时监控Hystrix的状态和指标
HystrixMetricsBinder用于将Hystrix的度量指标(如请求成功率、失败率、响应时间等)绑定到Spring Boot的Micrometer度量系统中
HystrixCircuitBreakerAutoConfigurationHystrixCircuitBreakerFactory创建断路器实例
管理断路器状态
关闭(close)、打开(open)、半开(half-open)
ReactiveHystrixCircuitBreakerAutoConfigurationReactiveHystrixCircuitBreakerFactory这个自动装配类专门为响应式编程环境(如使用Spring WebFlux的应用)配置Hystrix的断路器。它允许在响应式流中利用Hystrix的断路器模式来保护远程服务调用。
HystrixSecurityAutoConfiguration与Hystrix和安全性相关的自动装配类
HystrixCircuitBreakerConfigurationHystrixCommandAspect这个切面(Aspect)负责处理带有@HystrixCommand注解的方法,从而在方法执行时自动应用断路器的逻辑。
HystrixShutdownHook应用程序关闭时执行特定清理任务的组件
  • @HystrixCommand

在 Spring Cloud 中,Hystrix 通常与 Spring Cloud Netflix 的 spring-cloud-starter-netflix-hystrix 依赖一起使用。整合的关键在于通过 Spring 的 AOP(面向切面编程)特性来包装服务调用,以便在调用失败时能够执行回退逻辑。

当 Spring 容器启动时,它会扫描所有带有 @HystrixCommand 注解的方法,并使用 AOP 技术创建一个代理。这个代理会在实际方法调用之前和之后插入逻辑,以处理断路器的逻辑(如是否允许调用、记录调用结果、触发回退等)。

5.2 HystrixCommandAspect

Hystrix整合的关键是AOP,HystrixCommandAspect就是Hystrix为我们生成AOP的入口类,见名知意,该类是处理 @HystrixCommand 的一个切面类。

  @Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
    public Object methodsAnnotatedWithHystrixCommand(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取被代理的目标方法(原始方法),AOP代理可能会改变方法的签名或行为。
        Method method = AopUtils.getMethodFromTarget(joinPoint);
        Validate.notNull(method, "failed to get method from joinPoint: %s", new Object[]{joinPoint});
        //方法不能同时被@HystrixCommand和@HystrixCollapser修饰
        if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
            throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser annotations at the same time");
        } else {
            //根据方法的注解类型(@HystrixCommand或@HystrixCollapser),从META_HOLDER_FACTORY_MAP中获取相应的
            //MetaHolderFactory,并创建MetaHolder实例。MetaHolder用于封装与Hystrix命令执行相关的元数据。
            MetaHolderFactory metaHolderFactory = (MetaHolderFactory)META_HOLDER_FACTORY_MAP.get(HystrixCommandAspect.HystrixPointcutType.of(method));
            MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
            //创建HystrixInvokable:这个实例封装了实际要执行的方法调用。
            HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
            
            ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ? metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();

            try {
                Object result;
                if (!metaHolder.isObservable()) {
                    //@HystrixCommand 默认非观察着模式处理CommandExecutor.execute() 我们的常用模式
                    result = CommandExecutor.execute(invokable, executionType, metaHolder);
                } else {
                    //@HystrixCollapser 注解使用的是观察模式处理
                    //可观察的(响应式编程中的概念,表示数据流的源,允许观察者订阅以接收数据更新)
                    result = this.executeObservable(invokable, executionType, metaHolder);
                }
                //返回执行结果
                return result;
            } catch (HystrixBadRequestException var9) {
                //省略异常处理
            }
        }
    }

5.3 Hystrix的断路器配置

隔离:Hystrix 通过线程池或信号量将远程服务调用隔离开来,防止一个服务的失败影响到其他服务的调用。
快速失败:当检测到服务故障时,Hystrix 会迅速让请求失败,并调用回退逻辑,而不是让请求长时间等待或导致系统资源耗尽。
资源控制:通过限制并发请求的数量,Hystrix 可以防止某个服务消耗过多资源,影响系统的整体性能。

隔离策略:线程池配置

配置项描述默认值
hystrix.command.default.execution.isolation.strategy设置默认的隔离策略,THREAD 表示线程池隔离THREAD
hystrix.command.default.execution.isolation.thread
.timeoutInMilliseconds
线程池隔离下,命令执行的超时时间(毫秒)默认值取决于具体实现,通常为1秒或更长
hystrix.command.default.execution.isolation.thread.coreSize线程池的核心线程数,即线程池始终维持的活跃线程数10(但可能因版本或配置而异,需根据实际情况调整)
hystrix.command.default.execution.isolation.thread.maximumSize线程池允许的最大线程数,用于应对高并发情况10(但可能因版本或配置而异,需根据实际情况调整)
hystrix.command.default.execution.isolation.thread
.queueSizeRejectionThreshold
线程池队列拒绝阈值,当队列中的等待任务数超过此值时,即使没有达到maximumSize,也会拒绝新的命令5(但需注意,当maxQueueSize小于等于0时,此配置无效)
hystrix.command.default.execution.isolation.thread.maxQueueSize线程池阻塞队列的最大长度,用于控制队列中可等待的任务数-1(使用SynchronousQueue,不存储排队数据;大于0时使用LinkedBlockingQueue)
hystrix.command.default.execution.isolation.thread.
keepAliveTimeMinutes
线程池中非核心线程的空闲存活时间(分钟),超过此时间后非核心线程将被终止

隔离策略:信号量配置

配置项描述默认值
hystrix.command.default.execution.isolation.strategy设置默认的隔离策略,SEMAPHORE 表示信号量隔离非 THREAD(因为默认是线程池隔离,所以信号量隔离需显式指定)
hystrix.command.default.execution.isolation.semaphore.
maxConcurrentRequests
信号量隔离下,同时执行的最大命令数(即信号量的最大值)无固定默认值,需根据业务场景和服务器资源来配置

断路器开关配置

配置项描述默认值
hystrix.command.default.circuitBreaker.enabled是否启用断路器功能。设置为true时启用,false时禁用。true
hystrix.command.default.circuitBreaker.requestVolumeThreshold触发断路器打开之前,必须达到的最小请求量。默认值可能因版本而异,但通常是一个较低的值(如20)
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds断路器打开后,等待多久尝试恢复服务(半开状态测试周期)。默认值可能因版本而异,但通常是一个合理的等待时间(如5000毫秒)
hystrix.command.default.circuitBreaker.errorThresholdPercentage在requestVolumeThreshold指定的请求量中,允许失败的百分比。超过此百分比将触发断路器打开。默认值可能因版本而异,但通常设置为50%左右。

5.4 Hystrix隔离机制原理

在Hystrix的源码中,隔离机制的实现主要依赖于HystrixThreadPool和HystrixSemaphore等类。

  1. 线程池隔离的源码实现

    • 线程池的创建与管理:Hystrix通过HystrixThreadPoolFactory类创建和管理线程池。每个服务(或命令)的线程池通过HystrixThreadPoolKey来标识,并存储在ConcurrentHashMap中以便复用。
    • 命令的执行:当命令(HystrixCommand或HystrixObservableCommand)执行时,会首先检查对应的线程池是否有足够的资源来执行该命令。如果有,则将命令提交到线程池中异步执行;如果没有,则根据配置执行降级逻辑。(HystrixObservableCommand响应式编程实现类)。
  2. 信号量隔离的源码实现

    • 信号量的创建与管理:Hystrix使用HystrixSemaphore类来实现信号量隔离。每个服务(或命令)的信号量数量通过配置指定,并在命令执行时进行检查。
    • 命令的执行:在信号量隔离模式下,命令执行前会尝试获取信号量。如果成功获取,则执行命令;如果失败,则直接执行降级逻辑。

更多推荐