Hystrix是什么
在講Hystrix之前,應該先了解一下Netflix這家神奇的公司。
想必很多人都看過美劇《紙牌屋》,不過應該很少有人知道它的出品方就是Netflix,可以說是《紙牌屋》之父,同時愛奇藝、優(yōu)酷也是模仿Netflix的國內本土產品。作為一家在線影片租賃提供商,Netflix成立于1997年,在美國、加拿大提供互聯(lián)網(wǎng)隨選流媒體播放,定制DVD、藍光光碟在線出租業(yè)務,經(jīng)過多次商業(yè)模式的變革,Netflix成為了在線內容的霸主。據(jù)統(tǒng)計,Netflix在高峰期間的下載流量可以占到北美地區(qū)的1/3。
這里不得不提一點的是,從09年開始,Netflix逐漸把它的IT系統(tǒng)遷移到AWS云平臺上,并開始業(yè)務的轉型,從DVD租賃演變?yōu)樵诰€視頻供應商,依托于強大的AWS,這也給AWS帶來了巨大挑戰(zhàn)。
Netflix在AWS運行多年期間,總結了不少實踐經(jīng)驗,比如必須考慮到故障的可能性,在AWS云平臺上進行架構設計的一個經(jīng)驗法則是要作為一個悲觀主義者來設計應用架構:假設會出問題。
我們知道硬件總會發(fā)生故障,服務器會發(fā)生宕機,唯一不確定的就是在什么時候發(fā)生,所以在應用架構上要進行高可用設計,比如需要有一個清晰的數(shù)據(jù)備份和恢復機制,并自動化這個流程。
一個用戶看美劇看的好好的,后端提供該美劇的服務掛了,這時比較友好的方式是推送一部熱門的電影給用戶,這個動作即所謂的發(fā)生故障時的降級方案。
為此,Netflix API團隊在2011年啟動了彈性工程工作,即Hystrix,旨在通過控制那些訪問遠程系統(tǒng)、服務和第三方庫的節(jié)點,從而對延遲和故障提供更強大的容錯能力,提供了熔斷、隔離、Fallback、cache、監(jiān)控等功能,能夠在一個、或多個依賴同時出現(xiàn)問題時保證系統(tǒng)依然可用,目前它在Netflix每天處理著數(shù)百億的隔離線程以及數(shù)千億的隔離信號調用。
Hystrix是基于Apache License 2.0協(xié)議的開源的程序庫,目前托管在GitHub上。這個Star也是多的嚇人,足夠說明Hystrix的重要性。

什么場景可以使用
既然有了這么好的開源庫,必須得好好利用,那么具體都用在什么場景呢?下面以一個門票產品為例,大概描述一下使用場景。

在一個門票詳情的頁面中,可能最終依賴了很多個底層服務,比如推薦服務、評分服務、資源服務、優(yōu)惠服務、廣告服務等。仔細查看可以發(fā)現(xiàn),如果廣告、推薦、評分、優(yōu)惠等服務掛了,其實并不會影響整個下單流程,所以可以針對這些服務調用賦予熔斷降級的能力。
如果這些服務真的掛了,那么返回一個預設好的值即可,這樣用戶也幾乎察覺不出有什么異常。
如何使用Hystrix
目前Hystrix最新版本是1.5.13,在項目的pom文件中加上依賴
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.13</version>
</dependency>
Command方式
Hystrix提供了Command模式的接入方式,如果一個服務CommandHelloWorld需要熔斷降級的能力,那么只需要繼承Hystrix的HystrixCommand類,并重寫run方法和getFallback方法。
public class CommandHelloWorld extends HystrixCommand<String> {
private final String name;
public CommandHelloWorld(String name) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.name = name;
}
@Override
protected String run() {
// 省略業(yè)務邏輯
// 該方法可能會拋出異常
return "Hello " + name + "!";
}
@Override
protected String getFallback() {
return "Hello Failure " + name + "!";
}
}
這里需要注意的是,不能直接執(zhí)行run方法,這樣熔斷降級功能無法生效。
HystrixCommand內部提供了兩個方法:execute、queue
1、execute()
執(zhí)行HystrixCommand內部的execute方法,可以實現(xiàn)run方法的同步執(zhí)行
new CommandHelloWorld("hello").execute();
2、queue()
執(zhí)行HystrixCommand內部的queue方法,可以實現(xiàn)run方法的異步執(zhí)行
Future future = new CommandHelloWorld().queue();
String s = future.get();
如果依賴多個下游接口 ,通過異步方式,可以同時執(zhí)行,提高接口性能。
注解方式
如果覺得Command模式比較的繁瑣,Hystrix也提供了注解方式,不過必須引入hystrix-javanica,通過aspect的方式實現(xiàn)。
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>1.5.13</version>
</dependency>
并且在xml配置文件中加入
<aop:aspectj-autoproxy/>
<bean id="hystrixAspect" class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"></bean>
下面是注解方式的Helloworld
@Component
public class HystrixHelloworld {
@HystrixCommand(fallbackMethod = "fallback")
public String run() {
// 省略業(yè)務邏輯
// 該方法可能會拋出異常
return "Hello world!";
}
public String fallback() {
return "fallback";
}
在需要進行熔斷降級的方法上加@HystrixCommand注解,并指定fallbackMethod,這里需要注意的是,被指定的fallback方法,其返回和參數(shù)申明和主方法需要保持一致。
什么時候熔斷
默認情況下,如果run方法在運行期間,10秒總請求數(shù)超過20個,且有50%以上的請求發(fā)生異常,Hystrix內部會自動發(fā)生熔斷,并且執(zhí)行getFallback方法。
什么時候恢復
默認情況下,如果發(fā)生了熔斷,Hystrix內部每隔5s進行一次試探,即放過一個正常請求到后端服務,如果這個請求成功了,就算后端服務恢復了,Hystrix內部會自動關閉熔斷。