【一起学源码-微服务】Hystrix 源码一:Hystrix基础原理与Demo搭建

上一个系列文章讲解了Feign的源码,主要是Feign动态代理实现的原理,及配合Ribbon实现负载均衡的机制。

这里我们讲解一个新的组件Hystrix,也是和Feign进行融合的。

本讲目录

这一讲开始讲解Hystrix相关代码,当然还是基于上一个组件Feign的基础上开始讲解的,这里默认你对Feign已经有了大致的了解。

使用过spring cloud的小伙伴对这个组件都不会陌生,Hystrix是保证系统高可用一个很重要的组件,主要提供一下几个功能:

对依赖服务调用时出现的调用延迟和调用失败进行控制和容错保护

在复杂的分布式系统中,阻止某一个依赖服务的故障在整个系统中蔓延,服务A->服务B->服务C,服务C故障了,服务B也故障了,服务A故障了,整套分布式系统全部故障,整体宕机

提供fail-fast(快速失败)和快速恢复的支持

提供fallback优雅降级的支持

支持近实时的监控、报警以及运维操作

目录如下:

Hystrix基础原理

Hystrix Demo搭建

Hystrix源码阅读及调试说明

Hystrix入口程序初探

组件分析 Hystrix基础原理 命令模式

将所有请求外部系统(或者叫依赖服务)的逻辑封装到 HystrixCommand 或者 HystrixObservableCommand 对象中。

Run()方法为实现业务逻辑,这些逻辑将会在独立的线程中被执行当请求依赖服务时出现拒绝服务、超时或者短路(多个依赖服务顺序请求,前面的依赖服务请求失败,则后面的请求不会发出)时,执行该依赖服务的失败回退逻辑(Fallback)。

隔离策略

Hystrix 为每个依赖项维护一个小线程池(或信号量);如果它们达到设定值(触发隔离),则发往该依赖项的请求将立即被拒绝,执行失败回退逻辑(Fallback),而不是排队。

隔离策略分线程隔离和信号隔离。

线程隔离

第三方客户端(执行Hystrix的run()方法)会在单独的线程执行,会与调用的该任务的线程进行隔离,以此来防止调用者调用依赖所消耗的时间过长而阻塞调用者的线程。

使用线程隔离的好处:

应用程序可以不受失控的第三方客户端的威胁,如果第三方客户端出现问题,可以通过降级来隔离依赖。

当失败的客户端服务恢复时,线程池将会被清除,应用程序也会恢复,而不至于使整个Tomcat容器出现故障。

如果一个客户端库的配置错误,线程池可以很快的感知这一错误(通过增加错误比例,延迟,超时,拒绝等),并可以在不影响应用程序的功能情况下来处理这些问题(可以通过动态配置来进行实时的改变)。

如果一个客户端服务的性能变差,可以通过改变线程池的指标(错误、延迟、超时、拒绝)来进行属性的调整,并且这些调整可以不影响其他的客户端请求。

简而言之,由线程供的隔离功能可以使客户端和应用程序优雅的处理各种变化,而不会造成中断。

线程池的缺点

线程最主要的缺点就是增加了CPU的计算开销,每个command都会在单独的线程上执行,这样的执行方式会涉及到命令的排队、调度和上下文切换。

Netflix在设计这个系统时,决定接受这个开销的代价,来换取它所提供的好处,并且认为这个开销是足够小的,不会有重大的成本或者是性能影响。

信号隔离

信号隔离是通过限制依赖服务的并发请求数,来控制隔离开关。信号隔离方式下,业务请求线程和执行依赖服务的线程是同一个线程(例如Tomcat容器线程)。

观察者模式

Hystrix通过观察者模式对服务进行状态监听

每个任务都包含有一个对应的Metrics,所有Metrics都由一个ConcurrentHashMap来进行维护,Key是CommandKey.name()

在任务的不同阶段会往Metrics中写入不同的信息,Metrics会对统计到的历史信息进行统计汇总,供熔断器以及Dashboard监控时使用

Metrics

Metrics内部又包含了许多内部用来管理各种状态的类,所有的状态都是由这些类管理的

各种状态的内部也是用ConcurrentHashMap来进行维护的

熔断机制

熔断机制是一种保护性机制,当系统中某个服务失败率过高时,将开启熔断器,对该服务的后续调用,直接拒绝,进行Fallback操作。

熔断所依靠的数据即是Metrics中的HealthCount所统计的错误率。

如何判断是否应该开启熔断器?

必须同时满足两个条件:

请求数达到设定的阀值;

请求的失败数 / 总请求数 > 错误占比阀值%。

降级策略

当construct()或run()执行失败时,Hystrix调用fallback执行回退逻辑,回退逻辑包含了通用的响应信息,这些响应从内存缓存中或者其他固定逻辑中得到,而不应有任何的网络依赖。

如果一定要在失败回退逻辑中包含网络请求,必须将这些网络请求包装在另一个 HystrixCommand 或 HystrixObservableCommand 中,即多次降级。

失败降级也有频率限时,如果同一fallback短时间请求过大,则会抛出拒绝异常。

缓存机制

同一对象的不同HystrixCommand实例,只执行一次底层的run()方法,并将第一个响应结果缓存起来,其后的请求都会从缓存返回相同的数据。

由于请求缓存位于construct()或run()方法调用之前,所以,它减少了线程的执行,消除了线程、上下文等开销。

Hystrix基础原理总结

用一张简单地流程图总结:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwydfx.html