Hystrix分布式系統限流、降級、熔斷框架(二)


三、Hystrix容錯

       Hystrix的容錯主要是通過添加容許延遲和容錯方法,幫助控制這些分布式服務之間的交互。 還通過隔離服務之間的訪問點,阻止它們之間的級聯故障以及提供回退選項來實現這一點,從而提高系統的整體彈性。Hystrix主要提供了以下幾種容錯方法:

  • 資源隔離
  • 熔斷
  • 降級

1、資源隔離-線程池


cmd-markdown-logo

cmd-markdown-logo



2、資源隔離-信號量


cmd-markdown-logo



cmd-markdown-logo

線程池和信號量隔離比較
  線程切換 支持異步 支持超時 支持熔斷 限流 開銷
信號量
線程池

       當請求的服務網絡開銷比較大的時候,或者是請求比較耗時的時候,我們最好是使用線程隔離策略,這樣的話,可以保證大量的容器(tomcat)線程可用,不會由於服務原因,一直處於阻塞或等待狀態,快速失敗返回。而當我們請求緩存這些服務的時候,我們可以使用信號量隔離策略,因為這類服務的返回通常會非常的快,不會占用容器線程太長時間,而且也減少了線程切換的一些開銷,提高了緩存服務的效率。

       線程池適合絕大多數的場景,對依賴服務的網絡請求的調用;信號量適合訪問不是對外部依賴的訪問,而是對內部的一些比較復雜的業務邏輯的訪問,只要做信號量的普通限流就可以了。

3、熔斷

為什么要使用斷路器

       在分布式架構中,一個應用依賴多個服務是非常常見的,如果其中一個依賴由於延遲過高發生阻塞,調用該依賴服務的線程就會阻塞,如果相關業務的QPS較高,就可能產生大量阻塞,從而導致該應用/服務由於服務器資源被耗盡而拖垮。另外,故障也會在應用之間傳遞,如果故障服務的上游依賴較多,可能會引起服務的雪崩效應。

cmd-markdown-logo

熔斷器工作的詳細過程如下:

第一步,調用allowRequest()判斷是否允許將請求提交到線程池

1、如果熔斷器強制打開,circuitBreaker.forceOpen為true,不允許放行,返回。

2、如果熔斷器強制關閉,circuitBreaker.forceClosed為true,允許放行。此外不必關注熔斷器實際狀態,也就是說熔斷器仍然會維護統計數據和開關狀態,只是不生效而已。

第二步,調用isOpen()判斷熔斷器開關是否打開

1、如果熔斷器開關打開,進入第三步,否則繼續;

2、如果一個周期內總的請求數小於circuitBreaker.requestVolumeThreshold的值,允許請求放行,否則繼續;

3、如果一個周期內錯誤率小於circuitBreaker.errorThresholdPercentage的值,允許請求放行。否則,打開熔斷器開關,進入第三步。

第三步,調用allowSingleTest()判斷是否允許單個請求通行,檢查依賴服務是否恢復

1、如果熔斷器打開,且距離熔斷器打開的時間或上一次試探請求放行的時間超過circuitBreaker.sleepWindowInMilliseconds的值時,熔斷器器進入半開狀態,允許放行一個試探請求;否則,不允許放行。

此外,為了提供決策依據,每個熔斷器默認維護了10個bucket,每秒一個bucket,當新的bucket被創建時,最舊的bucket會被拋棄。其中每個blucket維護了請求成功、失敗、超時、拒絕的計數器,Hystrix負責收集並統計這些計數器。

cmd-markdown-logo

執行策略如下:

Hystrix遇到一個超時/失敗請求,此時啟動一個10s的窗口,后續的請求會進行如下判斷:

(1)查看失敗次數是否超過最小調用次數

  • 如果沒有超過,則放行請求。
  • 如果超過最小請求數,繼續下面邏輯

(2)判斷失敗率是否超過一個閾值,這里錯誤是指超時和失敗兩種。

  • 如果沒有超過,則放行
  • 如果超過錯誤閾值,則繼續下面邏輯

(3)熔斷器斷開

  • 請求會直接返回失敗。
  • 會開一個5s的窗口,每隔5s調用一次請求,如果成功,表示下游服務恢復,否則繼續保持斷路器斷開狀態。

4、降級

       降級,通常指務高峰期,為了保證核心服務正常運行,需要停掉一些不太重要的業務,或者某些服務不可用時,執行備用邏輯從故障服務中快速失敗或快速返回,以保障主體業務不受影響。

       要支持回退或降級處理,一般是查詢操作,可以重寫HystrixCommand的getFallBack方法或HystrixObservableCommand的resumeWithFallback方法,通常不建議在回退邏輯中執行任何可能失敗的操作。

Hystrix在以下幾種情況下會走降級邏輯:

  • 執行construct()或run()拋出異常
  • 熔斷器打開導致命令短路
  • 命令的線程池和隊列或信號量的容量超額,命令被拒絕
  • 命令執行超時

       如果降級邏輯中需要發起遠程調用,建議重新封裝一個HystrixCommand,使用不同的ThreadPoolKey,與主線程池進行隔離。

四、Hystrix配置

       Hystrix默認使用Netflix Archaius進行配置管理,項目中使用zookeeper作為配置源,通過archaius-zookeeper實現hystrix命令、熔斷器、線程池、監控等參數的動態配置,根據生產環境需要動態調整hystrix參數,實現了對微服務的治理。

       每個Hystrix參數都有4個地方可以配置,優先級從低到高如下,如果每個地方都配置相同的屬性,則優先級高的值會覆蓋優先級低的值:

  • 內置全局默認值:寫死在Hystrix代碼里的默認值,如HystrixCommandProperties.default_executionTimeoutInMilliseconds屬性
  • 動態全局默認屬性:全局配置文件讀到的默認值
  • 內置實例默認值:創建HystrixCommand時,通過注解或者給父類構造器傳參的方式設置的默認值
  • 動態配置實例屬性:通過屬性文件配置特定實例的值

以hystrix命令sns.grassSearchIndex執行的超時時間設置為例,屬性的優先級從低到高為

default_executionTimeoutInMilliseconds=1000
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=500
HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(1000)
hystrix.command.sns.grassSearchIndex.execution.isolation.thread.timeoutInMilliseconds=1500

Command 配置

# 隔離策略: 可選THREAD|SEMAPHORE,默認TREAD
hystrix.command.default.execution.isolation.strategy=TREAD
# 服務超時時間,單位毫秒,默認1000
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000 
# 服務sns.grassSearchIndex超時時間
hystrix.command.sns.grassSearchIndex.execution.isolation.thread.timeoutInMilliseconds=2000
# 是否打開超時檢測,默認啟用true
hystrix.command.default.execution.timeout.enabled=true
# 使用信號量隔離時qps閾值,后續的請求會被拒,默認10
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests=10

熔斷器(Circuit Breaker)配置

# 是否打開斷路器,默認開啟true
hystrix.command.default.circuitBreaker.enabled=true
# 斷路器檢測的基礎請求值,只有時間窗口內的請求數達到這個閾值時,才會判定錯誤率,否則比如只有一兩個請求,即便都失敗了,也不會打開斷路器,因為基數太少了,默認20
hystrix.command.default.circuitBreaker.requestVolumeThreshold=100
# 錯誤百分比,超過就會短路,默認值50
hystrix.command.default.circuitBreaker.errorThresholdPercentage=75
# 指的是從斷路器打開狀態到半開半閉狀態需要的時間,即斷路后,需要等多久才能放一個請求進來,默認值5000
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000

# Metrics
# 統計的時間窗口大小,默認10000
hystrix.command.default.metrics.rollingStats.timeInMilliseconds=10000
# 時間窗口的桶的數目,必須能被時間窗口大小整除,否則報錯,每個bucket包含success,failure,timeout,rejection的次數的統計信息,默認10
hystrix.command.default.metrics.rollingStats.numBuckets=10
# 每一次檢測的間隙。因為就算分窗口統計錯誤率,也會很占cpu,所以每一次統計都會等一個時間間隔再開始,默認500
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds=500
# 帶rollingPercentile的都表示調用時延的統計,該選項表示是否打開時延統計,比如說95分位99分位等,如果關閉都返回-1,默認true
hystrix.command.default.metrics.rollingPercentile.enabled=true
# 時延統計的時間窗口,默認60000
hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds=60000 
# 時延統計的桶數目
hystrix.command.default.metrics.rollingPercentile.numBuckets=6
# 時延統計的桶大小,時延統計每一個桶只維持最新的該數值的請求的數據,早一些的將會被覆蓋。如果bucket size=100,window=10s,若這10s里有500次執行,只有最后100次執行會被統計到bucket里去,增加該值會增加內存開銷以及排序的開銷,默認100
hystrix.command.default.metrics.rollingPercentile.bucketSize=100 

線程池(ThreadPool)配置

# 默認核心線程數,不會變,默認10
hystrix.threadpool.default.coreSize=30
# userLogin隔離線程池核心線程數
hystrix.threadpool.userLogin.coreSize=20
# 等待隊列,還超就會被拒,這個數值無法動態修改,默認-1
hystrix.threadpool.default.maxQueueSize=50000
# userLogin隔離線程池等待隊列
hystrix.threadpool.userLogin.maxQueueSize=3000
# 進入queue時被拒的概率值,即便是沒有達到maxQueueSize。這個為了彌補上面無法動態修改的不足。可以通過這個概率值來控制隊列大小
hystrix.threadpool.default.queueSizeRejectionThreshold=45000
#線程池統計指標的時間,默認10000
hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds=10000
#將rolling window划分為n個buckets,默認10
hystrix.threadpool.default.metrics.rollingStats.numBuckets=10

五、服務監控

Hystrix Dashboard

       Hystrix Dashboard主要用來實時監控Hystrix的各項指標信息。通過Hystrix Dashboard反饋的實時信息,可以幫助我們快速發現系統中存在的問題。

       通過 https://search.maven.org 站點下載standalone-hystrix-dashboard,運行jar包后訪問http://localhost:7979/hystrix-dashboard/,即可進入hystrix dashboard頁面

nohup java -jar -DserverPort=7979 -DbindAddress=localhost standalone-hystrix-dashboard-1.5.3-all.jar &

cmd-markdown-logo

       集群環境監控可使用Netflix提供的turbine進行監控。通過maven公服https://search.maven.org下載並部署war包turbine-web,修改集群節點配置,將turbine地址http://localhost:${port}/turbine.stream?cluster=default添加監控到dashboard

cmd-markdown-logo

turbine.aggregator.clusterConfig=default
turbine.instanceUrlSuffix=:8080/gateway/hystrix.stream
turbine.ConfigPropertyBasedDiscovery.test.instances=10.66.70.1,10.66.70.2,10.66.70.3


免責聲明!

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



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