6.hystrix执行时的8大流程以及内部原理



之前几章讲解了hystrix最基本的支持高可用的技术,资源隔离+限流


创建command,执行这个command,配置这个command对应的group和线程池,以及线程池/信号量的容量和大小。
我们要去讲解一下,你开始执行这个command,调用了这个command的execute()方法以后,hystrix内部的底层的执行流程和步骤以及原理是什么呢?

在讲解这个流程的过程中,我们会带出来hystrix其他的一些核心以及重要的功能。


画图分析整个8大步骤的流程,然后再对每个步骤进行细致的讲解


1、构建一个HystrixCommand或者HystrixObservableCommand


一个HystrixCommand或一个HystrixObservableCommand对象,代表了对某个依赖服务发起的一次请求或者调用


构造的时候,可以在构造函数中传入任何需要的参数


HystrixCommand主要用于仅仅会返回一个结果的调用
HystrixObservableCommand主要用于可能会返回多条结果的调用


HystrixCommand command = new HystrixCommand(arg1, arg2);
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);


2、调用command的执行方法


执行Command就可以发起一次对依赖服务的调用


要执行Command,需要在4个方法中选择其中的一个:execute(),queue(),observe(),toObservable()


其中execute()和queue()仅仅对HystrixCommand适用


execute():调用后直接block住,属于同步调用,直到依赖服务返回单条结果,或者抛出异常
queue():返回一个Future,属于异步调用,后面可以通过Future获取单条结果


observe():订阅一个Observable对象,Observable代表的是依赖服务返回的结果,获取到一个那个代表结果的Observable对象的拷贝对象
toObservable():返回一个Observable对象,如果我们订阅这个对象,就会执行command并且获取返回结果


K             value   = command.execute();
Future<K>     fValue  = command.queue();
Observable<K> ohValue = command.observe();         
Observable<K> ocValue = command.toObservable();    


execute()实际上会调用queue().get().queue(),接着会调用toObservable().toBlocking().toFuture()


也就是说,无论是哪种执行command的方式,最终都是依赖toObservable()去执行的


3、检查是否开启缓存


从这一步开始,进入我们的底层的运行原理啦,了解hysrix的一些更加高级的功能和特性


如果这个command开启了请求缓存,request cache,而且这个调用的结果在缓存中存在,那么直接从缓存中返回结果


4、检查是否开启了短路器


检查这个command对应的依赖服务是否开启了短路器


如果断路器被打开了,那么hystrix就不会执行这个command,而是直接去执行fallback降级机制


5、检查线程池/队列/semaphore是否已经满了


如果command对应的线程池/队列/semaphore已经满了,那么也不会执行command,而是直接去调用fallback降级机制


6、执行command


调用HystrixObservableCommand.construct()或HystrixCommand.run()来实际执行这个command


HystrixCommand.run()是返回一个单条结果,或者抛出一个异常
HystrixObservableCommand.construct()是返回一个Observable对象,可以获取多条结果


如果HystrixCommand.run()或HystrixObservableCommand.construct()的执行,超过了timeout时长的话,那么command所在的线程就会抛出一个TimeoutException


如果timeout了,也会去执行fallback降级机制,而且就不会管run()或construct()返回的值了


这里要注意的一点是,我们是不可能终止掉一个调用严重延迟的依赖服务的线程的,只能说给你抛出来一个TimeoutException,但是还是可能会因为严重延迟的调用线程占满整个线程池的


即使这个时候新来的流量都被限流了。。。


如果没有timeout的话,那么就会拿到一些调用依赖服务获取到的结果,然后hystrix会做一些logging记录和metric统计


7、短路健康检查


Hystrix会将每一个依赖服务的调用成功,失败,拒绝,超时,等事件,都会发送给circuit breaker断路器


短路器就会对调用成功/失败/拒绝/超时等事件的次数进行统计


短路器会根据这些统计次数来决定,是否要进行短路,如果打开了短路器,那么在一段时间内就会直接短路,然后如果在之后第一次检查发现调用成功了,就关闭断路器


8、调用fallback降级机制


在以下几种情况中,hystrix会调用fallback降级机制:run()或construct()抛出一个异常,短路器打开,线程池/队列/semaphore满了,command执行超时了


一般在降级机制中,都建议给出一些默认的返回值,比如静态的一些代码逻辑,或者从内存中的缓存中提取一些数据,尽量在这里不要再进行网络请求了


即使在降级中,一定要进行网络调用,也应该将那个调用放在一个HystrixCommand中,进行隔离


在HystrixCommand中,上线getFallback()方法,可以提供降级机制


在HystirxObservableCommand中,实现一个resumeWithFallback()方法,返回一个Observable对象,可以提供降级结果


如果fallback返回了结果,那么hystrix就会返回这个结果


对于HystrixCommand,会返回一个Observable对象,其中会发返回对应的结果
对于HystrixObservableCommand,会返回一个原始的Observable对象


如果没有实现fallback,或者是fallback抛出了异常,Hystrix会返回一个Observable,但是不会返回任何数据

不同的command执行方式,其fallback为空或者异常时的返回结果不同

对于execute(),直接抛出异常
对于queue(),返回一个Future,调用get()时抛出异常
对于observe(),返回一个Observable对象,但是调用subscribe()方法订阅它时,理解抛出调用者的onError方法
对于toObservable(),返回一个Observable对象,但是调用subscribe()方法订阅它时,理解抛出调用者的onError方法


9、不同的执行方式


execute(),获取一个Future.get(),然后拿到单个结果
queue(),返回一个Future
observer(),立即订阅Observable,然后启动8大执行步骤,返回一个拷贝的Observable,订阅时立即回调给你结果
toObservable(),返回一个原始的Observable,必须手动订阅才会去执行8大步骤







<think>我们正在讨论Hystrix的工作原理和源码分析。根据用户要求,我们需要深入分析Hystrix流程机制和源码。根据引用,我们知道Hystrix的核心是HystrixCommand和HystrixObservableCommand,它们封装了依赖服务的调用逻辑,并提供了熔断、隔离、降级等功能。另外,Hystrix还提供了监控功能(HystrixDashboard)来实查看请求的执行情况。我们首先从Hystrix执行流程开始,然后深入到关键类的源码分析。Hystrix的工作流程(以HystrixCommand为例):1.构建HystrixCommand对象(或HystrixObservableCommand)。2.执行命令(有多种执行方式,如execute(),queue(),observe()等)。3.判断是否开启缓存(如果开启则从缓存中取结果)。4.判断熔断器是否打开(如果打开则直接进入降级逻辑)。5.判断线程池/信号量是否已(如果了则进入降级逻辑)。6.执行run()方法(即我们封装的业务逻辑)。7.计算熔断器的健康指标(根据成功、失败、超、线程拒绝等)。8.如果执行过程中出现异常,则执行降级逻辑(getFallback())。9.返回结果。接下来,我们分析几个核心类:1.HystrixCommand:这是用户自定义命令的基类,用户需要继承该类并实现run()和getFallback()方法。-run():封装了需要保护的依赖服务调用。-getFallback():当run()执行失败或触发熔断,提供降级逻辑。2.HystrixCircuitBreaker:熔断器接口,实现类为HystrixCircuitBreakerImpl,它负责监控调用健康状况,并在达到阈值打开熔断器。3.HystrixThreadPool:负责线程池的配置和管理,用于实现线程隔离。4.HystrixCommandProperties:命令的配置属性,如超间、熔断器阈值等。5.HystrixCommandMetrics:用于收集命令执行过程中的各项指标,供熔断器和监控使用。我们以HystrixCommand的execute()方法为例,分析其执行过程:在HystrixCommand中,execute()方法实际上是调用queue().get(),而queue()方法返回一个Future对象。所以,我们看queue()方法:```javapublicFuture<R>queue(){//实际上调用toObservable()方法得到一个Observable,然后将其转换为FuturefinalFuture<R>delegate=toObservable().toBlocking().toFuture();//...省略一些处理}```真正的执行逻辑在toObservable()方法中,该方法构建了一个Observable对象,并应用了一系列的操作符(如超、熔断、线程隔离等)。在HystrixCommand中,有一个核心方法叫做executeCommandAndObserve,它定义了整个执行流程的观察链。由于源码较长,我们简化其关键步骤:```javaprivateObservable<R>executeCommandAndObserve(finalAbstractCommand<R>_cmd){//...省略部分代码//应用各种钩子(hook)和操作符returnObservable.defer(newFunc0<Observable<R>>(){@OverridepublicObservable<R>call(){//1.检查熔断器if(circuitBreaker.allowRequest()){//2.获取信号量(如果使用信号量隔离)或线程池(线程隔离)的许可//3.执行run()方法//4.处理超//5.处理结果和异常}else{//熔断器打开,执行降级逻辑returnhandleShortCircuitViaFallback();}}}).onErrorResumeNext(handleFallback)//处理错误并执行降级.doOnTerminate(terminateCommandCleanup)//终止的清理.doOnUnsubscribe(unsubscribeCommandCleanup);//取消订阅的清理}```熔断器的实现(HystrixCircuitBreakerImpl):熔断器内部维护了一个状态机(OPEN,CLOSED,HALF_OPEN)和度量指标(HystrixCommandMetrics)。它通过判断请求的失败率(在一定间窗口内)是否达到阈值来决定是否打开熔断器。线程池隔离:Hystrix使用线程池隔离来限制并发调用量。每个命令都有自己的线程池(通过ThreadPoolKey区分),默认情况下,线程池的小是固定的(默认为10)。监控数据流:Hystrix通过HystrixMetricsStreamServlet(在hystrix-metrics-event-stream中)将监控数据以SSE(Server-SentEvents)的形式输出,然后HystrixDashboard可以消费这些数据并展示。虽然Hystrix已经进入维护阶段,但理解其设计思想和源码对于学习熔断、降级、限流等机制非常有帮助。下面我们给出一个简单的HystrixCommand示例:```javapublicclassHelloWorldCommandextendsHystrixCommand<String>{privatefinalStringname;publicHelloWorldCommand(Stringname){super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));this.name=name;}@OverrideprotectedStringrun(){//模拟可能失败的服务调用if("fail".equals(name)){thrownewRuntimeException("Commandfailed");}return"Hello"+name+"!";}@OverrideprotectedStringgetFallback(){return"Hellofallback!";}}```使用方式:```javaStringresult=newHelloWorldCommand("World").execute();```最后,关于用户提出的问题:官方社区已死,还有必要学习吗?回答:虽然Hystrix不再更新,但其设计思想和实现仍然值得学习。很多后续的熔断器(如Resilience4j)都借鉴了Hystrix的设计。而且,目前很多老项目仍在使用Hystrix,因此了解其原理对于维护和迁移也是必要的。根据要求,我们需要生成相关问题:§§相关问题§§1.Hystrix熔断器是如何实现状态转换的(如关闭、打开、半开)?2.Hystrix的线程池隔离和信号量隔离有什么区别?各自适用什么场景?3.Hystrix的监控数据是如何收集和展示的?4.Hystrix中,如何配置命令的超间?5.Hystrix的降级逻辑(fallback)有哪些触发条件?6.为什么Hystrix被Netflix宣布进入维护阶段?目前有哪些替代方案?</think>### Hystrix 工作原理与源码详解 Hystrix 是一个容错库,通过**熔断机制**、**资源隔离**和**降级策略**保护分布式系统。核心流程如下: #### 工作流程 1. **命令封装** 将外部调用封装为 `HystrixCommand` 或 `HystrixObservableCommand` 对象,继承类需实现 `run()` 方法(主逻辑)和 `getFallback()` 方法(降级逻辑)。 2. **熔断检查** 通过 `CircuitBreaker` 判断当前状态: - **关闭状态**:允许请求通过 - **打开状态**:直接触发降级 - **半开状态**:允许部分请求试探 3. **资源隔离** - **线程池隔离**(默认):每个服务使用独立线程池,避免雪崩 ```java // 线程池配置示例 HystrixThreadPoolProperties.Setter() .withCoreSize(10) // 核心线程数 ``` - **信号量隔离**:通过计数器限制并发量,适用于高频调用 4. **执行与降级** - 若 `run()` 执行/失败/被拒绝,触发 `getFallback()` - 降级逻辑可返回缓存值、默认值或友好错误 5. **指标收集** 实统计成功/失败/超等指标,通过 `HystrixMetricsStreamServlet` 输出数据供监控使用。 --- #### 核心源码解析 ##### 1. `HystrixCommand` 执行入口 ```java public abstract class HystrixCommand<R> { // 核心执行方法 public R execute() { return queue().get(); } protected abstract R run() throws Exception; protected R getFallback() { throw new UnsupportedOperationException(); } } ``` ##### 2. 熔断器实现 (`HystrixCircuitBreaker`) ```java public interface HystrixCircuitBreaker { boolean allowRequest(); // 判断是否允许请求 boolean isOpen(); // 熔断器是否打开 void markSuccess(); // 标记成功(半开状态下恢复) } ``` **状态转换逻辑**: - 失败率超过阈值(默认50%)→ 打开熔断器 - 休眠窗口期(默认5秒)→ 进入半开状态 - 半开状态下请求成功 → 关闭熔断器 ##### 3. 线程隔离实现 (`HystrixThreadPool`) ```java public class HystrixThreadPool { // 线程池执行封装 public Future<R> submit(Callable<R> task) { return threadPool.submit(task); } } ``` - 使用 `ThreadPoolExecutor` 管理资源 - 队列触发拒绝策略,直接执行降级 ##### 4. 监控数据流 (`HystrixMetricsStreamServlet`) ```java public class HystrixMetricsStreamServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { // 输出SSE格式的实监控数据 response.setContentType("text/event-stream"); // 每500ms推送一次指标数据 } } ``` 数据格式示例: ``` data: {"type":"HystrixCommand","name":"HelloService"} ``` --- #### 设计价值与局限 - **优势**: - 服务隔离避免级联故障 - 实熔断减少无效请求 - 监控集成方便问题定位 - **局限**: - 线程池开销较(需权衡) - Netflix 已停止更新(最新版本1.5.18)[^4] - 替代方案:Resilience4j/Sentinel > 尽管 Hystrix 进入维护阶段,其设计思想仍是微服务容错的经典范式,值得深入理解[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值