天天看點

springcloud(四):熔斷器Hystrix

說起springcloud熔斷讓我想起了去年股市中的熔斷,多次痛的領悟,随意實施的熔斷對整個系統的影響是災難性的,好了接下來我們還是說正事。

熔斷器

雪崩效應

在微服務架構中通常會有多個服務層調用,基礎服務的故障可能會導緻級聯故障,進而造成整個系統不可用的情況,這種現象被稱為服務雪崩效應。服務雪崩效應是一種因“服務提供者”的不可用導緻“服務消費者”的不可用,并将不可用逐漸放大的過程。

如果下圖所示:A作為服務提供者,B為A的服務消費者,C和D是B的服務消費者。A不可用引起了B的不可用,并将不可用像滾雪球一樣放大到C和D時,雪崩效應就形成了。

springcloud(四):熔斷器Hystrix

熔斷器(CircuitBreaker)

熔斷器的原理很簡單,如同電力過載保護器。它可以實作快速失敗,如果它在一段時間内偵測到許多類似的錯誤,會強迫其以後的多個調用快速失敗,不再通路遠端伺服器,進而防止應用程式不斷地嘗試執行可能會失敗的操作,使得應用程式繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的逾時産生。熔斷器也可以使應用程式能夠診斷錯誤是否已經修正,如果已經修正,應用程式會再次嘗試調用操作。

熔斷器模式就像是那些容易導緻錯誤的操作的一種代理。這種代理能夠記錄最近調用發生錯誤的次數,然後決定使用允許操作繼續,或者立即傳回錯誤。 熔斷器開關互相轉換的邏輯如下圖:

springcloud(四):熔斷器Hystrix

熔斷器就是保護服務高可用的最後一道防線。

Hystrix特性

1.斷路器機制

斷路器很好了解, 當Hystrix Command請求後端服務失敗數量超過一定比例(預設50%), 斷路器會切換到開路狀态(Open). 這時所有請求會直接失敗而不會發送到後端服務. 斷路器保持在開路狀态一段時間後(預設5秒), 自動切換到半開路狀态(HALF-OPEN). 這時會判斷下一次請求的傳回情況, 如果請求成功, 斷路器切回閉路狀态(CLOSED), 否則重新切換到開路狀态(OPEN). Hystrix的斷路器就像我們家庭電路中的保險絲, 一旦後端服務不可用, 斷路器會直接切斷請求鍊, 避免發送大量無效請求影響系統吞吐量, 并且斷路器有自我檢測并恢複的能力.

2.Fallback

Fallback相當于是降級操作. 對于查詢操作, 我們可以實作一個fallback方法, 當請求後端服務出現異常的時候, 可以使用fallback方法傳回的值. fallback方法的傳回值一般是設定的預設值或者來自緩存.

3.資源隔離

在Hystrix中, 主要通過線程池來實作資源隔離. 通常在使用的時候我們會根據調用的遠端服務劃分出多個線程池. 例如調用産品服務的Command放入A線程池, 調用賬戶服務的Command放入B線程池. 這樣做的主要優點是運作環境被隔離開了. 這樣就算調用服務的代碼存在bug或者由于其他原因導緻自己所線上程池被耗盡時, 不會對系統的其他服務造成影響. 但是帶來的代價就是維護多個線程池會對系統帶來額外的性能開銷. 如果是對性能有嚴格要求而且确信自己調用服務的用戶端代碼不會出問題的話, 可以使用Hystrix的信号模式(Semaphores)來隔離資源.

Feign Hystrix

因為熔斷隻是作用在服務調用這一端,是以我們根據上一篇的示例代碼隻需要改動spring-cloud-consumer項目相關代碼就可以。因為,Feign中已經依賴了Hystrix是以在maven配置上不用做任何改動。

1、配置檔案

application.properties添加這一條:

  1. feign.hystrix.enabled=true

2、建立回調類

建立HelloRemoteHystrix類繼承與HelloRemote實作回調的方法

  1. @Component
  2. public class HelloRemoteHystrix implements HelloRemote{
  3.    @Override
  4.    public String hello(@RequestParam(value = "name") String name) {
  5.        return "hello" +name+", this messge send failed ";
  6.    }
  7. }

3、添加fallback屬性

在 HelloRemote類添加指定fallback類,在服務熔斷的時候傳回fallback類中的内容。

  1. @FeignClient(name= "spring-cloud-producer",fallback = HelloRemoteHystrix.class)
  2. public interface HelloRemote {
  3.    @RequestMapping(value = "/hello")
  4.    public String hello(@RequestParam(value = "name") String name);

改動點就這點,很簡單吧。

4、測試

那我們就來測試一下看看效果吧。

依次啟動spring-cloud-eureka、spring-cloud-producer、spring-cloud-consumer三個項目。

浏覽器中輸入: http://localhost:9001/hello/neo

傳回: hello neo,thisisfirst messge

說明加入熔斷相關資訊後,不影響正常的通路。接下來我們手動停止spring-cloud-producer項目再次測試:

傳回: hello neo,thismessge send failed

繼續閱讀