Hystrix是什么
在微服務(wù)架構(gòu)中,我們是將一個(gè)單體應(yīng)用拆分成多個(gè)服務(wù)單元,各個(gè)服務(wù)單元之間通過(guò)注冊(cè)中心彼此發(fā)現(xiàn)和消費(fèi)對(duì)方提供的服務(wù),每個(gè)服務(wù)單元都是單獨(dú)部署,在各自的服務(wù)進(jìn)程中運(yùn)行,服務(wù)之間通過(guò)遠(yuǎn)程調(diào)用實(shí)現(xiàn)信息交互,那么當(dāng)某個(gè)服務(wù)的響應(yīng)太慢或者故障,又或者因?yàn)榫W(wǎng)絡(luò)波動(dòng)或故障,則會(huì)造成調(diào)用者延遲或調(diào)用失敗,當(dāng)大量請(qǐng)求到達(dá),則會(huì)造成請(qǐng)求的堆積,導(dǎo)致調(diào)用者的線程掛起,從而引發(fā)調(diào)用者也無(wú)法響應(yīng),調(diào)用者也發(fā)生故障。
比如電商中的用戶下訂單,我們有兩個(gè)服務(wù),一個(gè)下訂單服務(wù),一個(gè)減庫(kù)存服務(wù),當(dāng)用戶下訂單時(shí)調(diào)用下訂單服務(wù),然后下訂單服務(wù)又調(diào)用減庫(kù)存服務(wù),如果減庫(kù)存服務(wù)響應(yīng)延遲或者沒(méi)有響應(yīng),則會(huì)造成下訂單服務(wù)的線程掛起等待,如果大量的用戶請(qǐng)求下訂單,或?qū)е麓罅康恼?qǐng)求堆積,引起下訂單服務(wù)也不可用,如果還有另外一個(gè)服務(wù)依賴于訂單服務(wù),比如用戶服務(wù),它需要查詢用戶訂單,那么用戶服務(wù)查詢訂單也會(huì)引起大量的延遲和請(qǐng)求堆積,導(dǎo)致用戶服務(wù)也不可用。
所以在微服務(wù)架構(gòu)中,很容易造成服務(wù)故障的蔓延,引發(fā)整個(gè)微服務(wù)系統(tǒng)癱瘓不可用。
為了解決此問(wèn)題,微服務(wù)架構(gòu)中引入了一種叫熔斷器的服務(wù)保護(hù)機(jī)制。
熔斷器也有叫斷路器,他們表示同一個(gè)意思,最早來(lái)源于微服務(wù)之父Martin Fowler的論文CircuitBreaker一文。“熔斷器”本身是一種開(kāi)關(guān)裝置,用于在電路上保護(hù)線路過(guò)載,當(dāng)線路中有電器發(fā)生短路時(shí),能夠及時(shí)切斷故障電路,防止發(fā)生過(guò)載、發(fā)熱甚至起火等嚴(yán)重后果。
微服務(wù)架構(gòu)中的熔斷器,就是當(dāng)被調(diào)用方?jīng)]有響應(yīng),調(diào)用方直接返回一個(gè)錯(cuò)誤響應(yīng)即可,而不是長(zhǎng)時(shí)間的等待,這樣避免調(diào)用時(shí)因?yàn)榈却€程一直得不到釋放,避免故障在分布式系統(tǒng)間蔓延;
Spring Cloud Hystrix實(shí)現(xiàn)了熔斷器、線程隔離等一系列服務(wù)保護(hù)功能。該功能也是基于Netflix的開(kāi)源框架Hystrix實(shí)現(xiàn)的,該框架的目標(biāo)在于通過(guò)控制那些訪問(wèn)遠(yuǎn)程系統(tǒng)、服務(wù)和第三方庫(kù)的節(jié)點(diǎn),從而對(duì)延遲和故障提供更強(qiáng)大的容錯(cuò)能力。Hystrix具備服務(wù)降級(jí)、服務(wù)熔斷、線程和信號(hào)隔離、請(qǐng)求緩存、請(qǐng)求合并以及服務(wù)監(jiān)控等強(qiáng)大功能。
在SpringCloud中使用熔斷器Hystrix是非常簡(jiǎn)單和方便的,只需要簡(jiǎn)單兩步即可:
1、添加依賴
<!--Spring Cloud熔斷器起步依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
2、在入口類中使用@EnableCircuitBreaker注解開(kāi)啟斷路器功能,也可以使用一個(gè)名為@SpringCloudApplication的注解代替主類上的三個(gè)注解;
3、在調(diào)用遠(yuǎn)程服務(wù)的方法上添加注解:@HystrixCommand(fallbackMethod="error")
hystrix默認(rèn)超時(shí)時(shí)間是1000毫秒,如果你后端的響應(yīng)超過(guò)此時(shí)間,就會(huì)觸發(fā)斷路器;
修改hystrix的默認(rèn)超時(shí)時(shí)間:
@HystrixCommand(fallbackMethod="error", commandProperties={
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1500")}) //熔斷器,調(diào)用不通,回調(diào)error()方法
public String webHello () {
Hystrix的服務(wù)降級(jí)
有了服務(wù)的熔斷,隨之就會(huì)有服務(wù)的降級(jí),所謂服務(wù)降級(jí),就是當(dāng)某個(gè)服務(wù)熔斷之后,服務(wù)端提供的服務(wù)將不再被調(diào)用,此時(shí)由客戶端自己準(zhǔn)備一個(gè)本地的fallback回調(diào),返回一個(gè)默認(rèn)值來(lái)代表服務(wù)端的返回;
這種做法,雖然不能得到正確的返回結(jié)果,但至少保證了服務(wù)的可用,比直接拋出錯(cuò)誤或服務(wù)不可用要好很多,當(dāng)然這需要根據(jù)具體的業(yè)務(wù)場(chǎng)景來(lái)選擇;
我們?cè)谡{(diào)用服務(wù)提供者時(shí),我們自己也有可能會(huì)拋異常,默認(rèn)情況下方法拋了異常會(huì)自動(dòng)進(jìn)行服務(wù)降級(jí),交給服務(wù)降級(jí)中的方法去處理;
當(dāng)我們自己發(fā)生異常后,只需要在服務(wù)降級(jí)方法中添加一個(gè)Throwable類型的參數(shù)就能夠獲取到拋出的異常的類型,如下:
public String error(Throwable throwable) {
System.out.println(throwable.getMessage());
return "error";
}
此時(shí)我們可以在控制臺(tái)看到異常的類型;
如果遠(yuǎn)程服務(wù)有一個(gè)異常拋出后我們不希望進(jìn)入到服務(wù)降級(jí)方法中去處理,而是直接將異常拋給用戶,那么我們可以在@HystrixCommand注解中添加忽略異常,如下:
@HystrixCommand(fallbackMethod="error", ignoreExceptions = Exception.class)
自定義Hystrix請(qǐng)求的服務(wù)異常熔斷處理
我們也可以自定義類繼承自HystrixCommand來(lái)實(shí)現(xiàn)自定義的Hystrix請(qǐng)求,在getFallback方法中調(diào)用getExecutionException方法來(lái)獲取服務(wù)拋出的異常;
com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(""))
Hystrix儀表盤(Hystrix Dashboard),就像汽車的儀表盤實(shí)時(shí)顯示汽車的各項(xiàng)數(shù)據(jù)一樣,Hystrix儀表盤主要用來(lái)監(jiān)控Hystrix的實(shí)時(shí)運(yùn)行狀態(tài),通過(guò)它我們可以看到Hystrix的各項(xiàng)指標(biāo)信息,從而快速發(fā)現(xiàn)系統(tǒng)中存在的問(wèn)題進(jìn)而解決它。
要使用Hystrix儀表盤功能,我們首先需要有一個(gè)Hystrix Dashboard,這個(gè)功能我們可以在原來(lái)的消費(fèi)者應(yīng)用上添加,讓原來(lái)的消費(fèi)者應(yīng)用具備Hystrix儀表盤功能,但一般地,微服務(wù)架構(gòu)思想是推崇服務(wù)的拆分,Hystrix Dashboard也是一個(gè)服務(wù),所以通常會(huì)單獨(dú)創(chuàng)建一個(gè)新的工程專門用做Hystrix Dashboard服務(wù);
第一步:創(chuàng)建一個(gè)普通的Spring Boot工程
比如創(chuàng)建一個(gè)名為springcloud-hystrix-dashboard的Spring Boot工程,建立好基本的結(jié)構(gòu)和配置;
第二步:添加相關(guān)依賴
在創(chuàng)建好的Spring Boot項(xiàng)目的 pom.xml文件中添加相關(guān)依賴,如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
第三步:入口類上添加注解
添加好依賴之后,在入口類上添加@EnableHystrixDashboard注解開(kāi)啟儀表盤功能,如下:
@SpringBootApplication
@EnableHystrixDashboard
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
第四步:屬性配置
最后,我們可以根據(jù)個(gè)人習(xí)慣配置一下application.properties文件,如下:server.port=3721
至此,我們的Hystrix監(jiān)控環(huán)境就搭建好了;
Hystrix儀表盤工程已經(jīng)創(chuàng)建好了,現(xiàn)在我們需要有一個(gè)服務(wù),讓這個(gè)服務(wù)提供一個(gè)路徑為/actuator/hystrix.stream接口,然后就可以使用Hystrix儀表盤來(lái)對(duì)該服務(wù)進(jìn)行監(jiān)控了;
我們改造消費(fèi)者服務(wù),讓其能提供/actuator/hystrix.stream接口,步驟如下:
1、消費(fèi)者項(xiàng)目需要有hystrix的依賴:
<!--Spring Cloud熔斷器起步依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
2、需要有一個(gè)spring boot的服務(wù)監(jiān)控依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
3、配置文件需要配置spring boot監(jiān)控端點(diǎn)的訪問(wèn)權(quán)限:
management.endpoints.web.exposure.include=*
這個(gè)是用來(lái)暴露 endpoints 的,由于 endpoints 中會(huì)包含很多敏感信息,除了 health 和 info 兩個(gè)支持直接訪問(wèn)外,其他的默認(rèn)不能直接訪問(wèn),所以我們讓它都能訪問(wèn),或者指定:
management.endpoints.web.exposure.include=hystrix.stream
4、訪問(wèn)入口 http://localhost:8081/actuator/hystrix.stream
注意:這里有一個(gè)細(xì)節(jié)需要注意,要訪問(wèn)/hystrix.stream接口,首先得訪問(wèn)consumer工程中的任意一個(gè)其他接口,否則直接訪問(wèn)/hystrix.stream接口時(shí)會(huì)輸出出一連串的ping: ping: …,先訪問(wèn)consumer中的任意一個(gè)其他接口,然后再訪問(wèn)/hystrix.stream接口即可;