
Hystrix是什麼?
hystrix對應的中文名字是“豪豬”,豪豬周身長滿了刺,能保護自己不受天敵的傷害,代表了一種防禦機制,這與hystrix本身的功能不謀而合,是以Netflix團隊将該架構命名為Hystrix,并使用了對應的卡通形象做作為logo。
在一個分布式系統裡,許多依賴不可避免的會調用失敗,比如逾時、異常等,如何能夠保證在一個依賴出問題的情況下,不會導緻整體服務失敗,這個就是Hystrix需要做的事情。Hystrix提供了熔斷、隔離、Fallback、cache、監控等功能,能夠在一個、或多個依賴同時出現問題時保證系統依然可用。
為什麼需要Hystrix?
在大中型分布式系統中,通常系統很多依賴(HTTP,hession,Netty,Dubbo等),如下圖:
在高并發通路下,這些依賴的穩定性與否對系統的影響非常大,但是依賴有很多不可控問題:如網絡連接配接緩慢,資源繁忙,暫時不可用,服務脫機等。
如下圖:QPS為50的依賴 I 出現不可用,但是其他依賴仍然可用。
當依賴I 阻塞時,大多數伺服器的線程池就出現阻塞(BLOCK),影響整個線上服務的穩定性.如下圖:
在複雜的分布式架構的應用程式有很多的依賴,都會不可避免地在某些時候失敗。高并發的依賴失敗時如果沒有隔離措施,目前應用服務就有被拖垮的風險。
例如:一個依賴30個SOA服務的系統,每個服務99.99%可用。
99.99%的30次方 ≈ 99.7%
0.3% 意味着一億次請求 會有 3,000,00次失敗
換算成時間大約每月有2個小時服務不穩定.
随着服務依賴數量的變多,服務不穩定的機率會成指數性提高.
解決問題方案:對依賴做隔離,Hystrix就是處理依賴隔離的架構,同時也是可以幫我們做依賴服務的治理和監控。
Netflix 公司開發并成功使用Hystrix,使用規模如下:
The Netflix API processes 10+ billion HystrixCommand executions per day using thread isolation.
Each API instance has 40+ thread-pools with 5-20 threads in each (most are set to 10).
Hystrix如何解決依賴隔離?
Hystrix使用指令模式HystrixCommand(Command)包裝依賴調用邏輯,每個指令在單獨線程中/信号授權下執行。
可配置依賴調用逾時時間,逾時時間一般設為比99.5%平均時間略高即可.當調用逾時時,直接傳回或執行fallback邏輯。
為每個依賴提供一個小的線程池(或信号),如果線程池已滿調用将被立即拒絕,預設不采用排隊.加速失敗判定時間。
依賴調用結果分:成功,失敗(抛出異常),逾時,線程拒絕,短路。 請求失敗(異常,拒絕,逾時,短路)時執行fallback(降級)邏輯。
提供熔斷器元件,可以自動運作或手動調用,停止目前依賴一段時間(10秒),熔斷器預設錯誤率門檻值為50%,超過将自動運作。
提供近實時依賴的統計和監控。
Hystrix依賴的隔離架構,如下圖:
Hystrix應用實戰
Maven:
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.13</version>
</dependency>
源碼太多,不一一貼上來,這裡隻展示主要的測試源碼。
public static void main(String[] args) {
System.out.println(test("javastack"));
}
private static String test(String name) {
HystrixUtil.HystrixReqConfig hc = HystrixUtil.HystrixReqConfig.withGroupKey("TestGroup").withTimeout(3)
.withUnit(TimeUnit.SECONDS).withPassNum(64);
String result = HystrixUtil.getExcuteResult(new HystrixCallableService<String>() {
@Override
public String execute() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "success " + name;
}
@Override
public String fallback() {
return "fallback " + name;
}
}, hc);
return result;
}
這裡設定了3秒逾時進入熔斷。
測試程式中休眠5秒,進入熔斷器并輸出:
fallback javastack
測試程式中休眠2秒,進入正常流程并輸出:
success javastack
熔斷器測試成功,即使某個服務出問題,也不會影響整個系統的正常運作。