Spring Cloud 學習筆記06----斷路器(Hystrix)(Finchley版本)
簡介
接上一篇Spring Cloud 學習筆記04----服務消費者(RestTemplate+Ribbon(客戶端負載均衡)),接下來我們來學習另外一個組件 斷路器(Hystrix)。
在微服務架構(gòu)中,我們將系統(tǒng)拆分成很多個獨立服務單元,服務與服務之間通過RPC的方式調(diào)用,在Spring Cloud 中可以通過RestTemplate+Ribbon 或者Feign 的方式調(diào)用。為了保證高可用性,單個服務通常會集群部署。這樣就有可能因為網(wǎng)絡原因或者是依賴服務自身問題出現(xiàn)調(diào)用故障或延遲,而這些問題會直接導致調(diào)用方的對外服務也出現(xiàn)延遲,若此時調(diào)用方的請求不斷增加,最后等待出現(xiàn)故障的依賴方響應形成任務積壓,最終導致自身服務的癱瘓。
斷路器(Hystrix)簡介
Netflix的創(chuàng)造了一個調(diào)用的庫Hystrix實現(xiàn)了斷路器圖案。在微服務架構(gòu)中,通常有多層服務調(diào)用。
如圖所示,微服務圖
較低級別的服務中的服務故障可能導致用戶級聯(lián)故障。當對特定服務的調(diào)用的不可用達到一個閥值時(Hystrix中的默認值為5秒內(nèi)的20次故障),斷路器打開,向調(diào)用方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得線程因調(diào)用故障服務被長時間占用不釋放,避免了故障在分布式系統(tǒng)中的蔓延。
如下圖. Hystrix回退防止級聯(lián)故障
快速入門
在使用Spring Cloud Hystrix 實現(xiàn)斷路器之前。首先,我們先構(gòu)建一個服務調(diào)用關系。
我們以上一篇的項目為基礎,首先啟動如下項目:
eureka-server 工程:服務注冊中心,端口1111
order-provider 工程: order-service的服務,兩個實例啟動端口分別是8081 和8082
service-ribbon 工程:使用Ribbon實現(xiàn)的服務消費者,端口為8764。
在未加入斷路器之前,關閉8081的實例,發(fā)送GET請求到http://localhost:8764/getOrderService,可以看到如下輸出
引入Hystrix。
- 在service-ribbon 工程的pom.xml 引入 spring-cloud-starter-hystrix 依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 在service-ribbon 工程的主類ServiceRibbonApplication中使用
@EnableCircuitBreaker
注解開啟斷路器功能:
@SpringBootApplication
@EnableEurekaClient //ribbon
@EnableCircuitBreaker //斷路器
@SpringCloudApplication
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced //開啟負載均衡
RestTemplate restTemplate() {
return new RestTemplate();
}
}
PS: 這里可以使用Spring Cloud應用中的@SpringCloudApplication注解來修飾應用主類,該注解的具體定義如下所示??梢钥吹?,該注解中包含了上述我們所引用的三個注解, 這也意味著一個Spring Cloud 標準應用包含服務發(fā)現(xiàn)以及斷路器。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
- 改造服務消費方式,在HelloService 類中,在getOrderService方法上增加
@HystrixCommand
注解。代碼如下:
@HystrixCommand(fallbackMethod ="helloFallback" )
public String getOrderService() {
return restTemplate.getForObject("http://ORDER-SERVICE/dc",String.class);
}
public String helloFallback() {
return "服務出現(xiàn)故障了";
}
下面,我們來驗證一下斷路器實現(xiàn)的服務回調(diào)邏輯,重新啟動之前關閉的8081端口order-provider,確保此時服務注冊中心,兩個order-provider以及service-ribbon均已啟動,訪問http://localhost:8764/getOrderService 可以輪詢到兩個order-provider 并返回一些文字信息。當輪詢到8081時,輸出內(nèi)容服務出現(xiàn)故障了
,不再是之前的錯誤內(nèi)容,Hystrix的服務回調(diào)生效。
除了通過斷開具體的服務實例來模擬某個節(jié)點無法訪問的情況之外,我們還可以模擬一下服務阻塞的情況,我們對order-provider中增加/hello
接口,具體如下:
@GetMapping("/hello")
public String hello(HttpServletRequest request) throws InterruptedException {
// 讓處理線程等待幾分鐘
int sleepTime = new Random().nextInt(3000);
Thread.sleep(sleepTime);
String services = "Services: " + discoveryClient.getServices() + ";port=" + request.getServerPort();
System.out.println(services);
return "hello world";
}
通過Thread.sleep()方法可以讓/hello
接口的處理線程不是馬上返回內(nèi)容,而是在阻塞幾秒之后才返回內(nèi)容。由于Hystrix默認超時時間為2000毫秒,所以這里采取0至3000的隨機數(shù)以讓處理過程有一定概率發(fā)生超時來觸發(fā)斷路器。測試如下:
源碼地址
https://github.com/XWxiaowei/SpringCloud-Learning/tree/master/2-Finchley版教程示例/Chapter5-1
參考
【Spring Cloud 微服務實戰(zhàn) 第5章】
作者:碼農(nóng)飛哥
微信公眾號:碼農(nóng)飛哥