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. ...
随机推荐
- Ling to sql 多表查询,多个条件进行关联
使用多表查询进行关联时,提示 join子句中其中一个表达式的类型不正确,注意字段类型和名称要一致,否则join时提示语法错误,错误截图如下 var incomeDetails = from a in ...
- Linux 释放cache
sysc 将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node.已延迟的块 I/O 和读写映射文件 echo 3 > /proc/sys/vm/drop_caches To free p ...
- Saltstack_使用指南14_无master
1. 主机规划 salt 版本 [root@salt100 ~]# salt --version salt (Oxygen) [root@salt100 ~]# salt-minion --versi ...
- linux上下键,rlwrap来解决
需要安装两个包1.readline,配置好yum直接安装[root@test152 ~]# yum install readline*2.rlwrap这个下载连接当前有效,找了很多没找到有用的http ...
- RMAN DUPLICATE DATABASE with SET NEWNAME failed: RMAN-05501 RMAN-05517 (Doc ID 387093.1)
RMAN DUPLICATE DATABASE with SET NEWNAME failed: RMAN-05501 RMAN-05517 (Doc ID 387093.1) APPLIES TO: ...
- CK:User mode Bus Error(用户空间操作内核地址导致的异常)
关键词:VEC_ACCESS.coredump.LR.PC等. CK中存在一种VEC_ACCESS异常,可能原因是用户空间访问了内核空间,还有一种是内核访问不存在的总线地址. 下面简单构造VEC_AC ...
- Fiddler安装
1.在网上搜一下fiddler的安装包,下载.下载完成能看到一个exe文件. 2.点击文件安装,同意,选择一个目录进行安装即可. 3.安装完成,打开应用是一个这样的界面. 需要安装包的下面评论.... ...
- Node.js接口避免重复启动
众所周知,一个Node接口要是想被调用,得先在命令行中执行如下代码来启动接口 node base.js 但是一旦修改了base.js,就得重新执行这句命令 注:这里的base.js是我的node接口文 ...
- 打包一个python解释器
利用python的exec语句,可以很方便地动态执行python语句.如果一个python代码打包为了exe,其原先的代码就很难更改了.一个好的解决方法就是import相应的库,然后把主程序段放到一个 ...
- networkx生成网络
ER随机网络,WS小世界网络,BA无标度网络的生成 import networkx as nx import matplotlib.pyplot as plt #ER随机网络 #10个节点,连接概率为 ...