在微服務架構中,根據業務來拆分成一個個的服務,服務與服務之間可以相互調用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign來調用。為了保證其高可用,單個服務通常會集群部署。由於網絡原因或者自身的原因,服務並不能保證100%可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求涌入,Servlet容器的線程資源會被消耗完畢,導致服務癱瘓。
服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重后果,這就是服務故障的“雪崩”效應。為了解決這個問題,業界提出了斷路器模型。
一、斷路器簡介
Netflix開源了 Hystrix 組件,實現了斷路器模式,SpringCloud對這一組件進行了整合。 在微服務架構中,一個請求需要調用多個服務是非常常見的。
較底層的服務如果出現故障,會導致連鎖故障。當對特定的服務的調用的不可用達到一個閥值(Hystric 是5秒20次) 斷路器將會被打開。
斷路打開后,可用避免連鎖故障,fallback方法可以直接返回一個固定值。
二、斷路器的作用
在微服務架構中,存在着多個微服務,彼此之間可能存在依賴關系,當某個單元出現故障或者網絡不通時,就會因為依賴關系形成故障蔓延,最終導致整個系統的癱瘓,相對於傳統架構更加不穩定。為了解決這樣的問題,因此產生了斷路器模式。
斷路器本身是一種開關裝置,用於在電路上保護線路過載,當線路中有電器發生短路時,“斷路器”能夠及時切斷故障電源,防止發生過載、發熱甚至起火等嚴重后果。
在分布式架構中,斷路器模式的作用也是類似的,當某個服務單元發生故障(類似用電器發生短路)之后,通過斷路器的故障監控(類似熔斷保險絲),向調用方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得線程因調用故障服務被長時間占用不釋放,避免了故障在分布式系統中的蔓延。
當一個服務調用另一個服務由於網絡原因或者自身原因出現問題時 ,調用者就會等待被調者的響應,當更多的服務請求到這些資源時,導致更多的請求等待,這樣就會發生連鎖效應,斷路器就是解決這一問題的。
1、斷路器有完全打開狀態:一定時間內,達到一定的次數無法調用,並且多次檢測沒有恢復的跡象,斷路器完全打開,那么下次的請求不會請求到該服務。
2、半開狀態:短時間內有恢復跡象,斷路器會將部分請求發送給服務,當能正常調用時,斷路器關閉。
3、關閉狀態:當服務一直處於正常狀態,能正常調用,斷路器關閉。
三、Feign中使用斷路器
Feign是自帶斷路器的,在D版本的Spring Cloud中,它沒有默認打開。需要在配置文件中配置打開它,在配置文件加以下代碼:
feign.hystrix.enabled=true
// 基於service-feign工程進行改造,只需要在FeignClient的SchedualServiceHi接口的注解中加上fallback的指定類就行了:
@FeignClient(value = "service-hi",fallback = SchedualServiceHiHystric.class) public interface SchedualServiceHi { @RequestMapping(value = "/hi",method = RequestMethod.GET) String sayHiFromClientOne(@RequestParam(value = "name") String name); } // SchedualServiceHiHystric需要實現SchedualServiceHi 接口,並注入到Ioc容器中,代碼如下:
@Component public class SchedualServiceHiHystric implements SchedualServiceHi { @Override public String sayHiFromClientOne(String name) { return "sorry "+name; } }
啟動 servcie-feign工程,瀏覽器打開 http://localhost:8765/hi?name=forezp,注意此時 service-hi 工程沒有啟動,網頁顯示:sorry forezp。
打開 service-hi 工程,再次訪問,瀏覽器顯示:hi forezp,i am from port:8762,這證明斷路器起到作用了。