Spring Cloud(五)斷路器監控(Hystrix Dashboard)

搜雲庫技術團隊發表於2017-12-08

在上兩篇文章中講了,服務提供者 Eureka + 服務消費者 Feign,服務提供者 Eureka + 服務消費者(rest + Ribbon),本篇文章結合,上兩篇文章中程式碼進行修改加入 斷路器監控(Hystrix Dashboard)

在微服務架構中,根據業務來拆分成一個個的服務,服務與服務之間可以相互呼叫(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign來呼叫。為了保證其高可用,單個服務通常會叢集部署。由於網路原因或者自身的原因,服務並不能保證100%可用,如果單個服務出現問題,呼叫這個服務就會出現執行緒阻塞,此時若有大量的請求湧入,Servlet容器的執行緒資源會被消耗完畢,導致服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的“雪崩”效應。

針對上述問題,在Spring Cloud Hystrix中實現了執行緒隔離、斷路器等一系列的服務保護功能。它也是基於Netflix的開源框架 Hystrix實現的,該框架目標在於通過控制那些訪問遠端系統、服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。Hystrix具備了服務降級、服務熔斷、執行緒隔離、請求快取、請求合併以及服務監控等強大功能。

什麼是斷路器

斷路器模式源於Martin Fowler的Circuit Breaker一文。“斷路器”本身是一種開關裝置,用於在電路上保護線路過載,當線路中有電器發生短路時,“斷路器”能夠及時的切斷故障電路,防止發生過載、發熱、甚至起火等嚴重後果。

在分散式架構中,斷路器模式的作用也是類似的,當某個服務單元發生故障(類似用電器發生短路)之後,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得執行緒因呼叫故障服務被長時間佔用不釋放,避免了故障在分散式系統中的蔓延。

斷路器示意圖

SpringCloud Netflix實現了斷路器庫的名字叫Hystrix. 在微服務架構下,通常會有多個層次的服務呼叫. 下面是微服架構下, 瀏覽器端通過API訪問後臺微服務的一個示意圖:

hystrix 1

一個微服務的超時失敗可能導致瀑布式連鎖反映,下圖中,Hystrix通過自主反饋實現的斷路器, 防止了這種情況發生。

hystrix 2

圖中的服務B因為某些原因失敗,變得不可用,所有對服務B的呼叫都會超時。當對B的呼叫失敗達到一個特定的閥值(5秒之內發生20次失敗是Hystrix定義的預設值), 鏈路就會被處於open狀態, 之後所有所有對服務B的呼叫都不會被執行, 取而代之的是由斷路器提供的一個表示鏈路open的Fallback訊息. Hystrix提供了相應機制,可以讓開發者定義這個Fallbak訊息.

open的鏈路阻斷了瀑布式錯誤, 可以讓被淹沒或者錯誤的服務有時間進行修復。這個fallback可以是另外一個Hystrix保護的呼叫, 靜態資料,或者合法的空值. Fallbacks可以組成鏈式結構,所以,最底層呼叫其它業務服務的第一個Fallback返回靜態資料.

準備工作

在開始加入斷路器之前,我們先拿之前兩篇部落格,構建的兩個微服務程式碼為基礎,進行下面的操作

建議先閱讀以下兩篇文章

Spring Cloud(四) 服務提供者 Eureka + 服務消費者 Feign
Spring Cloud(三) 服務提供者 Eureka + 服務消費者(rest + Ribbon)

Eureka Service

匯入第三篇文章中的專案:作為服務註冊中心

spring-cloud-eureka-service

Eureka Provider

匯入第三篇文章中的專案:作為服務的提供者

spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3

Ribbon Hystrix

在 Ribbon中使用斷路器

修改專案

複製 spring-cloud-ribbon-consumer 專案,修改名稱為spring-cloud-ribbon-consumer-hystrix

新增依賴

在專案pom 加上hystrix的依賴

<!-- hystrix 斷路器 -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
複製程式碼

服務註冊

在程式的啟動類 RibbonConsumerApplication 通過 @EnableHystrix 開啟 Hystrix 斷路器監控

package io.ymq.example.ribbon.consumer.hystrix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableHystrix
@EnableDiscoveryClient
@SpringBootApplication
public class RibbonConsumerApplication {

    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

	public static void main(String[] args) {
		SpringApplication.run(RibbonConsumerApplication.class, args);
	}
}
複製程式碼

消費提供者方法

修改 ConsumerController 類的,hello 方法,加上註解@HystrixCommand(fallbackMethod = "defaultStores") 該註解對該方法建立了熔斷器的功能 ,並指定了defaultStores熔斷方法,熔斷方法直接返回了一個字串, "feign + hystrix ,提供者服務掛了"

@HystrixCommand 表明該方法為hystrix包裹,可以對依賴服務進行隔離、降級、快速失敗、快速重試等等hystrix相關功能 該註解屬性較多,下面講解其中幾個

  • fallbackMethod 降級方法
  • commandProperties 普通配置屬性,可以配置HystrixCommand對應屬性,例如採用執行緒池還是訊號量隔離、熔斷器熔斷規則等等
  • ignoreExceptions 忽略的異常,預設HystrixBadRequestException不計入失敗
  • groupKey() 組名稱,預設使用類名稱
  • commandKey 命令名稱,預設使用方法名
package io.ymq.example.ribbon.consumer.hystrix;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 描述:呼叫提供者的 `home` 方法
 *
 * @author yanpenglei
 * @create 2017-12-05 18:53
 **/
@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "defaultStores")
    @GetMapping(value = "/hello")
    public String hello() {
        return restTemplate.getForEntity("http://eureka-provider/", String.class).getBody();
    }

    public String defaultStores() {
        return "Ribbon + hystrix ,提供者服務掛了";
    }

}
複製程式碼

測試斷路器

依次啟動專案:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-ribbon-consumer-hystrix

啟動該工程後,訪問服務註冊中心,檢視服務是否都已註冊成功:http://localhost:8761/

檢視各個服務註冊狀態

在命令視窗curl http://localhost:9000/hello,發現一切正常

或者瀏覽器get 請求http://localhost:9000/hello F5 重新整理

eureka-provider 提供者服務響應

停止 spring-cloud-eureka-provider-1 提供者,埠為:8081服務

再次訪問命令視窗curl http://localhost:9000/hello ,斷路器已經生效,提示:Ribbon + hystrix ,提供者服務掛了

Ribbon + hystrix ,提供者服務掛了

Feign Hystrix

在 Feign中使用斷路器

修改專案

複製spring-cloud-feign-consumer 專案,修改名稱為spring-cloud-feign-consumer-hystrix

新增依賴

Feign是自帶斷路器的,如果在Dalston版本的Spring Cloud中,它沒有預設開啟。需要需要在配置檔案中配置開啟它,本專案我們是不需要開啟的

feign:
  hystrix:
    enabled: true
複製程式碼

服務註冊

修改 HomeClient類 ,@FeignClient 註解,加上fallbackFactory指定新建的HystrixClientFallbackFactory 工廠類

在程式的啟動類 RibbonConsumerApplication 通過 @EnableHystrix 開啟 Hystrix

package io.ymq.example.feign.consumer.hystrix;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * 描述: 指定這個介面所要呼叫的 提供者服務名稱 "eureka-provider"
 *
 * @author yanpenglei
 * @create 2017-12-06 15:13
 **/
@FeignClient(value ="eureka-provider",fallbackFactory = HystrixClientFallbackFactory.class)
public interface  HomeClient {

    @GetMapping("/")
    String consumer();
}
複製程式碼

新加的類 HystrixClientFallbackFactory.java

package io.ymq.example.feign.consumer.hystrix;

import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

/**
 * 描述:
 *
 * @author yanpenglei
 * @create 2017-12-07 20:37
 **/
@Component
public class HystrixClientFallbackFactory implements FallbackFactory<HomeClient> {

    @Override
    public HomeClient create(Throwable throwable) {
        return () -> "feign + hystrix ,提供者服務掛了";
    }
}
複製程式碼

測試斷路器

依次啟動專案:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-feign-consumer-hystrix

啟動該工程後,訪問服務註冊中心,檢視服務是否都已註冊成功:http://localhost:8761/

檢視各個服務註冊狀態

在命令視窗curl http://localhost:9000/hello,發現一切正常

或者瀏覽器get 請求http://localhost:9000/hello F5 重新整理

eureka-provider 提供者服務響應

停止 spring-cloud-eureka-provider-1 提供者,埠為:8081服務

再次訪問命令視窗curl http://localhost:9000/hello ,斷路器已經生效,提示:Feign + hystrix ,提供者服務掛了

Feign + hystrix ,提供者服務掛了

Hystrix Dashboard

HD 簡介

Hystrix Dashboard在微服務架構中為例保證程式的可用性,防止程式出錯導致網路阻塞,出現了斷路器模型。斷路器的狀況反應了一個程式的可用性和健壯性,它是一個重要指標。Hystrix Dashboard是作為斷路器狀態的一個元件,提供了資料監控和友好的圖形化介面。

改造專案

複製專案 spring-cloud-ribbon-consumer-hystrix,修改名稱 spring-cloud-ribbon-consumer-hystrix-dashboard 在它的基礎上進行改造。Feign的改造和這一樣。

pom的工程檔案引入相應的依賴:

新增依賴

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
複製程式碼

開啟 HD

修改 RibbonConsumerApplication.java

在程式的入口RibbonConsumerApplication類,加上@EnableHystrix註解開啟斷路器,這個是必須的,並且需要在程式中宣告斷路點@HystrixCommand;加上@EnableHystrixDashboard註解,開啟HystrixDashboard

package io.ymq.example.ribbon.consumer.hystrix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableHystrix
@EnableDiscoveryClient
@EnableHystrixDashboard
@SpringBootApplication
public class RibbonConsumerApplication {

    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

	public static void main(String[] args) {
		SpringApplication.run(RibbonConsumerApplication.class, args);
	}
}

複製程式碼

宣告斷路點

宣告斷路點 @HystrixCommand(fallbackMethod = "defaultStores")

package io.ymq.example.ribbon.consumer.hystrix;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 描述:呼叫提供者的 `home` 方法
 *
 * @author yanpenglei
 * @create 2017-12-05 18:53
 **/
@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "defaultStores")
    @GetMapping(value = "/hello")
    public String hello() {
        return restTemplate.getForEntity("http://eureka-provider/", String.class).getBody();
    }

    public String defaultStores() {
        return "feign + hystrix Dashboard ,提供者服務掛了";
    }

}

複製程式碼

@HystrixCommand 表明該方法為hystrix包裹,可以對依賴服務進行隔離、降級、快速失敗、快速重試等等hystrix相關功能 該註解屬性較多,下面講解其中幾個

  • fallbackMethod 降級方法
  • commandProperties 普通配置屬性,可以配置HystrixCommand對應屬性,例如採用執行緒池還是訊號量隔離、熔斷器熔斷規則等等
  • ignoreExceptions 忽略的異常,預設HystrixBadRequestException不計入失敗
  • groupKey() 組名稱,預設使用類名稱
  • commandKey 命令名稱,預設使用方法名

測試服務

依次啟動專案:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-ribbon-consumer-hystrix-dashboard

啟動該工程後,訪問服務註冊中心,檢視服務是否都已註冊成功:http://localhost:8761/

檢視各個服務註冊狀態

Hystrix Dashboard 監控

可以訪問 http://127.0.0.1:9090/hystrix ,獲取Hystrix Dashboard資訊,預設最大開啟5個終端獲取監控資訊,可以增加delay引數指定獲取監控資料間隔時間

在介面依次輸入:http://127.0.0.1:9000/hystrix.stream2000hello 點確定。可以訪問以下,圖形化監控頁面

Hystrix Dashboard

Hystrix Monitor 圖形化監控頁面

Hystrix  Monitor 圖形化監控頁面

原始碼下載

GitHub:github.com/souyunku/sp…

碼雲:gitee.com/souyunku/sp…

Contact

  • 作者:鵬磊
  • 出處:www.ymq.io
  • Email:admin@souyunku.com
  • 版權歸作者所有,轉載請註明出處
  • Wechat:關注公眾號,搜雲庫,專注於開發技術的研究與知識分享

關注公眾號-搜雲庫
搜雲庫

相關文章