Hystrix工作流
Hystrix工作流程图:
流程图详解
1. 构造HystrixCommand对象或者HystrixObservableCommand对象
构造HystrixCommand
或HystrixObservableCommand对象表示当前流程的依赖,当然,请求中所有需要的参数必须在构造函数中提现,以方便后续使用。
如果希望依赖返回一个结果,那么就构造HystrixCommand对象
HystrixCommand command = new HystrixCommand(arg1, arg2);
如果希望返回依赖的一个观察对象,那么久构造HystrixObservableCommand对象
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);
2. 执行命令
我们可以通过四种方式调起依赖
1) execute()方法,会返回响应结果,如果出现异常,则抛出ERROR。只可以执行HystrixCommand对象
2) queue()方法,会返回Future对象,你可以从中获取响应信息。只可以执行HystrixCommand对象。当我们查看execute源码的时候,不难发现它实际就是调用queue().get()方法
//@see com.netflix.hystrix.HystrixCommand.execute()
public R execute() {
try {
return queue().get();
} catch (Exception e) {
throw Exceptions.sneakyThrow(decomposeException(e));
}
}
当然,在某些业务场景下我们还是需要执行queue方法的,它提供有更丰富的方法供我们调用,而不只是返回处理结果:
//取消命令执行
boolean cancel(boolean mayInterruptIfRunning);
//检查命令是否被取消
boolean isCancelled();
//检查依赖是否完成
boolean isDone();
//获取依赖执行结果
V get() throws InterruptedException, ExecutionException;
//获取依赖执行结果,如果超过获取时间限制,则抛出TimeoutException异常
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
而queue()方法中实际调用的是toObservable().toBlocking().toFuture()方法
//@see com.netflix.hystrix.HystrixCommand.queue()
public Future<R> queue() {
/*
* The Future returned by Observable.toBlocking().toFuture() does not implement the
* interruption of the execution thread when the "mayInterrupt" flag of Future.cancel(boolean) is set to true;
* thus, to comply with the contract of Future, we must wrap around it.
*/
final Future<R> delegate = toObservable().toBlocking().toFuture();
………
return f;
}
3) observe()订阅依赖的执行结果,当然我们也可以通过此方式执行依赖
Observable<String> fWorld = new CommandHelloWorld("World").observe();
Observable<String> fBob = new CommandHelloWorld("Bob").observe(); // blocking
assertEquals("Hello World!", fWorld.toBlocking().single());
assertEquals("Hello Bob!", fBob.toBlocking().single());
而在observe()内部又调用的是toObservable()方法
//@see com.netflix.hystrix.AbstractCommand.observe()
public Observable<R> observe() {
// us a ReplaySubject to buffer the eagerly subscribed-to Observable
ReplaySubject<R> subject = ReplaySubject.create();
// eagerly kick off subscription
final Subscription sourceSubscription = toObservable().subscribe(subject);
// return the subject that can be subscribed to later while the execution has already started
return subject.doOnUnsubscribe(new Action0() {
@Override
public void call() {
sourceSubscription.unsubscribe();
}
});
}
4) toObservable() 返回你订阅依赖的Observable对象
用法:
K value = command.execute();
Future<K> fValue = command.queue();
Observable<K> ohValue = command.observe(); //hot observable
Observable<K> ocValue = command.toObservable(); //cold observable
说明:
同步调用execute()方法,实际是调用queue().get(),而queue()方法中实际调用的是toObservable().toBlocking().toFuture()。也就是说所有的HystrixCommand都绑定了Observable对象,即使这个命令只是获取一个简单值。
3. 执行结果是否缓存
接下来会检查当前命令是否支持缓存,如果支持缓存,就会检查当前请求是否之前已经执行过,执行了,就直接从换从中获取结果。不支持缓存,则继续后续流程处理。
具体流程如下:
4. 熔断检查
当你执行依赖的时候,Hystrix会检查熔断器,判定当前流程是否通畅。
如果达到熔断条件,则不执行依赖,直接跳到第八步,执行FallBack方法。
如果未达到熔断条件,则继续向后执行。
5. 检查线程池、队列、阈值是否达到上限
如果线程池或者队列已经满了,那么就直接跳到第八步。
6. 执行HystrixObservableCommand的构造函数或者执行HystrixCommand的run方法
通过执行HystrixCommand.run()和HystrixObservableCommand.constract()执行依赖的方法。
如果run方法执行时间超时,那么当前线程就会抛出TimeoutException(如果要执行的依赖进程未启动或被占用,就会启动一个单独的Timer线程)。然后Hystrix就直接路由到第八步,执行Fallback,并且丢弃依赖的run()和constract()方法(如果依赖进程未被取消、中断),我使用1.5.13版本进行测试时,发现如果依赖进程未未执行超时,那么Timer进程就会将依赖进程杀死,然后执行Fallback方法。
注意:没有什么途径终止依赖进程的run方法,只有Hystrix抛出InterruptedException来终止。如果容器不理会Hystrix抛出的异常,那么依赖进程会继续执行,尽管客户端收到了TimeoutException。这种情况有可能导致Hystrix线程池沾满。大多数HTTP Client包不支持InterruptedException,所以,要确保HTTPclient中的read/write超时时间设定正确。
7. 检查回路是否正常
Hystrix reports successes, failures, rejections, and timeouts to the circuit breaker, which maintains a rolling set of counters that calculate statistics.
It uses these stats to determine when the circuit should “trip,” at which point it short-circuits any subsequent requests until a recovery period elapses, upon which it closes the circuit again after first checking certain health checks.
8. 获取Fallback数据
Hystrix tried to revert to your fallback whenever a command execution fails: when an exception is thrown by construct()
or run()
(6.), when the command is short-circuited because the circuit is open (4.), when the command’s thread pool and queue or semaphore are at capacity (5.), or when the command has exceeded its timeout length.
Write your fallback to provide a generic response, without any network dependency, from an in-memory cache or by means of other static logic. If you must use a network call in the fallback, you should do so by means of another HystrixCommand
or HystrixObservableCommand
.
In the case of a HystrixCommand
, to provide fallback logic you implement HystrixCommand.getFallback()
which returns a single fallback value.
In the case of a HystrixObservableCommand
, to provide fallback logic you implement HystrixObservableCommand.resumeWithFallback()
which returns an Observable that may emit a fallback value or values.
If the fallback method returns a response then Hystrix will return this response to the caller. In the case of a HystrixCommand.getFallback()
, it will return an Observable that emits the value returned from the method. In the case of HystrixObservableCommand.resumeWithFallback()
it will return the same Observable returned from the method.
If you have not implemented a fallback method for your Hystrix command, or if the fallback itself throws an exception, Hystrix still returns an Observable, but one that emits nothing and immediately terminates with an onError
notification. It is through this onError
notification that the exception that caused the command to fail is transmitted back to the caller. (It is a poor practice to implement a fallback implementation that can fail. You should implement your fallback such that it is not performing any logic that could fail.)
The result of a failed or nonexistent fallback will differ depending on how you invoked the Hystrix command:
execute()
— throws an exceptionqueue()
— successfully returns aFuture
, but thisFuture
will throw an exception if itsget()
method is calledobserve()
— returns anObservable
that, when you subscribe to it, will immediately terminate by calling the subscriber’sonError
methodtoObservable()
— returns anObservable
that, when you subscribe to it, will terminate by calling the subscriber’sonError
method
9. 返回处理成功的响应信息
Hystrix工作流的更多相关文章
- Hystrix原理与实战
Hystrix原理与实战 背景 分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务. 比如:订单服务调用商品服务,商品服务调用库存服务. 对于同步调用,当库存服务不可用时,商品 ...
- SpringCloud(四)之Netflix开源组件断路器Hystrix介绍
一.前言? 1.Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种 ...
- 一文带大家彻底搞懂Hystrix!
前言? Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用 ...
- 一文彻底搞定Hystrix!
前言 Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用于 ...
- springcloud 微服务分布式 框架源码 activiti工作流 前后分离
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
- 微服务分布式 spring cloud springboot 框架源码 activiti工作流 前后分离
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
- springcloud vue.js 微服务分布式 前后分离 集成代码生成器 shiro权限 activiti工作流
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
- springcloud Springboot vue.js Activiti6 前后分离 跨域 工作流 集成代码生成器 shiro权限
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
- springcloud 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
随机推荐
- Implement Custom Business Classes and Reference Properties实现自定义业务类和引用属性(EF)
In this lesson, you will learn how to implement business classes from scratch. For this purpose, the ...
- 【重学Git】基础命令篇
1.git commit :在提交树中增加一个提交节点,注意:分支是指向提交节点的. 2.git branch newImage : 表示创建一个名为newImage的分支. 3.git checko ...
- CSS学习笔记-盒子阴影及文字阴影
盒子阴影: 1.格式: box-shadow:h-shadow v-shadow blur spread color insert; box-shadow:水平偏移 ...
- DataPump遭遇ORA-06512&ORA-39080&ORA-01403错误案例
最近使用数据泵(DataPump)比较多,遇到了奇奇怪怪的问题,似乎Apply了补丁PSU 10.2.0.5.180717后,DataPump的问题就格外多.如下所示: expdp system/xx ...
- win10系统使用小技巧【转】
win10的很多小技巧又简单又实用,这里给大家整理了10个小技巧,一分钟学会,秒变win10高手,看不完的先收藏再看哦. 1.改美区 在设置中时间和语言中将区域和语言改为美国就可以瞬间切换Foreca ...
- 【2019.8.15 慈溪模拟赛 T1】插头(plugin)(二分+贪心)
二分 首先,可以发现,最后的答案显然满足可二分性,因此我们可以二分答案. 然后,我们只要贪心,就可以验证了. 贪心 不难发现,肯定会优先选择能提供更多插座的排插,且在确定充电器个数的情况下,肯定选择能 ...
- HTML连载42-清空默认边距、文字行高
一. webstorm取色技巧:webstorm内置了颜色取色器,我们对某种颜色未知的时候,可以利用下图中的取色器,进行颜色识别. 二.系统会默认给body添加外边距,因此我们对 ...
- angularjs 一篇文章看懂自定义指令directive
壹 ❀ 引 在angularjs开发中,指令的使用是无处无在的,我们习惯使用指令来拓展HTML:那么如何理解指令呢,你可以把它理解成在DOM元素上运行的函数,它可以帮助我们拓展DOM元素的功能.比如 ...
- JS 从内存空间谈到垃圾回收机制
壹 ❀ 引 从事计算机相关技术工作的同学,对于内存空间相关概念多少有所耳闻,毕竟像我这种非计算机科班出身的人,对于栈堆,垃圾回收都能简单说道几句:当我明白JS 基本类型与引用类型数据存储方式不同,才 ...
- SVN基本使用
1.把服务器的所有内容下载到本地 svn checkout 服务器地址 --username=使用者 --password=密码 2.添加文件 touch main.m(文件名) : 创建main.m ...