一、背景:微服架构中,我们将系统拆分成很多服务单元,各个服务中通过服务注册与订阅的凡是相互依赖。由于每个单元都在不同的进程中,依赖通过远程调用的方式执行,这样就可能因为网络原因或依赖服务自身的问题出现调用故障或延迟,而这些问题会直接导致第哦用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会因等待出现故障的依赖方相应形成任务挤压,导致自身服务瘫痪。
栗子:电商网站中,我们可能将系统拆分成用户、订单、库存、积分等服务单元,用户创建一个订单的时候,客户将第哦啊用订单服务的创建订单接口,此时闯进啊订单接口优惠想库存复位请求出货,此时若库存服务响应缓慢,会直接导致创建订单的服务的县城被挂起,以等待库存申请服务响应。若等待时间过长用户会因为请求库存失败而创建订单失败,如果高并发的情况,因这些挂起的县城在等待库存服务而未能释放,使得后续来的创建订单请求被阻塞,最终导致订单服务不可用,
二、方案:断路器模式:Spring cloud hystrix ,实现了断路器、线程隔离等一系列保护功能,具备服务降级、服务熔断、西纳城和信号隔离、请求缓存、请求合并以及服务监控等强大功能。
三、实现:
1:
pom.xml中加入
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</exclusion>
</exclusions>
<version>1.5.12</version>
</dependency>
2:
测试类:
可以发现当test()中有异常的时候会进入到helltest()中去;
四:原理
工作流程:
1:创建HystrixCommand或HystrixObservableCommand对象
HystrixCommand 用于返回单个操作结果的时候
HystrixObservableCommand 用于返回多个操作结果
a、命令模式:将客户端的请求封装成一个对象,从而让你可以使用不同的请求对客户端进行参数化。可以被用于“行为请求者”与“行为实现者”的解耦。
1)接收者:知道如何处理就提业务逻辑
2)抽象命令:定义了一个命令对戏那个应具备的一系列命令操作,比如execute(),当名利操作被调用的时候就会触发接收者去做具体的命令对应的也无逻辑
3)具体命令的事项,在这绑定了命令操作与接收者之间的关系,execute()命令的实现委托给力接收者的action()函数
4)调用者:持有一个命令对象,并且可以在需要的时候就通过命令对象完成具体的业务逻辑
b、调用者和接收者的关系非常类似于:请求--响应 ,所以比较适合记录日志、撤销操作、队列请求等。
下面情况应考虑命令模式:
1)使用命令模式作为回调(callback):callback讲的是先将函数登记上,然后以后调用此函数。
2)需要在不同不同的时间指定请求,将请求排队,原先的请求发出者可能已经不在了,而命令对象本身仍然是活的
3)系统需要支持命令的册小,命令对象可以把状态存储起来,等到客户端撤销命令所产生效果时可调用相应的方法。
4)若要将系统中所有的数据更新到日志里,以便在系统崩溃的时候可以根据日志读回命令操作。
2、命令执行
execute()同步执行
queue()异步执行,直接返回一个Future对象,其中包含了服务执行结束的时要返回的单一结果。
hystrixObservableCommand实现了另外两种方执行方式:
observe():返回Observable(事件源)对象,他代表了操作的多个结果,是一个hot Observable:不论该observable(事件源)是否有订阅者,都会在创建后对事件进行发布,而订阅者都有可能从事件者的中途开始,并且可能只是看到整个操作的局部。
toObservable():返回Observable对象,但返回的是一个Cold Observable:没有订阅者的时候是不会发布时间的,而是进行等待
3、结果是否被缓存
若当前命令的请求功能是被启用的,并且该命令在缓存命令中,那么缓存的结果会立即以Observable对象的形式返回。
4、断路器是否被打开
如果打开,Hystrix不会执行命令而是庄街道fallback处理逻辑(8)
否:检查是否有可用资源来执行命令(5)
5、线程池/请求队列/信号量是否占满
是:转到fallback处理逻辑(8)
Hystrix所判断的线程池并非容器的线程池而是每个依赖服务的线程池
6、hystrixObservableCommand.construct() 或hystrixCommand.run()
hystrixCommand.run() 返回一个单一结果,或者抛出异常
hystrixObservableCommand.construct()返回一个Observable对象发射多个结果,或通过onError发送错误通知
7、计算断路器的健康度
Hystrix会将“成功”,“失败”,“拒绝”,“超时”等信息报告给断路器,断路器会维护一组计数器来统计这些数据。
使用这些统计数据来决定是否要将断路器打开
8、fallback处理
当执行命令失败,Hystrix会尝试回退处理,通常也称“服务降级”
引起服务降级的处理情况:
4步:命令处于“熔断/短路”状态,断路器是打开的时候
5步:当前命令的线程池、请求队列或信号量被占满
6步:抛出异常的时候
9、返回成功响应
后续:命令名称、分组及线程池的划分,请求缓存