javascript
SpringCloud之Hystrix
簡介
在分布式環境中,許多服務依賴關系中的一些必然會失敗。Hystrix是一個庫,它通過添加延遲容忍和容錯邏輯來幫助您控制這些分布式服務之間的交互。Hystrix通過隔離服務之間的訪問點、停止跨服務的級聯故障并提供回退選項來實現這一點,所有這些選項都提高了系統的總體彈性。
目標
Hystrix的設計目的如下:
- 為通過第三方客戶端庫訪問的依賴項(通常通過網絡)提供保護和控制延遲和故障。
- 停止復雜分布式系統中的級聯故障。
- 故障快速恢復。
- 在可能的情況下,后退并優雅地降級。
- 啟用近實時監視、警報和操作控制。
背景
為了解決什么問題?
復雜分布式體系結構中的應用程序有幾十個依賴項,每個依賴項在某個時候都不可避免地會失敗。如果主機應用程序沒有從這些外部故障中隔離出來,那么它就有可能與這些外部故障一起宕機。
例如,對于一個依賴于30個服務的應用程序,其中每個服務都有99.99%的正常運行時間,您可以這樣期望:
99.9930 = 99.7% uptime 0.3% of 1 billion requests = 3,000,000 failures 2+ hours downtime/month even if all dependencies have excellent uptime.
現實通常更糟。 即使當所有依賴項都運行良好時,即使0.01%的停機時間對幾十個服務中的每個服務的總體影響也相當于一個月潛在的停機時間(如果您不為恢復而設計整個系統)。
如下面的圖演變:
當一切正常時,請求流可以是這樣的:
當許多后端系統之一成為潛在,它可以阻止整個用戶請求:
對于高流量,一個后端依賴項成為潛在,可能會導致所有服務器上的所有資源在幾秒鐘內飽和。 應用程序中通過網絡或客戶機庫到達可能導致網絡請求的每個點都是潛在故障的來源。比故障更糟的是,這些應用程序還可能導致服務之間的延遲增加,從而備份隊列、線程和其他系統資源,從而導致系統中出現更多級聯故障。
工作原理
工作流程圖:
1. 構造一個HystrixCommand或HystrixObservableCommand對象
第一步是構造一個HystrixCommand或HystrixObservableCommand對象來表示對依賴項的請求。將請求發出時需要的任何參數傳遞給構造函數。 如果期望依賴項返回單個響應,則構造一個HystrixCommand對象。例如:
HystrixCommand command = new HystrixCommand(arg1, arg2); 復制代碼如果期望依賴項返回發出響應的可觀察對象,則構造一個HystrixObservableCommand對象。例如:
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2); 復制代碼2.執行命令
有四種方法可以執行命令,使用以下四種方法之一的Hystrix命令對象(前兩種方法只適用于簡單的HystrixCommand對象,不適用于HystrixObservableCommand):
- execute()?— blocks, then returns the single response received from the dependency (or throws an exception in case of an error)
- queue()?— returns a?Future?with which you can obtain the single response from the dependency
- observe()?— subscribes to the?Observable?that represents the response(s) from the dependency and returns an?Observable?that replicates that source?Observable
- toObservable()?— returns an?Observable?that, when you subscribe to it, will execute the Hystrix command and emit its responses
3.是否緩存了響應
如果為該命令啟用了請求緩存,并且在緩存中可用對請求的響應,則此緩存的響應將立即以可觀察到的形式返回。
4. 電路打開了嗎?
當您執行該命令時,Hystrix將與斷路器一起檢查電路是否打開。 如果電路打開(或“跳閘”),那么Hystrix將不執行命令,而是將流路由到(8)獲取回退。 如果電路被關閉,則流繼續到(5),檢查是否有可用的容量來運行命令。
5.線程池/隊列/信號量是否已滿?
如果與該命令關聯的線程池和隊列(或信號量,如果不在線程中運行)已滿,那么Hystrix將不執行該命令,而是立即將流路由到(8)獲取回退。
6.HystrixObservableCommand.construct()或HystrixCommand.run ()
這里,Hystrix通過為此目的編寫的方法調用對依賴項的請求,方法如下:
- HystrixCommand.run()?— returns a single response or throws an exception
- HystrixObservableCommand.construct()?— returns an Observable that emits the response(s) or sends an?onError?notification
如果run()或construct()方法超過了命令的超時值,線程將拋出一個TimeoutException(如果命令本身不在自己的線程中運行,則單獨的計時器線程將拋出一個TimeoutException)。在這種情況下,Hystrix將響應路由到8。獲取回退,如果最終返回值run()或construct()方法沒有取消/中斷,那么它將丟棄該方法。 請注意,沒有辦法強制潛在線程停止工作——Hystrix在JVM上能做的最好的事情就是拋出InterruptedException。如果由Hystrix包裝的工作不尊重interruptedexception,那么Hystrix線程池中的線程將繼續它的工作,盡管客戶機已經收到了TimeoutException。這種行為可能會使Hystrix線程池飽和,盡管負載“正確釋放”。大多數Java HTTP客戶端庫不解釋interruptedexception。因此,請確保正確配置HTTP客戶機上的連接和讀/寫超時。 如果該命令沒有拋出任何異常并返回一個響應,那么Hystrix將在執行一些日志記錄和度量報告之后返回此響應。在run()的情況下,Hystrix返回一個可觀察的對象,該對象發出單個響應,然后發出一個onCompleted通知;在construct()的情況下,Hystrix返回由construct()返回的相同的可觀察值。
7.計算電路健康
Hystrix向斷路器報告成功、失敗、拒絕和超時,斷路器維護一組滾動計數器,用于計算統計數據。 它使用這些統計數據來確定電路應該在什么時候“跳閘”,在這一點上,它會短路任何后續的請求,直到恢復期結束,在此期間,它會在第一次檢查某些健康檢查之后再次關閉電路。
8.回退
Hystrix試圖恢復你的回滾命令執行失敗時:當一個異常的構造()或()運行(6),當命令電路短路,因為打開(4),當命令的線程池和隊列或信號能力(5),或者當命令已超過其超時長度。 詳情參考官網:github.com/Netflix/Hys…
9. 返回成功的響應
如果Hystrix命令成功,它將以可觀察到的形式返回響應或響應給調用者。根據您如何調用上面步驟2中的命令,這個可觀察對象可能在返回給您之前進行轉換:
- execute() — 以與.queue()相同的方式獲取一個Future,然后在這個Future上調用get()來獲取可觀察對象發出的單個值.
- queue() — 將可觀察對象轉換為BlockingObservable,以便將其轉換為未來,然后返回此未來
- observe() — 立即訂閱可觀察對象,并開始執行命令的流;返回一個可觀察對象,當您訂閱該對象時,將重播排放和通知
- toObservable() — 返回可觀察值不變;您必須訂閱它,才能真正開始執行命令的流程
更多原理可以移步官網 github.com/Netflix/Hys…
使用
加入依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>復制代碼在ribbon中使用
使用@EnableHystrix開啟
@SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient @EnableHystrix public class CloudServiceRibbonApplication {public static void main(String[] args) {SpringApplication.run(CloudServiceRibbonApplication.class, args);}@Bean@LoadBalancedRestTemplate restTemplate() {return new RestTemplate();}} 復制代碼該注解對該方法創建了熔斷器的功能,并指定了fallbackMethod熔斷方法,熔斷方法直接返回了一個字符串,字符串為"hi,"+name+",sorry,error!"
@Service public class TestService {@AutowiredRestTemplate restTemplate;@HystrixCommand(fallbackMethod = "hiError")public String hiService(String name) {return restTemplate.getForObject("http://CLOUD-EUREKA-CLIENT/hi?name="+name,String.class);}public String hiError(String name) {return "hi,"+name+",sorry,error!";}} 復制代碼在Feign中使用
feign.hystrix.enabled: true 開啟hystrix
eureka:client:serviceUrl:defaultZone: http://localhost:8761/eureka/ server:port: 8765 spring:application:name: cloud-service-feignfeign.hystrix.enabled: true 復制代碼@EnableFeignClients啟動
@SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient @EnableFeignClients public class CloudServiceFeginApplication {public static void main(String[] args) {SpringApplication.run(CloudServiceFeginApplication.class, args);}} 復制代碼**fallback:**配置連接失敗等錯誤的返回類
@FeignClient(value = "cloud-eureka-client",fallback = TestServiceHystric.class) public interface TestService {@RequestMapping(value = "/hi",method = RequestMethod.GET)String sayHiFromClientOne(@RequestParam(value = "name") String name);}復制代碼當訪問接口有問題時,直接調用此接口返回。
@Component public class TestServiceHystric implements TestService{@Overridepublic String sayHiFromClientOne(String name) {return "sorry "+name;} }復制代碼更多使用技巧可參考官網: github.com/Netflix/Hys…
總結
在微服務架構中通常會有多個服務層調用,基礎服務的故障可能會導致級聯故障,進而造成整個系統不可用的情況,這種現象被稱為服務雪崩效應。服務雪崩效應是一種因“服務提供者”的不可用導致“服務消費者”的不可用,并將不可用逐漸放大的過程。
熔斷器的原理很簡單,如同電力過載保護器。它可以實現快速失敗,如果它在一段時間內偵測到許多類似的錯誤,會強迫其以后的多個調用快速失敗,不再訪問遠程服務器,從而防止應用程序不斷地嘗試執行可能會失敗的操作,使得應用程序繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產生。熔斷器也可以使應用程序能夠診斷錯誤是否已經修正,如果已經修正,應用程序會再次嘗試調用操作。
更多優質文章:
- www.ityouknow.com/springcloud…
- www.fangzhipeng.com/springcloud…
- blog.didispace.com/tags/Hystri…
最后
如果對 Java、大數據感興趣請長按二維碼關注一波,我會努力帶給你們價值。覺得對你哪怕有一丁點幫助的請幫忙點個贊或者轉發哦。
轉載于:https://juejin.im/post/5ca96bdce51d452b573e2a1c
總結
以上是生活随笔為你收集整理的SpringCloud之Hystrix的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模块与包
- 下一篇: LeetCode 之 JavaScrip