SpringCloud微服務項目實戰 - 限流、熔斷、降級處理

我們知道,在分佈式微服務項目體系中,一個系統是由若干個子服務模塊組成,這若干個子服務相互調用協同工作,對外輸出服務使得整個系統運作。

由於服務之間的相互協作調用,所以要保證整個系統完整運行,就得保證每個服務模塊運行良好。但在實際龐大的分佈式體系中,我們難免遇到某個服務阻塞或掛起等情況。假設客戶在下單時,需要調用訂單服務的接口,而訂單服務有依賴了客戶服務、商品服務、庫存服務等,在下單時如果依賴的某個服務發生異常(請求超時),所有的請求就阻塞在這個依賴服務上,則會造成整個下單接口調用失敗。就會導致整個系統下單不可用甚至雪崩,那這種問題如何解決呢?這將是我們文章裏今天要討論的話題。

在SpringCloud分佈式項目中,爲了保證服務的高可用,Netflix的組件Hystrix可以將這些請求隔離,針對服務限流,當某個服務不可用時能夠熔斷並降級,防止級聯故障。

什麼是Hystrix?

Hystrix中文翻譯 豪豬,由於其背上長滿了棘刺,從而擁有自我保護的能力。Hystrix作爲Netflix開源的一款容錯框架,同樣具有自我保護能力。

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

"斷路器" 本身是一種開關裝置,當有服務發生故障後,通過斷路器的故障監控(類似保險熔斷),向調用方返回一個符合預期的、可處理的備選響應(FallBack) ,而不是等待/超時或拋出異常,這樣就保證了服務調用方的線程不會長時間,不必要地佔用,從而避免了故障在分佈式系統無線的蔓延,防止了雪崩效應的發生。

爲了實現容錯和自我保護,我們先看一下Hystrix的設計和實現。

Hystrix設計目標:

  • 對來自依賴的延遲和故障進行防護和控制——這些依賴通常都是通過網絡訪問的

  • 阻止故障的連鎖反應

  • 快速失敗並迅速恢復

  • 回退並優雅降級

  • 提供近實時的監控與告警

Hystrix遵循的設計原則:

  • 防止任何單獨的依賴耗盡資源(線程)

  • 過載立即切斷並快速失敗,防止排隊

  • 儘可能提供回退以保護用戶免受故障

  • 使用隔離技術(例如隔板,泳道和斷路器模式)來限制任何一個依賴的影響

  • 通過近實時的指標,監控和告警,確保故障被及時發現

  • 通過動態修改配置屬性,確保故障及時恢復

  • 防止整個依賴客戶端執行失敗,而不僅僅是網絡通信

Hystrix實現限流熔斷降級

1,通過Command實現

首先添加Hystrix的pom依賴:

配置Hystrix屬性(yml文件):

# Hystrix 默認加載的配置文件 - 限流、 熔斷
hystrix:
  # 線程池大小
  threadpool:
    default:
      coreSize: 1
      maxQueueSize: 200
      queueSizeRejectionThreshold: 2


    # 限流策略
    #如果沒有定義HystrixThreadPoolKey,HystrixThreadPoolKey會默認定義爲HystrixCommandGroupKey的值
    userGroup:
      coreSize: 1
      maxQueueSize: -1
      queueSizeRejectionThreshold:  800


    userThreadPool:
      coreSize: 1
      maxQueueSize: -1
      queueSizeRejectionThreshold:  800


# 執行策略
# 資源隔離模式,默認thread。還有一種叫信號量
  command:
    default:
      execution:
        isolation:
          strategy: THREAD
        # 是否打開超時
        timeout:
          enabled:  true
        # 超時時間,默認1000毫秒
        isolation:
          thread:
            timeoutInMilliseconds:  15000
            # 超時時中斷線程
            interruptOnTimeout: true
            # 取消時候中斷線程
            interruptOnFutureCancel: false
            # 信號量模式下,最大併發量
          semaphore:
            maxConcurrentRequests:  2
      # 降級策略
      # 是否開啓服務降級
      fallback:
        enabled:  true
        # fallback執行併發量
        isolation:
          semaphore:
            maxConcurrentRequests:  100
      # 熔斷策略
      # 啓用/禁用熔斷機制
      circuitBreaker:
        enabled:  true
        # 強制開啓熔斷
        forceOpen:  false
        # 強制關閉熔斷
        forceClosed:  false
        # 前提條件,一定時間內發起一定數量的請求。也就是5秒鐘內(這個5秒對應下面的滾動窗口長度)至少請求4次,熔斷器才發揮起作用。默認20
        requestVolumeThreshold: 4
        # 錯誤百分比。達到或超過這個百分比,熔斷器打開。比如:5秒內有4個請求,2個請求超時或者失敗,就會自動開啓熔斷
        errorThresholdPercentage: 50
        # 10秒後,進入半打開狀態(熔斷開啓,間隔一段時間後,會讓一部分的命令去請求服務提供者,如果結果依舊是失敗,則又會進入熔斷狀態,如果成功,就關閉熔斷)。默認5秒
        sleepWindowInMilliseconds:  10000


      # 度量策略
      # 5秒爲一次統計週期,術語描述:滾動窗口的長度爲5秒
      metrics:
        rollingStats:
          timeInMilliseconds: 5000
          # 統計週期內 度量桶的數量,必須被timeInMilliseconds整除。作用:
          numBuckets: 10
        # 是否收集執行時間,並計算各個時間段的百分比
        rollingPercentile:
          enabled:  true
          # 設置執行時間統計週期爲多久,用來計算百分比
          timeInMilliseconds: 60000
          # 執行時間統計週期內,度量桶的數量
          numBuckets: 6
          # 執行時間統計週期內,每個度量桶最多統計多少條記錄。設置爲50,有100次請求,則只會統計最近的10次
          bucketSize: 100
        # 數據取樣時間間隔
        healthSnapshot:
          intervalInMilliseconds: 500


      # 設置是否緩存請求,request-scope內緩存
      requestCache:
        enabled:  false
      # 設置HystrixCommand執行和事件是否打印到HystrixRequestLog中
      equestLog:
          enabled:  false
          
  userCommandKey:
    execution:
      isolation:
        thread:
          timeoutInMilliseconds: 5000

編寫Command類:

在服務提供者中寫調用的接口:

在當前服務中添加接口:

這裏HystrixCommand的每次都必須使用新的對象(保證每次請求都是一個新的線程)調用其execute方法,而不能使用單例。否則會提示

Thisinstance can only be executed once.Please instantiate a new instance.

服務降級

請求order-service的/order/exception接口,因爲customer-service的/customer/exception會隨機拋出運行時異常。當服務異常時,將返回“服務已降級,暫不可用”,而服務正常時將返回ok。這說明我們的服務因爲異常降級。

請求/order/timeout接口時,“服務已降級,暫不可用”。如果修改hystrix.command.userCommandKey.execution.isolation.thread.timeoutInMilliseconds=10000,Hstrix限制的超時時間大於接口的返回時長,就能成功返回ok。這個例子說明服務因爲請求超時降級了。

服務限流

在分佈式環境中,每個服務模塊的請求承載量是有限的,因此爲保證服務正常,我們會限制來自客戶端請求的併發數。可以通過semaphore.maxConcurrentRequests.coreSize.maxQueueSize和queueSizeRejectionThreshold設置信號量模式下的最大併發量、線程池大小、緩衝區大小和緩衝區降級閾值。在示例中我們作如下設置

  • #不設置緩衝區,當請求數超過coreSize時直接降級

  • hystrix.threadpool.userThreadPool.maxQueueSize=-1

  • #超時時間大於我們的timeout接口返回時間

  • hystrix.command.userCommandKey.execution.isolation.thread.timeoutInMilliseconds=10000

這個時候當連續多次請求/order/timeout接口,在第一個請求還沒有成功返回時,查看輸出日誌可以發現只有第一個請求正常的進入到order-service的接口中,其它請求會直接返回降級信息。這樣我們就實現了對服務請求的限流。

服務熔斷

在yml配置中開啓熔斷,並且以5秒爲度量週期,當5秒內請求超過4個錯誤超過50%時,就會開啓熔斷器,所有的請求都會直接降級,如果5秒內的請求不夠4個,就算有三個請求且全部失敗也不會開啓熔斷器。10秒後熔斷器進入半打開狀態會讓一部分請求向服務端發起調用,如果成功關閉熔斷器,否則再次進入熔斷狀態。

我們對order-serivce的/order/exception連續發起請求(5秒內至少4次),當我們的請求異常超過50%時,服務會直接返回降級信息。
實際上當服務異常、超時、宕機並滿足熔斷條件時,都會開啓熔斷。

2,通過FeignClient集成實現

前面通過Command要對每個接口寫command類,很是麻煩,但使用Hystrix和Feign的集成就十分方便了。需要在啓動類中添加註解@EnableCircuitBreaker啓用熔斷機制。

添加Feign客戶端和降級類

降級類:

再在Controller添加接口:

今天要說的就講到這裏,我們下一篇繼續講SpringCloud微服務項目實戰。代碼我也講上傳到github,請注意後續動態。

推薦閱讀:

SpringCloud微服務項目實戰 -  API網關Gateway詳解實現

SpringCloud微服務項目實戰 - 網關zuul詳解及搭建

SpringCloud微服務項目實戰 - 微服務調用詳解(附面試題)

SpringCloud微服務項目實戰,服務註冊與發現(附面試題)

Spring Cloud微服務項目實戰--Eureka服務搭建



掃碼關注公衆號,發送關鍵詞獲取相關資料:發“Springboot”領取電商項目實戰源碼;發“SpringCloud”領取學習實戰資料;

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