Spring Cloud 學習筆記06----斷路器(Hystrix)(Finchley版本)

簡介

接上一篇Spring Cloud 學習筆記04----服務消費者(RestTemplate+Ribbon(客戶端負載均衡)),接下來我們來學習另外一個組件 斷路器(Hystrix)。
在微服務架構中,我們將系統(tǒng)拆分成很多個獨立服務單元,服務與服務之間通過RPC的方式調用,在Spring Cloud 中可以通過RestTemplate+Ribbon 或者Feign 的方式調用。為了保證高可用性,單個服務通常會集群部署。這樣就有可能因為網絡原因或者是依賴服務自身問題出現調用故障或延遲,而這些問題會直接導致調用方的對外服務也出現延遲,若此時調用方的請求不斷增加,最后等待出現故障的依賴方響應形成任務積壓,最終導致自身服務的癱瘓。

斷路器(Hystrix)簡介

Netflix的創(chuàng)造了一個調用的庫Hystrix實現了斷路器圖案。在微服務架構中,通常有多層服務調用。
如圖所示,微服務圖

微服務圖
較低級別的服務中的服務故障可能導致用戶級聯(lián)故障。當對特定服務的調用的不可用達到一個閥值時(Hystrix中的默認值為5秒內的20次故障),斷路器打開,向調用方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得線程因調用故障服務被長時間占用不釋放,避免了故障在分布式系統(tǒng)中的蔓延。
如下圖. Hystrix回退防止級聯(lián)故障

在這里插入圖片描述

快速入門

在使用Spring Cloud Hystrix 實現斷路器之前。首先,我們先構建一個服務調用關系。
我們以上一篇的項目為基礎,首先啟動如下項目:
eureka-server 工程:服務注冊中心,端口1111
order-provider 工程: order-service的服務,兩個實例啟動端口分別是8081 和8082
service-ribbon 工程:使用Ribbon實現的服務消費者,端口為8764。
在未加入斷路器之前,關閉8081的實例,發(fā)送GET請求到http://localhost:8764/getOrderService,可以看到如下輸出
在這里插入圖片描述

引入Hystrix。

  1. 在service-ribbon 工程的pom.xml 引入 spring-cloud-starter-hystrix 依賴
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		</dependency>
  1. 在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ā)現以及斷路器。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
  1. 改造服務消費方式,在HelloService 類中,在getOrderService方法上增加@HystrixCommand注解。代碼如下:
  @HystrixCommand(fallbackMethod ="helloFallback" )
    public String getOrderService() {
        return restTemplate.getForObject("http://ORDER-SERVICE/dc",String.class);
    }

    public String helloFallback() {
        return "服務出現故障了";
    }

下面,我們來驗證一下斷路器實現的服務回調邏輯,重新啟動之前關閉的8081端口order-provider,確保此時服務注冊中心,兩個order-provider以及service-ribbon均已啟動,訪問http://localhost:8764/getOrderService 可以輪詢到兩個order-provider 并返回一些文字信息。當輪詢到8081時,輸出內容服務出現故障了,不再是之前的錯誤內容,Hystrix的服務回調生效。
在這里插入圖片描述
除了通過斷開具體的服務實例來模擬某個節(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接口的處理線程不是馬上返回內容,而是在阻塞幾秒之后才返回內容。由于Hystrix默認超時時間為2000毫秒,所以這里采取0至3000的隨機數以讓處理過程有一定概率發(fā)生超時來觸發(fā)斷路器。測試如下:
在這里插入圖片描述
在這里插入圖片描述

源碼地址

https://github.com/XWxiaowei/SpringCloud-Learning/tree/master/2-Finchley版教程示例/Chapter5-1

參考

【Spring Cloud 微服務實戰(zhàn) 第5章】




作者:碼農飛哥

微信公眾號:碼農飛哥