Spring Cloud Hystrix功能解析

说明

前面我们已经使用了ribbon实现了各服务的服务间通信,并且实现了相应的负载均衡方式,以便应对一个服务多个实例的情况,在系统中

我们可能会遇见的问题:

1、某个服务故障的连锁反应
2、在高可用的情况下,我们需要快速失败的功能
3、我们需要回退并优雅降级
复制代码

因此引入Hystrix组件

Hystrix是Spring Cloud提供的一种带有熔断机制的框架,由于在微服务系统中同一个操作会由多个不同的微服务来共同完成,所以微服务与微服务之间会由很多相互的调用,由于在分布式环境中经常会出现某个微服务节点故障的情况,所以会由调用失败发生,而熔断器的作用就是当出现远程调用失败的时候提供一种机制来保证程序的正常运行而不会卡死在某一次调用,类似Java程序中的try-catch结构,而只有当异常发生的时候才会进入catch的代码块。

Hystrix遵循的设计原则:

1、防止任何单独的依赖耗尽资源(线程)
2、过载立即切断并快速失败,防止排队
3、尽可能提供回退以保护用户免受故障
4、使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
5、通过近实时的指标,监控和告警,确保故障被及时发现
6、通过动态修改配置属性,确保故障及时恢复
7、防止整个依赖客户端执行失败,而不仅仅是网络通信
复制代码

开始搭建(详细见hystrix具体使用)

1、引入相关依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency> 
复制代码

将client1,client2,client3
client1引入依赖并在主函数加入@EnableHystrix注解,另外两个先不引入
场景一:直接在controller上面使用

图片(10).png
调用getOther方法

图片(11).png

更改成
图片(12).png
之后调用成功
此时我们将client2和client3实例停机

测试

思考:如果我们只停用client2服务其中的一个实例

测试发现
第一次调用
fallback
第二次调用
成功
复制代码

说明我们的熔断机制已经实现,但是服务一会进熔断一会正常(此时我们client1使用的是ribbon默认轮询负载均衡方式),我们查看注册中心发现,CLIENT2-SERVICE中停用一个容器,停用的容器并没有马上从注册中心列表移除(猜测和注册中心心跳机制有关,具体分析放到eureka模块讲解)

Hystrix工作流程

1、构造一个 HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数;
2、执行命令,Hystrix提供了4种执行命令的方法,后面详述;
3、判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动;
4、判断熔断器是否打开,如果打开,跳到第8步;
5、判断线程池/队列/信号量是否已满,已满则跳到第8步;
6、执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到第8步;否则,跳到第9步;
7、统计熔断器监控指标;
8、走Fallback备用逻辑
9、返回请求响应
复制代码

Hystrix容错机制

Hystrix主要提供以下三种容错方式
1、资源隔离
2、熔断
3、降级
资源隔离有两种实现方式
1、线程池隔离
2、信号量
复制代码

线程池隔离优缺点:

1、保护应用程序以免受来自依赖故障的影响,指定依赖线程池饱和不会影响应用程序的其余部分。
2、当引入新客户端lib时,即使发生问题,也是在本lib中,并不会影响到其他内容。
3、当依赖从故障恢复正常时,应用程序会立即恢复正常的性能。
4、当应用程序一些配置参数错误时,线程池的运行状况会很快检测到这一点(通过增加错误,延迟,超时,拒绝等),同时可以通过动态属性进行实时纠正错误的参数配置。
5、如果服务的性能有变化,需要实时调整,比如增加或者减少超时时间,更改重试次数,可以通过线程池指标动态属性修改,而且不会影响到其他调用请求。
6、除了隔离优势外,hystrix拥有专门的线程池可提供内置的并发功能,使得可以在同步调用之上构建异步门面(外观模式),为异步编程提供了支持(Hystrix引入了Rxjava异步框架)。
复制代码

缺点:

线程池的主要缺点是增加了计算开销。每个命令的执行都在单独的线程完成,增加了排队、调度和上下文切换的开销。因此,要使用Hystrix,就必须接受它带来的开销,以换取它所提供的好处。
通常情况下,线程池引入的开销足够小,不会有重大的成本或性能影响。但对于一些访问延迟极低的服务,如只依赖内存缓存,线程池引入的开销就比较明显了,这时候使用线程池隔离技术就不适合了,我们需要考虑更轻量级的方式,如信号量隔离。
如果不想要这么大的开销,可以使用信号量隔离
由于Hystrix默认使用线程池做线程隔离,使用信号量隔离需要显示地将属性execution.isolation.strategy设置为ExecutionIsolationStrategy.SEMAPHORE,同时配置信号量个数,默认为10。客户端需向依赖服务发起请求时,首先要获取一个信号量才能真正发起调用,由于信号量的数量有限,当并发请求量超过信号量个数时,后续的请求都会直接拒绝,进入fallback流程。
复制代码

clipboard.png

熔断

Hystrix在运行过程中会向每个commandKey对应的熔断器报告成功、失败、超时和拒绝的状态,熔断器维护并统计这些数据,并根据这些统计信息来决策熔断开关是否打开。如果打开,熔断后续请求,快速返回。隔一段时间(默认是5s)之后熔断器尝试半开,放入一部分流量请求进来,相当于对依赖服务进行一次健康检查,如果请求成功,熔断器关闭。

降级

降级一般是从整体负荷考虑,当某个服务熔断之后,服务器将不再被调用,客户端可自己准备一个本地的fallback回调,返回一个缺省值,虽然服务水平下降,当能用,比直接挂掉要强

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享