Hystrix超時機制
開篇
Hystrix的超時檢測本質上通過啟動單獨執行緒去檢測的,執行緒的啟動的時間剛好就是任務超時的時間,本質上就是這麼個簡單的邏輯。
Hystrix超時後會丟擲一個HystrixTimeoutException的異常。
超時檢測邏輯
Hystrix的超時包括註冊過程和執行過程兩個,註冊過程如下:
執行lift(new HystrixObservableTimeoutOperator<R>(_cmd))關聯超時檢測任務。
在HystrixObservableTimeoutOperator類中,new TimerListener()負責建立檢測任務,HystrixTimer.getInstance().addTimerListener(listener)負責關聯定時任務。
在HystrixObservableTimeoutOperator類中,addTimerListener通過java的定時任務服務scheduleAtFixedRate在延遲超時時間後執行。
Hystrix的超時執行過程如下:
在超時後執行 listener.tick()方法後執行類TimerListener的tick方法
在TimerListener類的tick方法中執行timeoutRunnable.run()後執行HystrixContextRunnable的run方法
在HystrixContextRunnable類run方法中執行child.onError(new HystrixTimeoutException())實現超時。
executeCommandWithSpecifiedIsolation(_cmd).lift(new HystrixObservableTimeoutOperator<R>(_cmd));
private static class HystrixObservableTimeoutOperator<R> implements Operator<R, R> {
final AbstractCommand<R> originalCommand;
public HystrixObservableTimeoutOperator(final AbstractCommand<R> originalCommand) {
this.originalCommand = originalCommand;
}
@Override
public Subscriber<? super R> call(final Subscriber<? super R> child) {
final CompositeSubscription s = new CompositeSubscription();
// if the child unsubscribes we unsubscribe our parent as well
child.add(s);
//capture the HystrixRequestContext upfront so that we can use it in the timeout thread later
final HystrixRequestContext hystrixRequestContext = HystrixRequestContext.getContextForCurrentThread();
TimerListener listener = new TimerListener() {
@Override
public void tick() {
if (originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.TIMED_OUT)) {
// report timeout failure
originalCommand.eventNotifier.markEvent(HystrixEventType.TIMEOUT, originalCommand.commandKey);
// shut down the original request
s.unsubscribe();
final HystrixContextRunnable timeoutRunnable = new HystrixContextRunnable(
originalCommand.concurrencyStrategy, hystrixRequestContext, new Runnable() {
@Override
public void run() {
child.onError(new HystrixTimeoutException());
}
});
timeoutRunnable.run();
}
}
@Override
public int getIntervalTimeInMilliseconds() {
return originalCommand.properties.executionTimeoutInMilliseconds().get();
}
};
final Reference<TimerListener> tl = HystrixTimer.getInstance().addTimerListener(listener);
// set externally so execute/queue can see this
originalCommand.timeoutTimer.set(tl);
/**
* If this subscriber receives values it means the parent succeeded/completed
*/
Subscriber<R> parent = new Subscriber<R>() {
@Override
public void onCompleted() {
if (isNotTimedOut()) {
// stop timer and pass notification through
tl.clear();
child.onCompleted();
}
}
@Override
public void onError(Throwable e) {
if (isNotTimedOut()) {
// stop timer and pass notification through
tl.clear();
child.onError(e);
}
}
@Override
public void onNext(R v) {
if (isNotTimedOut()) {
child.onNext(v);
}
}
private boolean isNotTimedOut() {
// if already marked COMPLETED (by onNext) or succeeds in setting to COMPLETED
return originalCommand.isCommandTimedOut.get() == TimedOutStatus.COMPLETED ||
originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED,
TimedOutStatus.COMPLETED);
}
};
// if s is unsubscribed we want to unsubscribe the parent
s.add(parent);
return parent;
}
}
public Reference<TimerListener> addTimerListener(final TimerListener listener) {
startThreadIfNeeded();
// add the listener
Runnable r = new Runnable() {
@Override
public void run() {
try {
listener.tick();
} catch (Exception e) {
logger.error("Failed while ticking TimerListener", e);
}
}
};
//這裡直接簡單粗暴的scheduleAtFixedRate以超時時間作為週期去判斷是否執行完成
ScheduledFuture<?> f = executor.get().getThreadPool().scheduleAtFixedRate(r,
listener.getIntervalTimeInMilliseconds(), listener.getIntervalTimeInMilliseconds(), TimeUnit.MILLISECONDS);
return new TimerReference(listener, f);
}
public class HystrixContextRunnable implements Runnable {
private final Callable<Void> actual;
private final HystrixRequestContext parentThreadState;
public HystrixContextRunnable(Runnable actual) {
this(HystrixPlugins.getInstance().getConcurrencyStrategy(), actual);
}
public HystrixContextRunnable(HystrixConcurrencyStrategy concurrencyStrategy, final Runnable actual) {
this(concurrencyStrategy, HystrixRequestContext.getContextForCurrentThread(), actual);
}
public HystrixContextRunnable(final HystrixConcurrencyStrategy concurrencyStrategy,
final HystrixRequestContext hystrixRequestContext, final Runnable actual) {
this.actual = concurrencyStrategy.wrapCallable(new Callable<Void>() {
@Override
public Void call() throws Exception {
actual.run();
return null;
}
});
this.parentThreadState = hystrixRequestContext;
}
@Override
public void run() {
HystrixRequestContext existingState = HystrixRequestContext.getContextForCurrentThread();
try {
// set the state of this thread to that of its parent
HystrixRequestContext.setContextOnCurrentThread(parentThreadState);
// execute actual Callable with the state of the parent
try {
actual.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
} finally {
// restore this thread back to its original state
HystrixRequestContext.setContextOnCurrentThread(existingState);
}
}
}
參考文章
相關文章
- 從原始碼分析Hystrix工作機制原始碼
- Nginx 超時事件的處理機制Nginx事件
- Golang利用select實現超時機制Golang
- Hystrix- 基於 Hystrix 訊號量機制實現資源隔離
- 螞蟻金服通訊框架 SOFABolt 解析 | 超時控制機制及心跳機制框架
- 超詳細的node垃圾回收機制
- Redis之時間輪機制(五)Redis
- 超全面Redis分散式高可用方案:哨兵機制Redis分散式
- 超硬核解析!Apache Hudi靈活的Payload機制Apache
- 讓 Spartacus 伺服器端渲染引入 long API 呼叫超時機制的兩種配置方法伺服器API
- 一小時搞懂Mysql鎖機制MySql
- Zookeeper的選舉機制和同步機制超詳細講解,面試經常問到!面試
- 使用 RxJS timeout 操作符給 Angular SSR 渲染模式下的 HTTP 請求新增超時機制JSAngular模式HTTP
- 一種極簡的非同步超時處理機制設計與實現(C#版)非同步C#
- 虛擬機器類載入機制:類載入時機虛擬機
- HDFS 02 - HDFS 的機制:副本機制、機架感知機制、負載均衡機制負載
- 手機小技巧:小米手機時間24小時制怎麼設定
- 8.JVM記憶體分配機制超詳細解析JVM記憶體
- centos7的時間同步機制:chrony使用CentOS
- Java高階架構面試知識點:基於 Hystrix 訊號量機制實現資源隔離Java架構面試
- Spring Cloud 快速入門(四)Hystrix Dashboard 監控儀表盤、Turbine 聚合監控、服務降級報警機制SpringCloud
- SpringCloud之HystrixSpringGCCloud
- Hystrix Fallback 解析
- 玩弄時間的回合制戰棋——《魔鐵危機:時間碎片》
- 快速失敗機制&失敗安全機制
- JavaScript執行緒機制與事件機制JavaScript執行緒事件
- 時間操控機制RPG《魔鐵危機》今日登陸STEAM 以及 GOGGo
- SPI機制
- 包機制
- Binder機制
- C++24小時制轉換成12小時制C++
- 詳解 Handler 訊息處理機制(附自整理超全 Q&A)
- JS忍者祕籍中的定時器機制詳解JS定時器
- 淺談JS事件機制與React事件機制JS事件React
- Android Handler機制之Message及Message回收機制Android
- Hystrix--熔斷
- SpringCould中的HystrixSpringGC
- 7、Spring Cloud HystrixSpringCloud