Hystrix工作流程图:

流程图详解

1. 构造HystrixCommand对象或者HystrixObservableCommand对象

构造HystrixCommandHystrixObservableCommand对象表示当前流程的依赖,当然,请求中所有需要的参数必须在构造函数中提现,以方便后续使用。

如果希望依赖返回一个结果,那么就构造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 exception

  • queue() — successfully returns a Future, but this Future will throw an exception if its get()method is called
  • observe() — returns an Observable that, when you subscribe to it, will immediately terminate by calling the subscriber’s onError method
  • toObservable() — returns an Observable that, when you subscribe to it, will terminate by calling the subscriber’s onError method

9. 返回处理成功的响应信息

Hystrix工作流的更多相关文章

  1. Hystrix原理与实战

    Hystrix原理与实战 背景 分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务. 比如:订单服务调用商品服务,商品服务调用库存服务. 对于同步调用,当库存服务不可用时,商品 ...

  2. SpringCloud(四)之Netflix开源组件断路器Hystrix介绍

    一.前言? 1.Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种 ...

  3. 一文带大家彻底搞懂Hystrix!

    前言? Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用 ...

  4. 一文彻底搞定Hystrix!

    前言 Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用于 ...

  5. springcloud 微服务分布式 框架源码 activiti工作流 前后分离

    1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...

  6. 微服务分布式 spring cloud springboot 框架源码 activiti工作流 前后分离

    1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...

  7. springcloud vue.js 微服务分布式 前后分离 集成代码生成器 shiro权限 activiti工作流

    1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...

  8. springcloud Springboot vue.js Activiti6 前后分离 跨域 工作流 集成代码生成器 shiro权限

    1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...

  9. springcloud 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离

    1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...

随机推荐

  1. 网络协议 2 - IP 地址和 MAC 地址

    了解完网络协议,我们会发现,网络通信的五层模型里,有两个很重要的概念:IP 地址和 MAC 地址. 那么 IP 地址是怎么来的,又是怎么没的?MAC 地址与 IP 地址又有什么区别? 这回答上面问题前 ...

  2. Oracle 11g DATAGUARD 同步延时监控脚本

    转自 https://blog.51cto.com/8858975/1401988监控脚本(注:这里没用Sendmail工具发送邮件,如果用的话需要修改)$cat check_oracle_dg_de ...

  3. 004.MongoDB数据库基础使用

    一 数据库管理 1.1 创建数据库 [root@uhost ~]# mongo --host 172.24.9.225 --port 27017 -u useradmin -p useradmin & ...

  4. 使用python对整个网页进行截图

    方法一.使用PyQt4的QtWebKit组件 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ...

  5. 信号驱动式I/O

    信号驱动式I/O是指进程预先告知内核,使得当某个描述符上发生某事时,内核使用信号通知相关进程. 异步I/O是进程执行I/O系统调用(读或写)告知内核启动某个I/O操作,内核启动I/O操作后立刻返回到进 ...

  6. 浅谈vue中的计算属性和侦听属性

    计算属性 计算属性用于处理复杂的业务逻辑 计算属性具有依赖性,计算属性依赖 data中的初始值,只有当初始值改变的时候,计算属性才会再次计算 计算属性一般书写为一个函数,返回了一个值,这个值具有依赖性 ...

  7. Spring Batch基本概念

    Spring batch主要有以下部分组成: JobRepository     用来注册job的容器 JobLauncher             用来启动Job的接口 Job           ...

  8. golang数据结构之稀疏数组

    掌握知识: 数组的初始化和赋值 结构体的初始化和赋值 字符串和整型之间的转换以及其它的一些操作 类型断言 读取文件 写入文件 对稀疏数组进行压缩 package main import ( " ...

  9. 用一行Python代码制作动态二维码

    在GitHub上发现了一个比较有意思的项目,只需要一行Python代码就可以快捷方便生成普通二维码.艺术二维码(黑白/彩色)和动态GIF二维码. GitHub网站参见:https://github.c ...

  10. git分支合并创建切换

    1. 场景描述 介绍下Git最新内容合并到主干.从主干创建最新分支.idea下切换最新分支,能在2分钟内完成git合并.分支创建以及在idea中完成切换,希望能帮到一些朋友. 2. 解决方案 从以下三 ...