雪崩效應
在微服務架構中,由於服務眾多,通常會涉及多個服務層級的調用,而一旦基礎服務發生故障,很可能會導致級聯故障,進而造成整個系統不可用,這種現象被稱為服務雪崩效應。服務雪崩效應是一種因“服務提供者”的不可用導致“服務消費者”的不可用,並將這種不可用逐漸放大的過程。
比如在一個系統中, A作為服務提供者,B是A的服務消費者,C和D又是B的服務消費者。如果此時A發生故障,則會引起B的不可用,而B的不可用又將導致C和D的不可用,當這種不可用像滾雪球一樣逐漸放大的時候,雪崩效應就形成了。
熔斷器(CircuitBreaker)
熔斷器的原理很簡單,如同電力過載保護器。它可以實現快速失敗,如果它在一段時間內偵測到許多類似的錯誤,就會強迫其以后的多個調用快速失敗,不再訪問遠程服務器,從而防止應用程序不斷地嘗試執行可能會失敗的操作,使得應用程序繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產生。熔斷器也可以使應用程序能夠診斷錯誤是否已經修正,如果已經修正,應用程序會再次嘗試調用操作。熔斷器模式就像是那些容易導致錯誤的操作的一種代理。這種代理能夠記錄最近調用發生錯誤的次數,然后決定使用允許操作繼續,或者立即返回錯誤。熔斷器是保護服務高可用的最后一道防線。
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
因為 Feign 中已經依賴了 Hystrix, 所以在 maven 配置上不用做任何改動就可以使用了,我們在 spring-cloud-consul-consumer 項目中直接改造。
修改配置
在配置文件中添加配置,開啟 Hystrix 熔斷器。
application.yml
#開啟熔斷器 feign: hystrix: enabled: true
創建回調類
創建一個回調類 FeignHelloHystrix,實現 FeignHelloService 接口,並實現對應的方法,返回調用失敗后的信息。
FeignHelloHystrix.java
package com.louis.spring.cloud.consul.consumer.service; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; @Component public class FeignHelloHystrix implements FeignHelloService { @RequestMapping("/hello") public String hello() { return "sorry, this service call failed."; } }
添加fallback屬性
修改 FeignHelloService,在 @FeignClient 注解中加入 fallback 屬性,綁定我們創建的失敗回調處理類。
package com.louis.spring.cloud.consul.consumer.service; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; @FeignClient(name = "service-producer", fallback = FeignHelloHystrix.class) public interface FeignHelloService { @RequestMapping("/hello") public String hello(); }
到此,所有改動代碼就完成了。
測試效果
為了方便測試,我們把負載均衡策略修改為輪詢模式。
啟動成功之后,多次訪問 http://localhost:8521/feign/call,結果如同之前一樣交替返回 hello consul 和 hello consul two。
說明熔斷器的啟動,不會影響正常服務的訪問。
現在手動把 spring-cloud-consul-producer 的服務停掉,再次訪問,返回我們提供的熔斷回調信息,熔斷成功。
重啟 spring-cloud-consul-producer 服務,再次訪問,發現服務又可以訪問了,說明熔斷器具有自我診斷修復的功能。
注意:在重啟成功之后,可能需要一些時間,等待熔斷器進行自我診斷和修復完成之后,方可正常提供服務。
源碼下載
碼雲:https://gitee.com/liuge1988/spring-cloud-demo.git
作者:朝雨憶輕塵
出處:https://www.cnblogs.com/xifengxiaoma/
版權所有,歡迎轉載,轉載請注明原文作者及出處。