在之前的文章中,我們先后介紹了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,敬請期待!
本文由博客一文多發平台 OpenWrite 發布!