In-depth implementation of the principle of internal Hystrix

Copyright: ~ reproduced please marked, thank you - if infringement please private letter to me, I will immediately delete ~ https://blog.csdn.net/baidu_26954625/article/details/90633595

本系列内容转载自git项目advancejava
Hystrix basic support high availability technologies: resource isolation + current limiting.
• Create command;
• execute this command;
• configure the command corresponding group and thread pool.

After here, we talk about, you begin to execute this command, this command calls the execute () method, what Hystrix underlying processes and procedures as well as the implementation of the principle yes.

In the process of explaining this process, I will bring out some of the core and Hystrix other important functions.
Here is a flow chart of the entire eight major steps, I will explain each step carefully. The learning process, this flow chart on the shining, I believe it would be more clear thinking.
Here Insert Picture Description

Step one: Create a command

A HystrixCommandor HystrixObservableCommandobject that represents the dependence of a service request or initiated a call. When created, you can pass any required parameters in the constructor.
HystrixCommandmainly used only returns a result of the call.
HystrixObservableCommandmainly for calls may return multiple results.

// 创建 HystrixCommand
HystrixCommand hystrixCommand = new HystrixCommand(arg1, arg2);
// 创建 HystrixObservableCommand
HystrixObservableCommand hystrixObservableCommand = new HystrixObservableCommand(arg1, arg2);

Step two: Call the command execution method

Execute command, you can initiate a call to the dependent services.
Command to be executed, to choose one of four methods: execute(), queue(), observe(), toObservable().
Where execute()and queue()method only to HystrixCommandapply.
execute(): After calling directly block live, are synchronous calls, until the dependent service that returns a single result or throw an exception.
queue(): returns a Future, is an asynchronous call, you can get behind a single results Future.
observe(): subscribe to a Observabletarget, Observableit represents the result depends on service returns, to get a result that represents the Observablecopy of the object object.
toObservable(): returns an Observableobject, if we subscribe to this object, you'll get to perform command and returns the result.

K    value   = hystrixCommand.execute();
Future<K>     fValue  = hystrixCommand.queue();
Observable<K> oValue = hystrixObservableCommand.observe();
Observable<K> toOValue = hystrixObservableCommand.toObservable();
execute() 实际上会调用 queue().get() 方法,可以看一下 Hystrix 源码。
public R execute() {
    try {
        return queue().get();
    } catch (Exception e) {
        throw Exceptions.sneakyThrow(decomposeException(e));
    }
}

In the queue()process, it calls toObservable().toBlocking().toFuture().
final Future<R> delegate = toObservable().toBlocking().toFuture();
That is, by first toObservable()obtaining Futurethe object, and then call Futurethe get()method. So, in fact, no matter which way the implementation of command, ultimately rely on toObservable()to perform.
Here Insert Picture Description

Step three: Check open the cache

From this point, you run into the underlying principle Hystrix friends, Hystrix look at some of the more advanced features and characteristics.

如果这个 command 开启了请求缓存 Request Cache,而且这个调用的结果在缓存中存在,那么直接从缓存中返回结果。否则,继续往后的步骤。

步骤四:检查是否开启了断路器

检查这个 command 对应的依赖服务是否开启了断路器。如果断路器被打开了,那么 Hystrix 就不会执行这个 command,而是直接去执行 fallback 降级机制,返回降级结果。

步骤五:检查线程池/队列/信号量是否已满

如果这个 command 线程池和队列已满,或者 semaphore 信号量已满,那么也不会执行 command,而是直接去调用 fallback 降级机制,同时发送 reject 信息给断路器统计。

步骤六:执行 command

调用 HystrixObservableCommand 对象的 construct() 方法,或者 HystrixCommandrun() 方法来实际执行这个 command。
• HystrixCommand.run() 返回单条结果,或者抛出异常。

// 通过command执行,获取最新一条商品数据
ProductInfo productInfo = getProductInfoCommand.execute();
•	HystrixObservableCommand.construct() 返回一个 Observable 对象,可以获取多条结果。
Observable<ProductInfo> observable = getProductInfosCommand.observe();
// 订阅获取多条结果
observable.subscribe(new Observer<ProductInfo>() {
    @Override
    public void onCompleted() {
        System.out.println("获取完了所有的商品数据");
    }
@Override
    public void onError(Throwable e) {
        e.printStackTrace();
    }
/**
     * 获取完一条数据,就回调一次这个方法
     * @param productInfo
     */
    @Override
    public void onNext(ProductInfo productInfo) {
        System.out.println(productInfo);
    }
});

如果是采用线程池方式,并且 HystrixCommand.run() 或者 HystrixObservableCommand.construct() 的执行时间超过了 timeout 时长的话,那么 command 所在的线程会抛出一个 TimeoutException,这时会执行 fallback 降级机制,不会去管 run()construct() 返回的值了。另一种情况,如果 command 执行出错抛出了其它异常,那么也会走 fallback 降级。这两种情况下,Hystrix 都会发送异常事件给断路器统计。
注意,我们是不可能终止掉一个调用严重延迟的依赖服务的线程的,只能说给你抛出来一个 TimeoutException。
如果没有 timeout,也正常执行的话,那么调用线程就会拿到一些调用依赖服务获取到的结果,然后 Hystrix 也会做一些 logging 记录和 metric 度量统计。

Here Insert Picture Description

步骤七:断路健康检查

Hystrix 会把每一个依赖服务的调用成功、失败、RejectTimeout 等事件发送给 circuit breaker 断路器。断路器就会对这些事件的次数进行统计,根据异常事件发生的比例来决定是否要进行断路(熔断)。如果打开了断路器,那么在接下来一段时间内,会直接断路,返回降级结果。
如果在之后,断路器尝试执行 command,调用没有出错,返回了正常结果,那么 Hystrix 就会把断路器关闭。

步骤八:调用 fallback 降级机制

在以下几种情况中,Hystrix 会调用 fallback 降级机制。
• 断路器处于打开状态;
• 线程池/队列/semaphore满了;
• command 执行超时;
• run() 或者 construct() 抛出异常。
一般在降级机制中,都建议给出一些默认的返回值,比如静态的一些代码逻辑,或者从内存中的缓存中提取一些数据,在这里尽量不要再进行网络请求了。
在降级中,如果一定要进行网络调用的话,也应该将那个调用放在一个 HystrixCommand 中进行隔离。
HystrixCommand 中,实现 getFallback() 方法,可以提供降级机制。
HystrixObservableCommand 中,实现 resumeWithFallback() 方法,返回一个 Observable 对象,可以提供降级结果。
如果没有实现 fallback,或者 fallback 抛出了异常,Hystrix 会返回一个 Observable,但是不会返回任何数据。
不同的 command 执行方式,其 fallback 为空或者异常时的返回结果不同。
• 对于 execute(),直接抛出异常。
• 对于 queue(),返回一个 Future,调用 get() 时抛出异常。
• 对于 observe(),返回一个 Observable 对象,但是调用 subscribe() 方法订阅它时,立即抛出调用者的 onError() 方法。
• 对于 toObservable()Return to a Observablesubject, but to call subscribe()upon subscribe method, the caller immediately throw onError()method.
Different modes of implementation
execute(), get a Future.get(), then get a single result.
queue(), a return Future.
observe(), Subscribe Observable, and then start the implementation of eight major steps to return a copy of Observable, callback as soon as you subscribe to the results.
toObservable(), a return to the original Observable, will have to manually subscribe to perform eight major step.

Guess you like

Origin blog.csdn.net/baidu_26954625/article/details/90633595