18,深入Hystrix斷路器執行原理

https://www.jianshu.com/p/c2ab1ea4983d

深入Hystrix斷路器執行原理

RequestVolumeThreshold

HystrixCommandProperties.Setter()
     .withCircuitBreakerRequestVolumeThreshold(int)

表示在滑動窗口中,至少有多個請求,才肯那個出發斷路。
Hystrix經過斷路器的流量超過了一定的閥值,纔有可能出發斷路。比如說,要求在10s內經過斷路器的流量必須達到20個,而實際超過斷路器的流量才10個,那麼根本不會去判斷要不要斷路。

ErrorThresholdPercentage

HystrixCommandProperties.Setter()
    .withCircuiBreakerErrorYhresholdPercentage(int)

表示異常比例達到多少,纔會觸發斷路,默認爲50(%).
如果斷路器統計到異常調用的佔比超過了一定的閥值,比如說在10s內,經過斷路器的流量達到了30個,同時其中的異常訪問數量也達到了一定的比例,比如60%的請求都是異常(報錯/超時/reject),就會開啓斷路。

SleepWindowlnMilliseconds

HystrixCommandProperties.Setter()
  .withCircuitBreakerSleepWindowInMilliseconds(int)

斷路開啓,也就是由close轉換到open狀態(close->open).那麼在之後sleepWindowInMilliseconds時間內,所有經過該斷路器的請求全部都會被斷路,不調用後端服務,直接走fallback降級機制。

而在該參數時間以後,斷路器會變爲half-open扳開閉狀態,嘗試讓一條請求經過斷路器,看能不能正常調用。如果調用成功了,那麼就自動恢復,斷路器轉爲close狀態。

Enabled

   HystrixCommandProperties.Setter()
        .wiithCircuitBreakerEnabled(boolean)

控制是否允許斷路器工作,包括跟蹤依賴服務調用的健康狀況,以及對於異常過多時是否允許觸發斷路。默認值爲true.

ForceOpen

HystrixCommandProperties.Setter()
     .withCircuitBreakerEnabled(boolean)

控制是否允許斷路器工作,包括跟蹤依賴服務調用的健康情況,以及對異常情況過多時,是否允許觸發斷路。默認值爲true.

ForceOpen

HystrixCommandProperties.Setter()
    .withCircuitBreakerForceOpen(boolean)

如果設置爲true的話,直接強迫打開斷路器相當於手動斷路了,手動降級,默認值爲false。

ForceClosed

HystrixCommandProperties.Setter()
    .withCircuitBreakerForceClosed(boolean)

如果設置爲true,直接強迫關閉斷路器,相當於手動停止斷路了,手動升級,默認值爲false.
實例Demo

HystrixCommand配置參數

在GetProductInfoCommand中配置Setter斷路器相關參數。
1,滑動窗口中,最少20個請求,才肯那個觸發斷路
2,異常比例達到40%時,才觸發斷路
3,短路後3000ms內,所有請求都被reject,直接走fallback降級,不會調用run()方法。3000ms過後,變爲half-open狀態。

run()方法中,我們判斷下productld是否爲-1,是的話,直接跑出異常。這麼寫,我們之後測試的時候就可以傳入productld=-1模擬服務執行異常了。

在降級邏輯中,我們直接給他返回降級商品就好了。

 public class GetProductInfoCommand extends HystrixCommand<ProductInfo>{
private Long productId;
private static final HystrixCommandKey KEY=HystrixCommandKey.Factory.asKey("GetProductInfoCommand");


public GetProductInfoCommand(Long productId){
  super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ProductInfoService"))
 .andCommandKey(KEY)
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
   //是否允許斷路器工作
.withCircuiBreakerEndabled(true)
//滑動窗口中,最少有多少個請求,纔可能觸發斷路
.withCircuitBreakerRequestVolumeThreshold(20)
//異常比例達到多少,才觸發斷路,默認爲50%
.withCircuitBreakerErrorThresholdPercentage(40)
//斷路器後多少時間內直接reject請求,之後進入half-open狀態,默認爲5000ms
.withCircuitBreakerSleepWindowInMilliseconds(3000)));
this.productId =productId;

}
protected ProductInfo run() throws Exception{

 System.out.println("調用接口查詢商品數據,productId="+productId);
if(productId ==-1L){
   throw new Exception();
}

       String url = "http://localhost:8081/getProductInfo?productId=" + productId;
       String response = HttpClientUtils.sendGetRequest(url);
       return JSONObject.parseObject(response, ProductInfo.class);

}
protected productInfo getFallback(){
   ProductInfo productInfo =new ProductInfo();
productInfo.setName("降級商品");
   return productInfo;
}
}

斷路測試類

我們在測試類中,前30次請求,傳入productId =1,然後休眠3s,之後70次請求,傳入producytId=1;

@SpringBootTest
@RunWith(SpringRunner.class)
public class CircuitBreakerTest{
@Test
public void testCircuitBreaker(){
    String baseURL = "http://localhost:8080/getProductInfo?productId=";
for(int i =0; i<30; ++i){
    //傳入-1,會拋出異常,然後走降級邏輯
HttpClientUtils.sendGetRequest(baseURL+"-1);
}  
        TimeUtils.sleep(3);
System.out.println("After sleeping.... ");
  for(int i=31;i<100;i++){
   //傳入1,走服務正常調用
HttpClientUtils.sendGetRequest(baseURL+"1");
}


}


}


測試結果

測試結果,我們可以明顯看出系統斷路與恢復的整個過程

調用接口查詢商品數據,productId=-1
ProductInfo(id=null, name=降級商品, price=null, pictureList=null, specification=null, service=null, color=null, size=null, shopId=null, modifiedTime=null, cityId=null, cityName=null, brandId=null, brandName=null)
// ...
// 這裏重複打印了 20 次上面的結果


ProductInfo(id=null, name=降級商品, price=null, pictureList=null, specification=null, service=null, color=null, size=null, shopId=null, modifiedTime=null, cityId=null, cityName=null, brandId=null, brandName=null)
// ...
// 這裏重複打印了 8 次上面的結果


// 休眠 3s 後
調用接口查詢商品數據,productId=1
ProductInfo(id=1, name=iphone7手機, price=5599.0, pictureList=a.jpg,b.jpg, specification=iphone7的規格, service=iphone7的售後服務, color=紅色,白色,黑色, size=5.5, shopId=1, modifiedTime=2017-01-01 12:00:00, cityId=1, cityName=null, brandId=1, brandName=null)
// ...
// 這裏重複打印了 69 次上面的結果

前 30 次請求,我們傳入的 productId 爲 -1,所以服務執行過程中會拋出異常。我們設置了最少 20 次請求通過斷路器並且異常比例超出 40% 就觸發斷路。因此執行了 21 次接口調用,每次都拋異常並且走降級,21 次過後,斷路器就被打開了。
之後的 9 次請求,都不會執行 run() 方法,也就不會打印以下信息。
調用接口查詢商品數據,productId=-1

而是直接走降級邏輯,調用 getFallback() 執行。
休眠了 3s 後,我們在之後的 70 次請求中,都傳入 productId 爲 1。由於我們前面設置了 3000ms 過後斷路器變爲 half-open 狀態。因此 Hystrix 會嘗試執行請求,發現成功了,那麼斷路器關閉,之後的所有請求也都能正常調用了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章