天天看點

【Spring Cloud】-Hystrix斷路器

前言

高可用相關的技術以及架構,對于大型複雜的分布式系統,是非常重要的。而高可用架構中,非常重要的一個環節,就是如何将分布式系統中的各個服務打造成高可用的服務,進而足以應對分布式系統環境中的各種各樣的問題,比如服務間的調用逾時,或者服務間的調用失敗,避免整個分布式系統被某個服務的故障給拖垮。而要解決這些棘手的分布式系統可用性問題,就涉及到了高可用分布式系統中的很多重要的技術,包括資源隔離,限流與過載保護,熔斷,優雅降級,容錯,逾時控制,監控運維,等等。

什麼是斷路器

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

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

在Spring Cloud中使用了Hystrix 來實作斷路器的功能,Hystrix能夠完美的解決分布式系統架構中,打造高可用服務面臨的一系列技術難題,包括資源隔離,限流與過載保護,熔斷,優雅降級,容錯,逾時控制,監控運維等等。

雪崩效應

如果單個服務C出現問題,服務B調用服務C就會出現線程阻塞,此時若有大量的請求湧入,Servlet容器的線程資源會被消耗完畢,導緻服務B癱瘓。服務與服務之間的依賴性,故障會傳播,那麼服務A調用服務B也會癱瘓,這樣會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的“雪崩”效應。

如何防止血崩效應的發生

spring cloud Hystrix是防雪崩利器,主要解決方案包括服務降級、依賴隔離、服務熔斷、服務監控等功能

服務降級

概念

當伺服器壓力劇增的時候,根據目前業務情況以及流量,對一些服務和頁面有政策的降級,以此緩解伺服器資源的壓力以保障核心任務的正常運作,同時也保證了大部分客戶能得到正常的響應。

核心

優先核心服務,給核心服務不可用或若可用

自動降級使用場景

(1)、逾時降級:主要配置好逾時時間和逾時重試次數和機制,并使用異步機制探測回複情況

(2)、失敗次數降級:主要是一些不穩定的api,當失敗調用次數達到一定閥值自動降級,同樣要使用異步機制探測回複情況

(3)、故障降級:比如要調用的遠端服務挂掉了(網絡故障、DNS故障、http服務傳回錯誤的狀态碼、rpc服務抛出異常),則可以直接降級。降級後的處理方案有:預設值(比如庫存服務挂了,傳回預設現貨)、兜底資料(比如廣告挂了,傳回提前準備好的一些靜态頁面)、緩存(之前暫存的一些緩存資料)

(4)、限流降級:當我們去秒殺或者搶購一些限購商品時,此時可能會因為通路量太大而導緻系統崩潰,此時開發者會使用限流來進行限制通路量,當達到限流閥值,後續請求會被降級;降級後的處理方案可以是:排隊頁面(将使用者導流到排隊頁面等一會重試)、無貨(直接告知使用者沒貨了)、錯誤頁(如活動太火爆了,稍後重試)。

實作

1、添加依賴

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

2、啟動類添加注解@EnableCircuitBreaker

3、使用@HystrixCommand注解指定回調方法,即降級方法。

@RestController
public class HystrixController {

    @GetMapping("/getProductInfoList")
    //使用hystrix 實作容錯機制,請求失敗後執行Back,稱之為“服務降級”
    @HystrixCommand(fallbackMethod = "fallback")
    public String getProductInfoList(){
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject   ("http://127.0.0.1:8005/product/list",Arrays.asList("12222222222000"),String.class);
    }

	//回退方法
    private String fallback(){
        return "太擁擠了,請稍後再試~~";
    }
}
           

4、當目标服務出錯時,會觸發降級調用fallback。降級不一定就是發生在目标服務不能提供正常服務了,觸發降級;也可以用到自己服務内部的降級,比如抛出一個異常,觸發降級,這樣的話如果并發數太高,資料庫連接配接數太多了,就可以抛一個異常,這樣來觸發降級。

5、fallback也可以調用在類上,使用@DefaultProderties注解,如果在每個方法上都調用一次,會需要寫多次

@RestController
@DefaultProderties(defaultFallback = "defaultFallback")
public class HystrixController {
    @GetMapping("/getProductInfoList")
    public String getProductInfoList(){
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8005/product/list",Arrays.asList("12222222222000"),String.class);

    }

    private String defaultfallback(){
        return "太擁擠了,請稍後再試~~";
    }
}
           

依賴隔離

類似于docker的艙壁模式,實作程序隔離,保證容器之間互不影響。Hystrix自動實作依賴隔離,是線程池隔離。

線程池隔離:使用一個線程池來存儲目前的請求,也就是說發起請求是通過Hystrix的線程池來走的,不同的服務走不同的線程池,線程池對請求作處理,設定任務傳回處理逾時時間,堆積的請求堆積入線程池隊列。這種方式需要為每個依賴的服務申請線程池,實作了不同服務調用的隔離,避免了服務雪崩的問題。但是有一定的資源消耗,好處是可以應對突發流量(流量洪峰來臨時,處理不完可将資料存儲到線程池隊裡慢慢處理,最主要的是Hystrix自動實作了依賴隔離。

服務熔斷

概念

服務熔斷和保險絲的使用原理很像,保險系在電壓達到一定值後,會出現保險絲為控制風險,保護電器而自動燒掉,切斷電源。相應的,服務熔斷一般是指軟體系統中,由于某些原因使得服務出現了過載現象,為防止造成整個系統故障,進而采用的一種保護措施,是以很多地方把熔斷亦稱為過載保護。

熔斷機制

【Spring Cloud】-Hystrix斷路器

可以看到服務熔斷機制有三個狀态:熔斷關閉,熔斷打開,熔斷半開。

  1. 但請求成功或者失敗次數低于開關門檻值時,熔斷處于關閉狀态;
  2. 當請求失敗次數達到開關門檻值,熔斷器會變成變成打開狀态,打開狀态會設定一定時間的休眠窗,比如10秒,10秒内服務降級邏輯會成為主邏輯,10秒後,熔斷器會處于半開狀态;
  3. 半開狀态會釋放一部分請求,如果釋放的請求成功,熔斷器關閉,服務恢主邏輯複,如果釋放的請求依然失敗,熔斷器繼續進入打開狀态,休眠期計時。

實作

@RestController
@DefaultProderties(defaultFallback = "defaultFallback")
public class HystrixController {
    //熔斷設定
    @HystrixCommand(commandProperties = {
            @HystrixProerty(name="circuitbreaker.enable",value="true"),  //設定熔斷
            @HystrixProerty(name="circuitbreaker.requestVolumethreshold",value="10"), //滾動視窗,熔斷器最小請求次數
            @HystrixProerty(name="circuitbreaker.sleepWindowInMilliseconds",value="10000"), //休眠窗,設定10秒,休眠窗内降級邏輯執行
            @HystrixProerty(name="circuitbreaker.errorThreshouldPercentage",value="60") //熔斷器開關門檻值,在滾動視窗内如果失敗次數高于60%,熔斷器打開
    })
    @GetMapping("/getProductInfoList")
    public String getProductInfoList(@RequestParam("number") Integer number){
        if(number % 2== 0){
            return "success";
        }

        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8005/product/list",Arrays.asList("12222222222000"),String.class);
    }

    private String fallback(){
        return "太擁擠了,請稍後再試~~";
    }
}
           

熔斷參數

  1. Circuit Breaker:斷路器
  2. sleepWindowInMilliseconds:10s;表示10s秒的休眠時間窗,10s後休眠時間窗到期,熔斷器設定為半打開狀态,如果請求恢複,設定為關閉狀态,如果請求沒有恢複,則設定為打開狀态
  3. **requestVolumethreshold:**斷路器的最小請求數
  4. **errorThreshouldPercentage:**斷路器打開的錯誤百分比條件,在時間滾動視窗中如果發生了10次調用,如果有7次是錯誤的,超過了60%,這個時候斷路器就會設定為打開狀态

demo說明

【Spring Cloud】-Hystrix斷路器

熔斷器工作流程圖

【Spring Cloud】-Hystrix斷路器

降級與熔斷對比

共性

目的: 目的一緻,都是從系統的可用性、可靠性着想。放了防止系統的整體緩慢甚至奔潰而采用的技術手段。

最終表現: 表現類似,最終都是給使用者一種目前服務不可用或者不可達的感覺

粒度: 大多都是在服務級别,當然也有一些在持久層層面的應用

自治: 基本都是靠系統達到某一臨界條件時,實作自動的降級與熔斷,人工降級并不是那麼穩妥。

差別

觸發原因: 服務熔斷一般指某個服務的下遊服務出現問題時采用的手段,而服務降級一般是從整體層面考慮的。

管理目标層次: 熔斷是一種架構級的處理,每一個微服務都需要。而降級一般需要對業務有層級之分,降級一般都是從外圍服務開始的。

實作方式: 代碼級别實作有差異

服務監控

Hystrix還提供給我們一個監控功能Hystrix-dashboard,借助hystrix-dashboard可對監控進行圖形化展示,就能實時的觀察我們的服務調用情況。

1、引入hystrix-dashboard依賴

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

2、啟動類配置@EnableHystrixDashboard注解(同時配置@EnableDiscoveryClient向注冊中心注冊,友善管理)

3、配置檔案設定端口

server:
  port: 8087

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${server.port}
spring:
  application:
    name: hystrix-dashboard
           

4、監控界面如下

【Spring Cloud】-Hystrix斷路器

繼續閱讀