Spring Cloud構(gòu)建微服務(wù)架構(gòu) 斷路器(服務(wù)器熔斷)

原文鏈接:http://blog.didispace.com/springcloud3/

在微服務(wù)架構(gòu)中,我們將系統(tǒng)拆分成了一個個的服務(wù)單元,各單元間通過服務(wù)注冊與訂閱的方式互相依賴。由于每個單元都在不同的進(jìn)程中運(yùn)行,依賴通過遠(yuǎn)程調(diào)用的方式執(zhí)行,這樣就有可能因為網(wǎng)絡(luò)原因或是依賴服務(wù)自身問題出現(xiàn)調(diào)用故障或延遲,而這些問題會直接導(dǎo)致調(diào)用方的對外服務(wù)也出現(xiàn)延遲,若此時調(diào)用方的請求不斷增加,最后就會出現(xiàn)因等待出現(xiàn)故障的依賴方響應(yīng)而形成任務(wù)積壓,最終導(dǎo)致自身服務(wù)的癱瘓。

舉個例子,在一個電商網(wǎng)站中,我們可能會將系統(tǒng)拆分成,用戶、訂單、庫存、積分、評論等一系列的服務(wù)單元。用戶創(chuàng)建一個訂單的時候,在調(diào)用訂單服務(wù)創(chuàng)建訂單的時候,會向庫存服務(wù)來請求出貨(判斷是否有足夠庫存來出貨)。此時若庫存服務(wù)因網(wǎng)絡(luò)原因無法被訪問到,導(dǎo)致創(chuàng)建訂單服務(wù)的線程進(jìn)入等待庫存申請服務(wù)的響應(yīng),在漫長的等待之后用戶會因為請求庫存失敗而得到創(chuàng)建訂單失敗的結(jié)果。如果在高并發(fā)情況之下,因這些等待線程在等待庫存服務(wù)的響應(yīng)而未能釋放,使得后續(xù)到來的創(chuàng)建訂單請求被阻塞,最終導(dǎo)致訂單服務(wù)也不可用。

在微服務(wù)架構(gòu)中,存在著那么多的服務(wù)單元,若一個單元出現(xiàn)故障,就會因依賴關(guān)系形成故障蔓延,最終導(dǎo)致整個系統(tǒng)的癱瘓,這樣的架構(gòu)相較傳統(tǒng)架構(gòu)就更加的不穩(wěn)定。為了解決這樣的問題,因此產(chǎn)生了斷路器模式。

什么是斷路器

斷路器模式源于Martin Fowler的Circuit Breaker一文。“斷路器”本身是一種開關(guān)裝置,用于在電路上保護(hù)線路過載,當(dāng)線路中有電器發(fā)生短路時,“斷路器”能夠及時的切斷故障電路,防止發(fā)生過載、發(fā)熱、甚至起火等嚴(yán)重后果。

在分布式架構(gòu)中,斷路器模式的作用也是類似的,當(dāng)某個服務(wù)單元發(fā)生故障(類似用電器發(fā)生短路)之后,通過斷路器的故障監(jiān)控(類似熔斷保險絲),向調(diào)用方返回一個錯誤響應(yīng),而不是長時間的等待。這樣就不會使得線程因調(diào)用故障服務(wù)被長時間占用不釋放,避免了故障在分布式系統(tǒng)中的蔓延。

Netflix Hystrix

在Spring Cloud中使用了Hystrix?來實現(xiàn)斷路器的功能。Hystrix是Netflix開源的微服務(wù)框架套件之一,該框架目標(biāo)在于通過控制那些訪問遠(yuǎn)程系統(tǒng)、服務(wù)和第三方庫的節(jié)點,從而對延遲和故障提供更強(qiáng)大的容錯能力。Hystrix具備擁有回退機(jī)制和斷路器功能的線程和信號隔離,請求緩存和請求打包,以及監(jiān)控和配置等功能。

下面我們來看看如何使用Hystrix。

準(zhǔn)備工作

在開始加入斷路器之前,我們先拿之前構(gòu)建兩個微服務(wù)為基礎(chǔ)進(jìn)行下面的操作,主要使用下面幾個工程:

chapter9-1-1

eureka-server工程:服務(wù)注冊中心,端口1111

compute-service工程:服務(wù)單元,端口2222

chapter9-1-2

eureka-ribbon:通過ribbon實現(xiàn)的服務(wù)單元,依賴compute-service的服務(wù),端口3333

eureka-feign:通過feign實現(xiàn)的服務(wù)單元,依賴compute-service的服務(wù),端口3333

若您還沒有使用Spring Cloud的經(jīng)驗,可以先閱讀《服務(wù)注冊與發(fā)現(xiàn)》《服務(wù)消費者》,對Spring Cloud構(gòu)建的微服務(wù)有一個初步的認(rèn)識。

Ribbon中引入Hystrix

依次啟動eureka-server、compute-service、eureka-ribbon工程

訪問http://localhost:1111/可以看到注冊中心的狀態(tài)

訪問http://localhost:3333/add,調(diào)用eureka-ribbon的服務(wù),該服務(wù)會去調(diào)用compute-service的服務(wù),計算出10+20的值,頁面顯示30

關(guān)閉compute-service服務(wù),訪問http://localhost:3333/add,我們獲得了下面的報錯信息

Whitelabel Error Page

This application has no explicit mappingfor/error, so you are seeing this as a fallback.

Sat Jun 25 21:16:59 CST 2016

There was an unexpected error (type=Internal Server Error, status=500).

I/O error on GET requestfor"http://COMPUTE-SERVICE/add?a=10&b=20": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect

pom.xml中引入依賴hystrix依賴

org.springframework.cloud

spring-cloud-starter-hystrix

在eureka-ribbon的主類RibbonApplication中使用@EnableCircuitBreaker注解開啟斷路器功能:

@SpringBootApplication

@EnableDiscoveryClient

@EnableCircuitBreaker

publicclassRibbonApplication{

@Bean

@LoadBalanced

RestTemplaterestTemplate(){

returnnewRestTemplate();

}

publicstaticvoidmain(String[] args){

SpringApplication.run(RibbonApplication.class, args);

}

}

改造原來的服務(wù)消費方式,新增ComputeService類,在使用ribbon消費服務(wù)的函數(shù)上增加@HystrixCommand注解來指定回調(diào)方法。

@Service

publicclassComputeService{

@Autowired

? ? RestTemplate restTemplate;

@HystrixCommand(fallbackMethod ="addServiceFallback")

publicStringaddService(){

returnrestTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody();

? ? }

publicStringaddServiceFallback(){

return"error";

? ? }

}

提供rest接口的Controller改為調(diào)用ComputeService的addService

@RestController

publicclassConsumerController{

@Autowired

privateComputeService computeService;

@RequestMapping(value ="/add", method = RequestMethod.GET)

publicStringadd(){

returncomputeService.addService();

? ? }

}

驗證斷路器的回調(diào)

依次啟動eureka-server、compute-service、eureka-ribbon工程

訪問http://localhost:1111/可以看到注冊中心的狀態(tài)

訪問http://localhost:3333/add,頁面顯示:30

關(guān)閉compute-service服務(wù)后再訪問http://localhost:3333/add,頁面顯示:error

Feign使用Hystrix

注意這里說的是“使用”,沒有錯,我們不需要在Feigh工程中引入Hystix,F(xiàn)eign中已經(jīng)依賴了Hystrix,我們可以在未做任何改造前,嘗試下面你的操作:

依次啟動eureka-server、compute-service、eureka-feign工程

訪問http://localhost:1111/可以看到注冊中心的狀態(tài)

訪問http://localhost:3333/add,調(diào)用eureka-feign的服務(wù),該服務(wù)會去調(diào)用compute-service的服務(wù),計算出10+20的值,頁面顯示30

關(guān)閉compute-service服務(wù),訪問http://localhost:3333/add,我們獲得了下面的報錯信息

Whitelabel Error Page

This application has no explicit mappingfor/error, so you are seeing this as a fallback.

Sat Jun 25 22:10:05 CST 2016

There was an unexpected error (type=Internal Server Error, status=500).

add timed-out and no fallback available.

如果您夠仔細(xì),會發(fā)現(xiàn)與在ribbon中的報錯是不同的,看到add timed-out and no fallback available這句,或許您已經(jīng)猜到什么,看看我們的控制臺,可以看到報錯信息來自hystrix-core-1.5.2.jar,所以在這個工程中,我們要學(xué)習(xí)的就是如何使用Feign中集成的Hystrix。

使用@FeignClient注解中的fallback屬性指定回調(diào)類

@FeignClient(value ="compute-service", fallback = ComputeClientHystrix.class)

publicinterfaceComputeClient{

@RequestMapping(method = RequestMethod.GET, value ="/add")

Integeradd(@RequestParam(value ="a")Integer a, @RequestParam(value ="b")Integer b);

}

創(chuàng)建回調(diào)類ComputeClientHystrix,實現(xiàn)@FeignClient的接口,此時實現(xiàn)的方法就是對應(yīng)@FeignClient接口中映射的fallback函數(shù)。

@Component

publicclassComputeClientHystriximplementsComputeClient{

@Override

publicIntegeradd(@RequestParam(value ="a")Integer a, @RequestParam(value ="b")Integer b){

return-9999;

? ? }

}

再用之前的方法驗證一下,是否在compute-service服務(wù)不可用的情況下,頁面返回了-9999。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容