1. 程式人生 > >Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(二十):服務熔斷(Hystrix、Turbine)

Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(二十):服務熔斷(Hystrix、Turbine)

線上演示

演示地址:http://139.196.87.48:9002/kitty

使用者名稱:admin 密碼:admin

雪崩效應

在微服務架構中,由於服務眾多,通常會涉及多個服務層級的呼叫,而一旦基礎服務發生故障,很可能會導致級聯故障,進而造成整個系統不可用,這種現象被稱為服務雪崩效應。服務雪崩效應是一種因“服務提供者”的不可用導致“服務消費者”的不可用,並將這種不可用逐漸放大的過程。

比如在一個系統中, A作為服務提供者,B是A的服務消費者,C和D又是B的服務消費者。如果此時A發生故障,則會引起B的不可用,而B的不可用又將導致C和D的不可用,當這種不可用像滾雪球一樣逐漸放大的時候,雪崩效應就形成了。

熔斷器(CircuitBreaker)

熔斷器的原理很簡單,如同電力過載保護器。它可以實現快速失敗,如果它在一段時間內偵測到許多類似的錯誤,就會強迫其以後的多個呼叫快速失敗,不再訪問遠端伺服器,從而防止應用程式不斷地嘗試執行可能會失敗的操作,使得應用程式繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產生。熔斷器也可以使應用程式能夠診斷錯誤是否已經修正,如果已經修正,應用程式會再次嘗試呼叫操作。熔斷器模式就像是那些容易導致錯誤的操作的一種代理。這種代理能夠記錄最近呼叫發生錯誤的次數,然後決定使用允許操作繼續,或者立即返回錯誤。熔斷器是保護服務高可用的最後一道防線。

Hystrix特性

1.斷路器機制

斷路器很好理解, 當Hystrix Command請求後端服務失敗數量超過一定比例(預設50%), 斷路器會切換到開路狀態(Open). 這時所有請求會直接失敗而不會發送到後端服務. 斷路器保持在開路狀態一段時間後(預設5秒), 自動切換到半開路狀態(HALF-OPEN). 這時會判斷下一次請求的返回情況, 如果請求成功, 斷路器切回閉路狀態(CLOSED), 否則重新切換到開路狀態(OPEN). Hystrix的斷路器就像我們家庭電路中的保險絲, 一旦後端服務不可用, 斷路器會直接切斷請求鏈, 避免傳送大量無效請求影響系統吞吐量, 並且斷路器有自我檢測並恢復的能力。

2.Fallback

Fallback相當於是降級操作. 對於查詢操作, 我們可以實現一個fallback方法, 當請求後端服務出現異常的時候, 可以使用fallback方法返回的值. fallback方法的返回值一般是設定的預設值或者來自快取。

3.資源隔離

在Hystrix中, 主要通過執行緒池來實現資源隔離. 通常在使用的時候我們會根據呼叫的遠端服務劃分出多個執行緒池. 例如呼叫產品服務的Command放入A執行緒池, 呼叫賬戶服務的Command放入B執行緒池. 這樣做的主要優點是執行環境被隔離開了. 這樣就算呼叫服務的程式碼存在bug或者由於其他原因導致自己所線上程池被耗盡時, 不會對系統的其他服務造成影響. 但是帶來的代價就是維護多個執行緒池會對系統帶來額外的效能開銷. 如果是對效能有嚴格要求而且確信自己呼叫服務的客戶端程式碼不會出問題的話, 可以使用Hystrix的訊號模式(Semaphores)來隔離資源。

Feign Hystrix

因為 Feign 中已經依賴了 Hystrix, 所以在 maven 配置上不用做任何改動就可以使用了,我們在 kitty-consumer 專案中直接改造。

修改配置

在配置檔案中新增配置,開啟 Hystrix 熔斷器。

application.yml

#開啟熔斷器
feign:
  hystrix:
    enabled: true

建立回撥類

建立一個回撥類 KittyProducerHystrix,實現 KittyProducerService介面,並實現對應的方法,返回呼叫失敗後的資訊。

KittyProducerHystrix.java

package com.louis.kitty.consumer.feign;

import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

@Component
public class KittyProducerHystrix implements KittyProducerService {

    @RequestMapping("/hello")
    public String hello() {
        return "sorry, hello service call failed.";
    }
}

新增fallback屬性

修改 KittyProducerService,在 @FeignClient 註解中加入 fallback 屬性,繫結我們建立的失敗回撥處理類。

package com.louis.kitty.consumer.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient(name = "kitty-producer", fallback = KittyProducerHystrix.class)
public interface KittyProducerService {

    @RequestMapping("/hello")
    public String hello();
}

到此,所有改動程式碼就完成了。

測試效果

啟動成功之後,多次訪問 http://localhost:8005/feign/call,結果如同之前一樣交替返回 hello kitty 和 hello kitty 2。

說明熔斷器的啟動,不會影響正常服務的訪問。

 

把 kitty-producer 服務停掉,再次訪問,返回我們提供的熔斷回撥資訊,熔斷成功,kitty-producer2服務正常。

 

重啟 kitty-producer 服務,再次訪問,發現服務又可以訪問了,說明熔斷器具有自我診斷修復的功能。

注意:在重啟成功之後,可能需要一些時間,等待熔斷器進行自我診斷和修復完成之後,方可正常提供服務。

  

Hystrix Dashboard

Hystrix-dashboard是一款針對Hystrix進行實時監控的工具,通過Hystrix Dashboard我們可以在直觀地看到各Hystrix Command的請求響應時間, 請求成功率等資料。

新增依賴

新建一個 kitty-hystrix 工程,修改 pom 檔案,新增相關依賴。

pom.xml

<!-- spring boot -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<!--consul-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--actuator-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--spring-boot-admin-->
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>${spring.boot.admin.version}</version>
</dependency>
<!--hystrix-dashboard-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

Spring Cloud Pom依賴。

<!--srping cloud-->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

啟動類

在啟動類中添加註解 @EnableHystrixDashboard 開啟熔斷監控支援。

KittyHystrixApplication.java

package com.louis.kitty.hystrix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;

/**
 * 啟動器
 * @author Louis
 * @date Oct 29, 2018
 */
@EnableHystrixDashboard
@EnableDiscoveryClient
@SpringBootApplication
public class KittyHystrixApplication {

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

配置檔案

修改配置檔案,把服務註冊到註冊中心。

server:
  port: 8501
spring:
  application:
    name: kitty-hystrix
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        serviceName: ${spring.application.name}    # 註冊到consul的服務名稱

配置監控路徑

注意,如果你使用的是2.x等比較新的版本,需要在 Hystrix 的消費端配置監控路徑。

開啟消費端 kitty-consumer 工程, 新增依賴。

<!--actuator-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--hystrix-dashboard-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

修改啟動類,新增服務監控路徑配置。

ConsuleConsumerApplication.java

// 此配置是為了服務監控而配置,與服務容錯本身無關,
// ServletRegistrationBean因為springboot的預設路徑不是"/hystrix.stream",
// 只要在自己的專案裡配置上下面的servlet就可以了
@Bean
public ServletRegistrationBean getServlet() {
    HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
    registrationBean.setLoadOnStartup(1);
    registrationBean.addUrlMappings("/hystrix.stream");
    registrationBean.setName("HystrixMetricsStreamServlet");
    return registrationBean;
}

測試效果

先後啟動 monitor、producer、consumer、hystrix 服務。

訪問 http://localhost:8501/hystrix,會看到如下圖所示介面。

此時沒有任何具體的監控資訊,需要輸入要監控的消費者地址及監控資訊的輪詢時間和標題。

Hystrix Dashboard 共支援三種不同的監控方式:

單體Hystrix 消費者:通過URL http://hystrix-app:port/hystrix.stream 開啟,實現對具體某個服務例項的監控。

預設叢集監控:通過URL http://turbine-hostname:port/turbine.stream 開啟,實現對預設叢集的監控。

自定叢集監控:通過URL http://turbine-hostname:port/turbine.stream?cluster=[clusterName] 開啟,實現對clusterName叢集的監控。

我們這裡現在是對單體 Hystrix 消費者的監控,後面整合 Turbine 叢集的時候再說明後兩種的監控方式。

我們先訪問 http://localhost:8005/feign/call, 檢視要監控的服務是否可以正常訪問。

確認服務可以正常訪問之後,在監控地址內輸入 http://localhost:8005/hystrix.stream,然後點選 Monitor Stream 開始監控。


剛進去,頁面先顯示 loading... 資訊, 多次訪問 http://localhost:8005/feign/call 之後,統計圖表資訊如下圖所示。

各個指標的含義參見下圖。

Spring Cloud Turbine

上面我們集成了Hystrix Dashboard使用Hystrix Dashboard可以看到單個應用內的服務資訊,顯然這是不夠的,我們還需要一個工具能讓我們彙總系統內多個服務的資料並顯示到Hystrix Dashboard上,這個工具就是Turbine。

新增依賴

修改 kitty-hystrix 的pom檔案,新增 turbine 依賴包。

注意:因為我們使用的註冊中心是Consul,所以需要排除預設的euraka包,不然會有衝突啟動出錯。

pom.xml

<!--turbine-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
    <exclusions>  
         <exclusion>     
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
         </exclusion>  
    </exclusions> 
</dependency>

啟動類

啟動類新增 @EnableTurbine 註解,開啟 turbine 支援。

KittyHystrixApplication.java

package com.louis.kitty.hystrix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;

/**
 * 啟動器
 * @author Louis
 * @date Oct 29, 2018
 */
@EnableTurbine
@EnableHystrixDashboard
@EnableDiscoveryClient
@SpringBootApplication
public class KittyHystrixApplication {

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

配置檔案

修改配置,配置註冊服務資訊,新增turbine配置。

application.yml

turbine:
  instanceUrlSuffix: hystrix.stream    # 指定收集路徑
  appConfig: kitty-consumer    # 指定了需要收集監控資訊的服務名,多個以“,”進行區分
  clusterNameExpression: "'default'"    # 指定叢集名稱,若為default則為預設叢集,多個叢集則通過此配置區分
  combine-host-port: true    # 此配置預設為false,則服務是以host進行區分,若設定為true則以host+port進行區分

測試效果

依次啟動 monitor、producer、consumer,hystrix 服務,訪問 http://localhost:8500  檢視註冊中心管理介面。

 

 

確認服務無誤之後, 訪問 http://localhost:8501/hystrix,輸入 http://localhost:8501/turbine.stream,檢視監控圖表。

 

 

如下圖所示,就是利用 Turbine 聚合多個 Hytrix 消費者的熔斷監控資訊結果,記憶體允許可以多啟動幾個消費者檢視

 

 

原始碼下載

後端:https://gitee.com/liuge1988/kitty

前端:https://gitee.com/liuge1988/kitty-ui.git


作者:朝雨憶輕塵
出處:https://www.cnblogs.com/xifengxiaoma/ 
版權所有,歡迎轉載,轉載請註明原文作者及出處。