1. 程式人生 > >Hystrix-短路器原理及實戰

Hystrix-短路器原理及實戰

短路器是什麼?顧名思義,短路器的作用是用來阻斷的。即當開啟短路器時,後續對command的執行會直接執行fallback降級。那麼什麼情況下短路器會被開啟呢?下面我們一起了解下這其中的原理。

一、短路器的工作原理

1、短路器開啟的前提是經過短路器的流量超過了一定的閾值。比如說在10s內,經過短路器的流量必須達到20個才會判斷要不要短路。

2、到達短路器的流量異常佔比必須超過一定的閾值。比如我們說在10s,經過短路器的流量達到了30個,同事其中異常的訪問數量,佔到了一定的比例,比如說50%的請求都是異常的,那就開啟短路。

3、短路器達到了一定的閾值,且異常佔比也達到了閾值,那麼此時短路器就會從close狀態轉換到open狀態。

4、短路器開啟的時候,所有經過該短路器的請求全部被短路,不呼叫後端服務,直接fallback降級。

5、經過一段時間之後,短路器會處於半開狀態,讓一條請求經過短路器,看能否正常呼叫,如果呼叫成功,那麼短路器就會自動關閉。

二、短路器相關配置

1、circuitBreaker.enabled:控制短路器是否允許工作,包括跟蹤依賴服務呼叫的健康狀況,以及對異常情況過多時是否允許觸發短路,預設是true。HystrixCommandProperties.Setter().withCircuitBreakerEnabled(boolean value)

2、circuitBreaker.requestVolumeThreshold

:設定一個rolling window,滑動視窗中,最少要有多少個請求時才觸發開啟短路。(如果設定為20(預設值),那麼在一個10秒的滑動視窗內,如果只有19個請求,即使這19個請求都是異常的,也是不會觸發開啟短路器的。)HystrixCommandProperties.Setter().withCircuitBreakerRequestVolumeThreshold(int value)

3、circuitBreaker.sleepWindowInMilliseconds:設定在短路之後,需要在多長時間內直接reject請求,然後在這段時間之後,再重新到holf-open狀態,嘗試允許請求通過以及自動恢復,預設值是5000毫秒。HystrixCommandProperties.Setter().withCircuitBreakerSleepWindowInMilliseconds(int value)

4、circuitBreaker.errorThresholdPercentage:設定異常請求量的百分比,當異常請求達到這個百分比時,就觸發開啟短路器,預設是50,也就是50%。HystrixCommandProperties.Setter().withCircuitBreakerErrorThresholdPercentage(int value)

5、circuitBreaker.forceOpen:如果設定為true的話,直接強迫開啟短路器,相當於是手動短路了,手動降級,預設false。HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(boolean value)

6、circuitBreaker.forceClosed:如果設定為ture的話,直接強迫關閉短路器,相當於是手動停止短路了,手動升級,預設false。HystrixCommandProperties.Setter().withCircuitBreakerForceClosed(boolean value)

三、實戰

3.1、建立command

public class CommandCircuitBreaker extends HystrixCommand<String> {
  private String tag;

  public CommandCircuitBreaker(String tag) {
    super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CommandCircuitBreakerGroupKey"))
        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()//
            .withCircuitBreakerRequestVolumeThreshold(30)// 設定短路器的流量必須到達30
            .withCircuitBreakerErrorThresholdPercentage(40)// 異常佔比達到40%
            .withCircuitBreakerSleepWindowInMilliseconds(3000)));// 滑動視窗3s,3s後處於半開狀態
    this.tag = tag;
  }

  @Override
  protected String run() throws Exception {
    if ("error".equals(tag)) {
      throw new Exception("丟擲異常");
    }
    return "-----------------成功-----------------";
  }

  @Override
  protected String getFallback() {
    return "-----------------降級處理-----------------";
  }

}

3.2、執行command

public class CommandCircuitBreakerTest {

  public static void main(String[] args) throws Exception {

    for (int i = 0; i < 15; i++) {
      CommandCircuitBreaker breaker = new CommandCircuitBreaker("success");
      System.out.println("第" + (i + 1) + "次請求,結果為:" + breaker.execute());
    }
    for (int i = 0; i < 25; i++) {
      CommandCircuitBreaker breaker = new CommandCircuitBreaker("error");
      System.out.println("第" + (i + 1) + "次請求,結果為:" + breaker.execute());
    }
    // 因為時間視窗統計異常佔比需要時間,所以這裡等待了2s後
    Thread.sleep(2000);

    for (int i = 0; i < 10; i++) {
      CommandCircuitBreaker breaker = new CommandCircuitBreaker("success");
      System.out.println("第" + (i + 1) + "次請求,結果為:" + breaker.execute());
    }
    // 統計單位,有一個時間視窗的,我們必須要等到那個時間視窗過了以後,才會說,hystrix看一下最近的這個時間視窗
    // 比如說,最近的10秒內,有多少條資料,其中異常的資料有沒有到一定的比例
    // 如果到了一定的比例,那麼才會去短路
    System.out.println("嘗試等待3秒鐘。。。。。。");
    Thread.sleep(3000);
    for (int i = 0; i < 10; i++) {
      CommandCircuitBreaker breaker = new CommandCircuitBreaker("success");
      System.out.println("第" + (i + 1) + "次請求,結果為:" + breaker.execute());
    }
  }
}

3.3、執行結果

(1)成功執行15次之後,開始丟擲異常

(2)後面25次都是異常請求,然後等待2s,讓短路器進行異常佔比統計。再發起正常的請求,此時直接走了fallback降級處理,我們再等待3s,讓短路器處於半開狀態,發起正常請求,此時執行成功。