SpringCloud之Hystrix斷路器(熔斷、限流、降級、超時監控)


hystrix是什么?

Hystrix是一個用於處理分布式系統的延遲和容錯的開源庫,在分布式系統里,許多依賴不可避免的會調用失敗,比如超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分布式系統的彈性。

“斷路器”本身是一種開關裝置,當某個服務單元發生故障之后,通過斷路器的故障監控(類似熔斷保險絲),向調用方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者拋出調用方無法處理的異常,這樣就保證了服務調用方的線程不會被長時間、不必要地占用,從而避免了故障在分布式系統中的蔓延,乃至雪崩。

服務雪崩效應

聯想一下上圖, 如果發生這種情況, 也就是說所有發給微服務D的請求 都會被卡在微服務H那, 就會導致線程一直累計在這里, 那么其他的微服務(比如A,B,C...) 就沒有可用線程了, 導致整個服務器
崩潰,這就是服務血崩。

導致服務雪崩的情況我們來總結一下,再看看怎么解決:

程序BUG,數據不匹配,響應時間過長,服務不可用等等.....

針對上面的問題,我們來看看有哪些解決方案 :

服務限流

超時監控

服務熔斷

服務降級

降級,超時 :

降級是當我們的某個微服務響應時間過長,或者不可用了,講白了也就是那個微服務調用不了了,我們不能吧錯誤信息返回出來,或者讓他一直卡在那里,所以要在准備一個對應的策略(一個方法)當發生
這種問題的時候我們直接調用這個方法來快速返回這個請求,不讓他一直卡在那 。

來看看具體怎么操作:

某個微服務調用不了了要做降級,也就是說,要在調用方做降級(不然那個微服務都down掉了再做降級也沒什么意義了) 比如說我們 user 調用power 那么就在user(即客戶端) 做降級。

添加Hystrix依賴

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

啟動類加入注解@EnableHystrix 或者@EnableCircuitBreaker

然后在我們的controller上面加入注解@HystrixCommand(fallbackMethod就是我們剛剛說的方法的名字)

@RequestMapping("/feignPower.do")
@HystrixCommand(fallbackMethod = "fallbackMethod")
public Object feignPower(String name){
  return powerServiceClient.power();
}

fallbackMethod:

public Object fallbackMethod(String name){
  System.out.println(name);
  return R.error("降級信息");
 }

這里的這個降級信息具體內容得根據業務需求來, 比如說返回一個默認的查詢信息,亦或是系統維護(因為有可能要暫時關閉某個微服務而吧資源讓給其他服務)等等...

這時我們可以在power服務的power方法中制作一個異常即可自動調用fallbackMethod方法完成降級。

超時的情況也是如此,只需將在power方法中睡眠個幾秒鍾即可完成超時。

因為hystrix他有默認的超時監聽,當你這個請求默認超過了1秒鍾就會超時 當然,這個可以配置的。

降級到底有什么實際作用?

  1. 他可以監聽你的請求有沒有超時
  2. 報錯了他這里直接截斷了沒有讓請求一直卡在這里
  3. 整體資源快不夠了,忍痛將某些服務先關掉,把資源讓給主服務。就是當你的系統馬上迎來大量的並發(雙十一秒殺這種 或者促銷活動) 這時候如果發現系統馬上承載不了這么大的並發時, 可以考慮先關閉一些不重要的微服務(在降級方法里面返回一個比較友好的信息)

熔斷,限流:

其實熔斷,就好像我們生活中的跳閘一樣, 比如說你的電路出故障了,為了防止出現大型事故 這里直接切斷了你的電源以免意外繼續發生, 把這個概念放在我們程序上也是如此, 當一個微服務調用多
次出現問題時(默認是10秒內20次當然 這個也能配置),hystrix就會采取熔斷機制,不再繼續調用你的方法(會在默認5秒鍾內和電器短路一樣,5秒鍾后會試探性的先關閉熔斷機制,但是如果這時候再失敗一次{之前是20次}那么又會重新進行熔斷) 而是直接調用降級方法,這樣就一定程度上避免了服務雪崩的問題。

限流

限流, 顧名思義, 就是限制你某個微服務的使用量(可用線程)

hystrix通過線程池的方式來管理你的微服務調用,他默認是一個線程池(10大小) 管理你的所有微服務,你可以給某個微服務開辟新的線程池:

@RequestMapping("/feignOrder.do")
@HystrixCommand(fallbackMethod = "fallbackOrderMethod" ,
    threadPoolKey = "order",
    threadPoolProperties ={@HystrixProperty(name = "coreSize",value = "2")
              ,@HystrixProperty(name = "maxQueueSize",value = "1"})
public Object feignOrder(String name){
  System.out.println(1);
  return restTemplate.getForObject(ORDERURL+"/order.do",Object.class);
}

threadPoolKey 就是在線程池唯一標識, hystrix 會拿你這個標識去計數,看線程占用是否超過了, 超過了就會直接降級該次調用

比如, 這里coreSize給他值為2 那么假設你這個方法調用時間是3s執行完, 那么在3s內如果有超過2個請求進來的話, 剩下的請求則全部降級

feign整合hystrix:

feign 默認是支持hystrix的, 但是在Spring - cloud Dalston 版本之后就默認關閉了, 因為不一定業務需求要用的到

所以現在要使用首先得打開他,在yml文件加上如下配置:

feign:
hystrix:
 enabled: true

加上配置之后降級方法怎么寫呢?

@FeignClient(value = "SERVER-POWER",fallback = PowerServiceFallBack.class)
public interface PowerServiceClient {
  @RequestMapping("/power.do")
  public Object power(@RequestParam("name") String name);
}

在feign客戶端的注解上 有個屬性叫fallback 然后指向一個類

PowerServiceFallBack 類:

@Component
public class PowerServiceFallBack implements PowerServiceClient {
  @Override
  public Object power(String name) {
    return R.error("測試降級");
 }
}

這樣子,方法降級就寫好了

當然 可能你有這種需求, 需要拿到具體的錯誤信息, 那么可以這樣寫:

@Component
public class PowerServiceClientFallBackFactory implements
FallbackFactory<PowerServiceClient> {
  @Override
  public PowerServiceClient create(Throwable throwable) {
    return new PowerServiceClient() {
      @Override
      public Object power(String name) {
        String message = throwable.getMessage();
        return R.error("feign降級");
     }
   };
 }
}

客戶端指定一個fallbackFactory就好了

@FeignClient(value = "SERVER-POWER",fallbackFactory =
PowerServiceClientFallBackFactory.class)
public interface PowerServiceClient {
  @RequestMapping("/power.do")
  public Object power(@RequestParam("name") String name);
}

這個message 就是拿到的錯誤信息

至此, 就完成了feign與hystrix的整合

hystrix相關配置:

Execution相關的屬性的配置
hystrix.command.default.execution.isolation.strategy 隔離策略,默認是Thread, 可選Thread|Semaphor
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令執行超時時間,默認1000ms
hystrix.command.default.execution.timeout.enabled 執行是否啟用超時,默認啟用true
hystrix.command.default.execution.isolation.thread.interruptOnTimeout 發生超時是是否中斷,默認true
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大並發請求數,默認10,該參數當使用ExecutionIsolationStrategy.SEMAPHORE策略時才有效。如果達到最大並發請求
數,請求會被拒絕。理論上選擇semaphore size的原則和選擇thread size一致,但選用semaphore時每次執行的單元要比較小且執行速度快(ms級別),否則的話應該用thread。 semaphore應該占整個容器(tomcat)的線程
池的一小部分。 Fallback相關的屬性 這些參數可以應用於Hystrix的THREAD和SEMAPHORE策略
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 如果並發數達到該設置值,請求會被拒絕和拋出異常並且fallback不會被調用。默認10
hystrix.command.default.fallback.enabled 當執行失敗或者請求被拒絕,是否會嘗試調用
hystrixCommand.getFallback() 。默認true
Circuit Breaker相關的屬性
hystrix.command.default.circuitBreaker.enabled 用來跟蹤circuit的健康性,如果未達標則讓request短路。默認true
hystrix.command.default.circuitBreaker.requestVolumeThreshold 一個rolling window內最小的請 求數。如果設為20,那么當一個rolling window的時間內(比如說1個rolling window是10秒)收到19個請
求, 即使19個請求都失敗,也不會觸發circuit break。默認20
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 觸發短路的時間值,當該值設為5000時,則當觸發circuit break后的5000毫秒內都會拒絕request,也就是5000毫秒后才會關閉circuit。
默認5000
hystrix.command.default.circuitBreaker.errorThresholdPercentage錯誤比率閥值,如果錯誤率>=該值,circuit會被打開,並短路所有請求觸發fallback。默認50
hystrix.command.default.circuitBreaker.forceOpen 強制打開熔斷器,如果打開這個開關,那么拒絕所有request,默認false
hystrix.command.default.circuitBreaker.forceClosed 強制關閉熔斷器 如果這個開關打開,circuit將一直關閉且忽略circuitBreaker.errorThresholdPercentageMetrics相關參數
hystrix.command.default.metrics.rollingStats.timeInMilliseconds 設置統計的時間窗口值的,毫秒值,circuit break 的打開會根據1個rolling window的統計來計算。若rolling window被設為10000毫秒,
則rolling window會被分成n個buckets,每個bucket包含success,failure,timeout,rejection的次數的統計信息。默認10000
hystrix.command.default.metrics.rollingStats.numBuckets 設置一個rolling window被划分的數量,若numBuckets=10,rolling window=10000,那么一個bucket的時間即1秒。必須符合rolling window % numberBuckets == 0。默認10
hystrix.command.default.metrics.rollingPercentile.enabled 執行時是否enable指標的計算和跟蹤,默認true
hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds 設置rollingpercentile window的時間,默認60000
hystrix.command.default.metrics.rollingPercentile.numBuckets 設置rolling percentilewindow的numberBuckets。邏輯同上。默認6
hystrix.command.default.metrics.rollingPercentile.bucketSize 如果bucket size=100,window =10s,若這10s里有500次執行,只有最后100次執行會被統計到bucket里去。增加該值會增加內存開銷以及排序 的開銷。默認100
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 記錄health 快照(用
來統計成功和錯誤綠)的間隔,默認500ms
Request Context 相關參數
hystrix.command.default.requestCache.enabled 默認true,需要重載getCacheKey(),返回null時不緩存
hystrix.command.default.requestLog.enabled 記錄日志到HystrixRequestLog,默認true
Collapser Properties 相關參數
hystrix.collapser.default.maxRequestsInBatch 單次批處理的最大請求數,達到該數量觸發批處理,默認 Integer.MAX_VALU
hystrix.collapser.default.timerDelayInMilliseconds 觸發批處理的延遲,也可以為創建批處理的時間+該值,默認10
hystrix.collapser.default.requestCache.enabled 是否對HystrixCollapser.execute() and HystrixCollapser.queue()的cache,默認true
ThreadPool 相關參數
線程數默認值10適用於大部分情況(有時可以設置得更小),如果需要設置得更大,那有個基本得公式可以
follow:
requests per second at peak when healthy × 99th percentile latency in seconds + some
breathing room 每秒最大支撐的請求數 (99%平均響應時間 + 緩存值) 比如:每秒能處理1000個請求,99%的請求響應時間是60ms,那么公式是: 1000 (0.060+0.012)基本得原則時保持線程池盡可能小,他主要是為了釋放壓力,防止資源被阻塞。 當一切都是正常的時候,線程池一般
僅會有1到2個線程激活來提供服務
hystrix.threadpool.default.coreSize 並發執行的最大線程數,默認10
hystrix.threadpool.default.maxQueueSize BlockingQueue的最大隊列數,當設為-1,會使用
SynchronousQueue,值為正時使用LinkedBlcokingQueue。該設置只會在初始化時有效,之后不能修改
threadpool的queue size,除非reinitialising thread executor。默認-1。
hystrix.threadpool.default.queueSizeRejectionThreshold 即使maxQueueSize沒有達到,達到queueSizeRejectionThreshold該值后,請求也會被拒絕。因為maxQueueSize不能被動態修改,這個參數將允許我們動態設置該值。if maxQueueSize == •1,該字段將不起作用
hystrix.threadpool.default.keepAliveTimeMinutes 如果corePoolSize和maxPoolSize設成一樣(默認 實現)該設置無效。如果通過plugin(https://github.com/Netflix/Hystrix/wiki/Plugins)使用自定義 實現,該設置才有用,默認1.
hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds 線程池統計指標的時間,默認10000
hystrix.threadpool.default.metrics.rollingStats.numBuckets 將rolling window划分為n個buckets,默認10

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM