1. 程式人生 > >Spring-cloud微服務實戰【七】:服務熔斷與降級hystrix

Spring-cloud微服務實戰【七】:服務熔斷與降級hystrix

  在之前的文章中,我們先後介紹了eureka,ribbon,feign,使用eureka叢集的方式來保證註冊中心的高可用,在eureka中使用ribbon進行負載均衡,使用feign介面替換手動編碼請求介面的程式碼,整個微服務看似基本完成了,那是否有繼續值得優化的地方呢?答案肯定是有的,並且是整個微服務最重要的一環,那就是服務的熱熔斷與降級,那為什麼服務熔斷與降級是最重要的一環呢?我們先來看一下服務雪崩的概念.

服務雪崩

  所謂服務雪崩,是微服務系統中特有的概念,不瞭解服務雪崩的概念的童鞋,初一聽服務雪崩,肯定會聯想到快取雪崩,所謂快取雪崩,即大量快取在同一時間過期,導致大量請求不走快取而進行資料庫訪問,資料庫瞬時壓力暴增,導致資料庫宕機.一般我們的解決方案無非有幾點:
1.為不同的快取設定不同的過期時間.
2.熱點資料永不過期.
3.快取預熱.
  我們之所以要預防快取雪崩,從系統架構五個方面(高效能/高可用/伸縮性/擴充套件性/安全性)來講,是保證系統的高效能以及保護資料庫,而我們說要預防服務雪崩,是為了保證整個微服務系統的可用性,讓我們用一張圖來說說明:

  假設在一個電商微服務系統中,有使用者服務,訂單服務,產品服務,物流服務等服務,使用者服務呼叫訂單服務,訂單服務呼叫產品服務,產品服務呼叫物流服務,如果沒有考慮服務的熔斷與降級,假如在產品服務呼叫物流服務的時候,物流服務本身出問題了返回了錯誤或者是網路波動導致請求超時,則產品服務會報錯,從而影響訂單服務跟著報錯,層層返回,直到最頂層的服務,這樣就導致了一個微服務自身的問題影響了整個微服務系統級聯報錯,這就是所謂的服務雪崩,極端情況下,可能導致幾個甚至整個微服務系統全部宕機,這對於現代微服務系統來說,是無法忍受的,因此,我們需要進行服務的熔斷與降級.
  需要注意的是,服務的熔斷與降級是兩個概念,一般而言,所謂服務熔斷,是對服務提供方而言,當服務提供方無法呼叫的時候需要被熔斷,而降級是對服務消費方而言,當服務提供方無法正常提供服務時,消費方需要降級處理.spring cloud中對服務的熔斷和降級是使用hystrix,接下來,讓我們詳細瞭解一下hystrix.

服務熔斷與降級hystrix

  spring cloud中使用hystrix進行服務的熔斷和降級,hystrix翻譯成中文是豪豬的意思,它是Netflix開源的一款針對分散式系統進行服務熔斷與降級的框架.那麼我們如何使用呢?讓我們直接用程式碼來演示一下:
  把之前我們的專案dhp-micro-service-producer複製一份為dhp-micro-service-producer-hystrix:

  將之加入父專案:

  老規矩,三個步驟,首先新增maven依賴:

  然後修改程式碼:

  其中@HystrixCommand的作用是指定一個熔斷方法,當有該註解的方法丟擲異常的時候,會呼叫fallbackMethod指定的方法,該方法需要我們自己根據業務需要來完成.需要注意的是,方法的入參和返回值都必須要和原始方法保持一致.
  修改一下配置檔案,注意eureka註冊中心的地址和埠號,我這裡修改埠號為7301:

  最後修改啟動類,增加對hystrix的支援:

  然後啟動來訪問試一試,注意如果啟動報錯,看看是否eureka-server未啟動,但這並不影響我們的測試,由於我們在producer專案中的product資訊是使用程式碼方式來mock資料庫操作:

  總計只有6條資料,因此ID>6均查不出資料,返回product=null,就會觸發我們設定的降級方法,因此訪問試一試:

  說明我們的服務提供方在服務出現異常時的熔斷方法已經成功使用了,但這還不夠,在某些情況下,服務的提供方並沒有問題,但是可能由於網路原因導致消費方並不能成功呼叫到提供方的介面,此時服務提供方的任何處理都是毫無意義的,因此我們需要在消費者端進行服務降級.
  由於我們之前使用feign進行介面代理,而feign中已經集成了hystrix,因此我們需要改造consumer端程式碼:
  首先在feign代理介面中新增fallbackFactory指定降級服務的類:

  然後實現該類,該類需要實現FallbackFactory介面的create方法,返回一個泛型指定的服務,並且實現該指定介面中的所有方法的降級處理:

  然後我們可以驗證一下:首先啟動eureka-server,然後啟動producer,將producer註冊到eureka:

  可以看到,我們修改埠號為7301的producer[dhp-micro-service-producer-hystrix]已經成功註冊到eureka,然後再啟動consumer[dhp-micro-service-consumer-feign],我修改埠號為7005,並且還需要開啟feign.hystrix.enabled=true,預設是false:

  啟動成功後,訪問一下試一試:

  當我們id=1時,可以成功獲取結果,再試一試當ID>6時的情況:

  從描述可以看到,這是執行了producer[dhp-micro-service-producer-hystrix]的熔斷方法,那我們如何來驗證消費者端的降級方法呢?首先需要關閉eureka-server的自我保護功能,並且設定10秒自檢一次,剔除無效的服務:

  那麼如何算無效呢?這需要服務提供方進行設定,修改producer[dhp-micro-service-producer-hystrix]傳送心跳時間以及服務過期時間,以便儘快讓eureka-server剔除producer:

  這裡我們為了快速讓eureka-server剔除producer,設定5秒(預設值為30秒)傳送1次心跳,並且告訴eureka-server,假如15秒(預設值為90秒,一般為心跳間隔時間的3倍)內沒有傳送任何心跳,則eureka-server將producer剔除,此時,eureka-server主動失效檢測時間為10秒,則當我們停止producer後最多25秒eureka-server會將producer剔除,此時再訪問consumer:

  可以看到,這是執行了我們consumer的降級方法,自此hystrix在服務提供方和消費方的配置都完成了,是不是很簡單?接下來,讓我們再瞭解一下hystrix的儀表盤dashboard.

HystrixDashboard

  Dashboard(儀表盤)是hystrix提供的一種用於服務監控的功能,可以利用它對某一個微服務進行監控,讓我們來試一試,首先新建一個module[dhp-micro-service-hystrix-dashboard]:

  然後將之加入父專案:

  接下來新增maven依賴:

  然後配置檔案修改服務埠號:

  然後啟動類新增對dashboard的支援:

  啟動起來看一下:

  那麼該如何使用呢?首先,需要確保被監控的服務有健康檢查的依賴,比如我們對producer[dhp-micro-service-producer-hystrix]進行監控,則需要確保producer的maven配置中有健康檢查的相關依賴:

  並且還需要相關的配置:

  然後啟動producer,並且在hystrix dashboard中輸入對應的producer的地址,則就能監控到所有的對該地址的訪問:

  此時再訪問該producer的相關介面,就能看到相關統計資訊了:

  至於其中每項資料的含義,我相信肯定難不倒各位廣大童鞋,畢竟有問題找度娘,大家都知道,有條件就Google,沒有任何問題能難倒我們.

Turbine

  細心的同學會發現,之前我們在hystrix-dashboard的首頁上看到了這麼一行提示:

  翻譯一下,就是告訴我們如果是使用turbine的方式,監控地址的格式是turbine-hostname:port/turbine.stream,如果是單一的hystrix-app的方式,地址格式是hystrix-app:port/actuator/hystrix.stream,我們之前就是使用的單一的這種方式,那麼turbine又是什麼呢?

  我們在上面說到,dashboard只能對某一個微服務進行監控,但實際情況是一個微服務生產系統遠遠不止一個微服務,我們需要對所有的微服務都進行監控,而dashboard顯然無法滿足我們的需求,而turbine則可以,因此turbine的作用就是可以對多個微服務同時進行監控.為了方便演示turbine對多個微服務的監控,我們新建一個module[dhp-micro-service-user-hystrix]:

  然後加入父專案:

  然後老規矩,三個步驟,先配置maven依賴:

  然後再配置application.properties:

  相關配置具體的含義就不在多說了,之前的文章已經講得很詳細了,接著修改主類:

  然後進行編碼:

  相關程式碼和producer類似,然後啟動eureka-server,再啟動user和producer:

  可以看到兩個服務都已經註冊到eureka了,然後使用dashboard測試一下:

  沒有問題,說明可以,接下來,我們使用turbine同時監控producer和user服務,為了便於和之前的dashboard比較,我們新增一個turbine module[dhp-micro-service-turbine-dashboard]:

  將之加入父專案:

  然後老規矩,首先配置maven依賴:

  然後配置application.properties:

  其中最重要的就是需要配置turbine相關資訊,app-config標識需要監控的服務,多個用逗號隔開,並且從名字我們可以看出就是eureka中註冊的服務的服務名:

  新增主類配置:

  然後先啟動eureka-server,再啟動user[dhp-micro-service-user-hystrix]和producer[dhp-micro-service-producer-hystrix]兩個服務,再啟動dashboard[dhp-micro-service-hystrix-dashboard],最後啟動turbine[dhp-micro-service-turbine-dashboard],然後訪問dashboard[dhp-micro-service-hystrix-dashboard],並監控turbine的地址:

  然後分別請求user和producer:

  然後看一下hystrix-dashboard:

  發現只監控到了userController,但是並沒有監控到ProducerController,這是為什麼呢?是我們配置不對嗎?彆著急,我們來看一下控制檯的資訊:

  提示資訊告訴我們,有一個連線被拒絕,因此放棄turbine對其的監控,失敗的地址是192.168.1.13:7301,可以看出這是我們的producer服務的地址,另外提示資訊中status401,error和message都提示我們,未授權的登入,回憶一下,之前我們的producer專案引入了dhp-micro-service-auth進行安全驗證,需要使用者名稱和密碼,因此我們找到了原因:登入producer時未授權,導致監控失敗,那這該如何解決呢?很遺憾,turbine既能監控所有服務都有密碼的情形,也能監控所有服務都沒有密碼的情形,但是對於有些服務有密碼,而有些服務沒有密碼的情形,turbine就無能為力了,如果實在因為生產需要要適配,我們只能通過修改dhp-micro-service-auth的方式,來讓相應的服務取消對/actuator/hystrix.stream與/turbine.stream這兩個地址的密碼驗證:

  此時再重啟一下producer,然後再次訪問user和producer,再看一下dashboard:

  此時producerController和UserController均成功被turbine監控了.

  回顧一下,在本文我們介紹了spring-cloud斷路器hystrix以及對hystrix的單個服務監控hystrix-dashboard以及對多個服務監控的turbine,下一篇文章,我們繼續介紹閘道器zuul,敬請期待!

  本文的github地址

本文由部落格一文多發平臺 OpenWrite 釋出!