摘要: 原創出處 www.iocoder.cn/Hystrix/com… 「芋道原始碼」歡迎轉載,保留摘要,謝謝!
本文主要基於 Hystrix 1.5.X 版本
???關注微信公眾號:【芋道原始碼】有福利:
- RocketMQ / MyCAT / Sharding-JDBC 所有原始碼分析文章列表
- RocketMQ / MyCAT / Sharding-JDBC 中文註釋原始碼 GitHub 地址
- 您對於原始碼的疑問每條留言都將得到認真回覆。甚至不知道如何讀原始碼也可以請教噢。
- 新的原始碼解析文章實時收到通知。每週更新一篇左右。
- 認真的原始碼交流微信群。
1. 概述
本文主要分享 Hystrix 執行命令方法。
建議 :對 RxJava 已經有一定的瞭解的基礎上閱讀本文。
在官方提供的示例中,我們看到 CommandHelloWorld 通過繼承 HystrixCommand 抽象類,有四種呼叫方式:
方法 | ||
---|---|---|
#execute() |
同步呼叫,返回直接結果 | |
#queue() |
非同步呼叫,返回 java.util.concurrent.Future |
|
#observe() |
非同步呼叫,返回 rx.Observable 。向 Observable 註冊 rx.Subscriber 處理結果 |
|
#toObservable() |
未呼叫,返回 rx.Observable 。向 Observable 註冊 rx.Subscriber 處理結果 |
- 第四種方式,點選
#testToObservable()
檢視筆者補充的示例。
推薦 Spring Cloud 書籍:
- 請支援正版。下載盜版,等於主動編寫低階 BUG 。
- 程式猿DD —— 《Spring Cloud微服務實戰》
- 周立 —— 《Spring Cloud與Docker微服務架構實戰》
- 兩書齊買,京東包郵。
2. 實現
// 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()
方法 :未做訂閱,返回乾淨的 Observable 。這就是為什麼上文說“未呼叫” 。#observe()
方法 :呼叫#toObservable()
方法的基礎上,向 Observable 註冊rx.subjects.ReplaySubject
發起訂閱 。- ReplaySubject 會發射所有來自原始 Observable 的資料給觀察者,無論它們是何時訂閱的。感興趣的同學可以閱讀 《ReactiveX/RxJava文件中文版 —— Subject》 。
#queue()
方法 :呼叫#toObservable()
方法的基礎上,呼叫:Observable#toBlocking()
方法 :將 Observable 轉換成阻塞的rx.observables.BlockingObservable
。BlockingObservable#toFuture()
方法 :返回可獲得#run()
抽象方法執行結果的 Future 。#run()
方法 :子類實現該方法,執行正常的業務邏輯。- BlockingObservable 在 「3. BlockingObservable」 詳細解析。
#execute()
方法 :呼叫#queue()
方法的基礎上,呼叫Future#get()
方法,同步返回#run()
的執行結果。-
整理四種呼叫方式如下:
FROM 《【翻譯】Hystrix文件-實現原理》
3. BlockingObservable
本小節為擴充內容,原始碼解析 RxJava ( 非 Hystrix ) 的 rx.observables.BlockingObservable
的實現,所以你可以選擇:
- 1 ) 跳過本小節,不影響對本文的理解。
- 2 ) 選擇閱讀 《ReactiveX/RxJava文件中文版 —— 阻塞操作》 ,理解 BlockingObservable 的原理。
- 3 ) 選擇閱讀本小節,理解 BlockingObservable 的原理以及實現。
《RxJava 原始碼解析 —— BlockingObservable》
666. 彩蛋
第一篇 Hystrix 正式的原始碼解析。
梳理 Hystrix 的原始碼還是蠻痛苦的,主要是因為對 RxJava 不夠熟悉。
胖友,分享一波朋友圈可好!