Spring Cloud(四)斷路器(Hystrix)
一、Hystrix簡介
在微服務架構中,我們將系統拆分成了一個個的服務單元,各單元間通過服務註冊與訂閱的方式互相依賴。由於每個單元都在不同的程序中執行,依賴通過遠端呼叫的方式執行,這樣就有可能因為網路原因或是依賴服務自身問題出現呼叫故障或延遲,而這些問題會直接導致呼叫方的對外服務也出現延遲,若此時呼叫方的請求不斷增加,最後就會出現因等待出現故障的依賴方響應而形成任務積壓,最終導致自身服務的癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的“雪崩”效應。 斷路器(Circuit Breaker)模式: 為了解決上述問題,因此產生了斷路器模式。
斷路器本身是一種開關裝置,用於在電路上保護線路過載,當線路中有電器發生短路時,“斷路器”能夠及時的切斷故障電路,防止發生過載、發熱、甚至起火等嚴重後果。
在分散式架構中,斷路器模式的作用也是類似的,當某個服務單元發生故障(類似用電器發生短路)之後,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得執行緒因呼叫故障服務被長時間佔用不釋放,避免了故障在分散式系統中的蔓延。在Spring Cloud中使用了Hystrix 來實現斷路器的功能。接著我們使用前面建立的專案分別在服務消費斷Ribbn與Feign中使用斷路由模式:
二、在Ribbon中整合Hystrix斷路由
2.1 pom中增加Hystrix依賴
改造上節中ribbon-consumer 工程的程式碼,首先在pox.xml檔案中加入spring-cloud-starter-netflix-hystrix的起步依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.2 加@EnableHystrix註解
在springboot啟動類中 加@EnableHystrix註解開啟Hystrix:
@SpringBootApplication @EnableEurekaClient @EnableHystrix public class RibbonConsumerApplication { public static void main(String[] args) { SpringApplication.run(RibbonConsumerApplication.class, args); } @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } }
2.3 改造HelloService類
改造HelloService類,在hiService方法上加上@HystrixCommand註解。該註解對該方法建立了熔斷器的功能,並指定了fallbackMethod熔斷方法,熔斷方法直接返回了一個字串,字串為”hi,”+name+”,sorry,error!”,程式碼如下:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError")
public String hiService(String name) {
return restTemplate.getForObject("http://eureka-client/hello",String.class);
}
//Fall Back method
public String hiError(String name) {
return "hi,"+name+",sorry,error!";
}
}
2.4 驗證結果
啟動註冊中心,啟動ribbon-consumer,當我們訪問http://localhost:8083/hi/payne,瀏覽器顯示: 可以看到,當外部介面不能訪問的時候,程式直接呼叫fallback指定的方法返回結果,從而不需要阻塞當前執行緒,從而導致訪問請求一直處於等待 當啟動eureka-client,再次訪問的時候
hi ,i am from port:8081
三、Feign中使用斷路器
Feign是自帶斷路器的,因此不需要人為引用Hystrix依賴包
3.1 FeignClient介面改造
基於feign-consumer工程進行改造,只需要在FeignClient的HelloService介面的註解中加上fallback的指定類就行了:
@FeignClient(value = "eureka-client",fallback = FallBackHelloService.class)
public interface HelloService {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hiService();
}
3.2 新增FallBack指定類
FallBackHelloService需要實現HelloService 介面,並注入到Ioc容器中,程式碼如下:
@Component
public class FallBackHelloService implements HelloService{
@Override
public String hiService() {
return "Sorry,this is fall back method";
}
}
3.3 驗證結果
訪問地址: http://localhost:8084/hi 開啟eureka-client工程,再次訪問,瀏覽器又返回正常結構,說明我們的斷路由已經生效。