This article is mainly based on Hystrix 1.5.X version
-
1 Overview
-
2. Implementation
-
3. BlockingObservable
1 Overview
This article mainly shares the Hystrix execution command method .
Recommendation: Read this article on the basis of having a certain understanding of RxJava.
In the officially provided example, we see that CommandHelloWorld inherits the HystrixCommand abstract class, and there are four ways to call it:
method | |
---|---|
#execute() |
Synchronous call, return direct result |
#queue() |
Asynchronous call, return java.util.concurrent.Future |
#observe() |
Asynchronous call, return rx.Observable . rx.Subscriber Register processing results with Observable |
#toObservable() |
Not called , return rx.Observable . rx.Subscriber Register processing results with Observable |
|
|
|
|
2. Implementation
// AbstractCommand.java
abstract class AbstractCommand<R> implements HystrixInvokableInfo<R>, HystrixObservable<R> {
// ... 省略无关属性与方法
public Observable<R> toObservable() {
return Observable.defer(new Func0<Observable<R>>() {
@Override
public Observable<R> call() {
// ....
}
}
}
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();
}
});
}
}
// HystrixCommand.java
public abstract class HystrixCommand<R> extends AbstractCommand<R> implements HystrixExecutable<R>, HystrixInvokableInfo<R>, HystrixObservable<R> {
// ... 省略无关属性与方法
public Future<R> queue() {
final Future<R> delegate = toObservable().toBlocking().toFuture();
final Future<R> f = new Future<R>() {
// ... 包装 delegate
}
// ...
return f;
}
public R execute() {
try {
return queue().get();
} catch (Exception e) {
throw Exceptions.sneakyThrow(decomposeException(e));
}
}
protected abstract R run() throws Exception;
}
-
#toObservable()
Method: No subscription, return a clean Observable. That's why it says "not called" above . -
#observe()
Method: On the basis of calling the#toObservable()
method , register with the Observablerx.subjects.ReplaySubject
to initiate a subscription . ReplaySubject will emit all data from the original Observable to observers, regardless of when they subscribed. Interested students can read "ReactiveX/RxJava Documentation Chinese Version - Subject". -
#queue()
method: call#toObservable()
method based on the call:-
#run()
Method: Subclasses implement this method to perform normal business logic .
-
Observable#toBlocking()
Method: Convert Observable to blocking .rx.observables.BlockingObservable
-
BlockingObservable#toFuture()
Method: Returns a Future that can obtain the result of the execution of the#run()
abstract method .
-
-
BlockingObservable is analyzed in detail in "3. BlockingObservable".
-
#execute()
Method#queue()
: On the basis of calling theFuture#get()
method , call the method and return the execution result synchronously .#run()
-
The four calling methods are organized as follows:
3. BlockingObservable
This section is to expand the content , the source code parses rx.observables.BlockingObservable
the , so you can choose:
-
1) Skip this subsection without affecting the understanding of this article.
-
2) Choose to read "ReactiveX/RxJava Documentation Chinese Version - Blocking Operation" to understand the principle of BlockingObservable.
-
3) Choose to read this section to understand the principle and implementation of BlockingObservable.