javascript
SpringCloud之Hystrix
簡介
在分布式環(huán)境中,許多服務(wù)依賴關(guān)系中的一些必然會失敗。Hystrix是一個庫,它通過添加延遲容忍和容錯邏輯來幫助您控制這些分布式服務(wù)之間的交互。Hystrix通過隔離服務(wù)之間的訪問點、停止跨服務(wù)的級聯(lián)故障并提供回退選項來實現(xiàn)這一點,所有這些選項都提高了系統(tǒng)的總體彈性。
目標(biāo)
Hystrix的設(shè)計目的如下:
- 為通過第三方客戶端庫訪問的依賴項(通常通過網(wǎng)絡(luò))提供保護(hù)和控制延遲和故障。
- 停止復(fù)雜分布式系統(tǒng)中的級聯(lián)故障。
- 故障快速恢復(fù)。
- 在可能的情況下,后退并優(yōu)雅地降級。
- 啟用近實時監(jiān)視、警報和操作控制。
背景
為了解決什么問題?
復(fù)雜分布式體系結(jié)構(gòu)中的應(yīng)用程序有幾十個依賴項,每個依賴項在某個時候都不可避免地會失敗。如果主機(jī)應(yīng)用程序沒有從這些外部故障中隔離出來,那么它就有可能與這些外部故障一起宕機(jī)。
例如,對于一個依賴于30個服務(wù)的應(yīng)用程序,其中每個服務(wù)都有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.
現(xiàn)實通常更糟。 即使當(dāng)所有依賴項都運行良好時,即使0.01%的停機(jī)時間對幾十個服務(wù)中的每個服務(wù)的總體影響也相當(dāng)于一個月潛在的停機(jī)時間(如果您不為恢復(fù)而設(shè)計整個系統(tǒng))。
如下面的圖演變:
當(dāng)一切正常時,請求流可以是這樣的:
當(dāng)許多后端系統(tǒng)之一成為潛在,它可以阻止整個用戶請求:
對于高流量,一個后端依賴項成為潛在,可能會導(dǎo)致所有服務(wù)器上的所有資源在幾秒鐘內(nèi)飽和。 應(yīng)用程序中通過網(wǎng)絡(luò)或客戶機(jī)庫到達(dá)可能導(dǎo)致網(wǎng)絡(luò)請求的每個點都是潛在故障的來源。比故障更糟的是,這些應(yīng)用程序還可能導(dǎo)致服務(wù)之間的延遲增加,從而備份隊列、線程和其他系統(tǒng)資源,從而導(dǎo)致系統(tǒng)中出現(xiàn)更多級聯(lián)故障。
工作原理
工作流程圖:
1. 構(gòu)造一個HystrixCommand或HystrixObservableCommand對象
第一步是構(gòu)造一個HystrixCommand或HystrixObservableCommand對象來表示對依賴項的請求。將請求發(fā)出時需要的任何參數(shù)傳遞給構(gòu)造函數(shù)。 如果期望依賴項返回單個響應(yīng),則構(gòu)造一個HystrixCommand對象。例如:
HystrixCommand command = new HystrixCommand(arg1, arg2); 復(fù)制代碼如果期望依賴項返回發(fā)出響應(yīng)的可觀察對象,則構(gòu)造一個HystrixObservableCommand對象。例如:
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2); 復(fù)制代碼2.執(zhí)行命令
有四種方法可以執(zhí)行命令,使用以下四種方法之一的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.是否緩存了響應(yīng)
如果為該命令啟用了請求緩存,并且在緩存中可用對請求的響應(yīng),則此緩存的響應(yīng)將立即以可觀察到的形式返回。
4. 電路打開了嗎?
當(dāng)您執(zhí)行該命令時,Hystrix將與斷路器一起檢查電路是否打開。 如果電路打開(或“跳閘”),那么Hystrix將不執(zhí)行命令,而是將流路由到(8)獲取回退。 如果電路被關(guān)閉,則流繼續(xù)到(5),檢查是否有可用的容量來運行命令。
5.線程池/隊列/信號量是否已滿?
如果與該命令關(guān)聯(lián)的線程池和隊列(或信號量,如果不在線程中運行)已滿,那么Hystrix將不執(zhí)行該命令,而是立即將流路由到(8)獲取回退。
6.HystrixObservableCommand.construct()或HystrixCommand.run ()
這里,Hystrix通過為此目的編寫的方法調(diào)用對依賴項的請求,方法如下:
- 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將響應(yīng)路由到8。獲取回退,如果最終返回值run()或construct()方法沒有取消/中斷,那么它將丟棄該方法。 請注意,沒有辦法強(qiáng)制潛在線程停止工作——Hystrix在JVM上能做的最好的事情就是拋出InterruptedException。如果由Hystrix包裝的工作不尊重interruptedexception,那么Hystrix線程池中的線程將繼續(xù)它的工作,盡管客戶機(jī)已經(jīng)收到了TimeoutException。這種行為可能會使Hystrix線程池飽和,盡管負(fù)載“正確釋放”。大多數(shù)Java HTTP客戶端庫不解釋interruptedexception。因此,請確保正確配置HTTP客戶機(jī)上的連接和讀/寫超時。 如果該命令沒有拋出任何異常并返回一個響應(yīng),那么Hystrix將在執(zhí)行一些日志記錄和度量報告之后返回此響應(yīng)。在run()的情況下,Hystrix返回一個可觀察的對象,該對象發(fā)出單個響應(yīng),然后發(fā)出一個onCompleted通知;在construct()的情況下,Hystrix返回由construct()返回的相同的可觀察值。
7.計算電路健康
Hystrix向斷路器報告成功、失敗、拒絕和超時,斷路器維護(hù)一組滾動計數(shù)器,用于計算統(tǒng)計數(shù)據(jù)。 它使用這些統(tǒng)計數(shù)據(jù)來確定電路應(yīng)該在什么時候“跳閘”,在這一點上,它會短路任何后續(xù)的請求,直到恢復(fù)期結(jié)束,在此期間,它會在第一次檢查某些健康檢查之后再次關(guān)閉電路。
8.回退
Hystrix試圖恢復(fù)你的回滾命令執(zhí)行失敗時:當(dāng)一個異常的構(gòu)造()或()運行(6),當(dāng)命令電路短路,因為打開(4),當(dāng)命令的線程池和隊列或信號能力(5),或者當(dāng)命令已超過其超時長度。 詳情參考官網(wǎng):github.com/Netflix/Hys…
9. 返回成功的響應(yīng)
如果Hystrix命令成功,它將以可觀察到的形式返回響應(yīng)或響應(yīng)給調(diào)用者。根據(jù)您如何調(diào)用上面步驟2中的命令,這個可觀察對象可能在返回給您之前進(jìn)行轉(zhuǎn)換:
- execute() — 以與.queue()相同的方式獲取一個Future,然后在這個Future上調(diào)用get()來獲取可觀察對象發(fā)出的單個值.
- queue() — 將可觀察對象轉(zhuǎn)換為BlockingObservable,以便將其轉(zhuǎn)換為未來,然后返回此未來
- observe() — 立即訂閱可觀察對象,并開始執(zhí)行命令的流;返回一個可觀察對象,當(dāng)您訂閱該對象時,將重播排放和通知
- toObservable() — 返回可觀察值不變;您必須訂閱它,才能真正開始執(zhí)行命令的流程
更多原理可以移步官網(wǎng) github.com/Netflix/Hys…
使用
加入依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>復(fù)制代碼在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();}} 復(fù)制代碼該注解對該方法創(chuàng)建了熔斷器的功能,并指定了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!";}} 復(fù)制代碼在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 復(fù)制代碼@EnableFeignClients啟動
@SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient @EnableFeignClients public class CloudServiceFeginApplication {public static void main(String[] args) {SpringApplication.run(CloudServiceFeginApplication.class, args);}} 復(fù)制代碼**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);}復(fù)制代碼當(dāng)訪問接口有問題時,直接調(diào)用此接口返回。
@Component public class TestServiceHystric implements TestService{@Overridepublic String sayHiFromClientOne(String name) {return "sorry "+name;} }復(fù)制代碼更多使用技巧可參考官網(wǎng): github.com/Netflix/Hys…
總結(jié)
在微服務(wù)架構(gòu)中通常會有多個服務(wù)層調(diào)用,基礎(chǔ)服務(wù)的故障可能會導(dǎo)致級聯(lián)故障,進(jìn)而造成整個系統(tǒng)不可用的情況,這種現(xiàn)象被稱為服務(wù)雪崩效應(yīng)。服務(wù)雪崩效應(yīng)是一種因“服務(wù)提供者”的不可用導(dǎo)致“服務(wù)消費者”的不可用,并將不可用逐漸放大的過程。
熔斷器的原理很簡單,如同電力過載保護(hù)器。它可以實現(xiàn)快速失敗,如果它在一段時間內(nèi)偵測到許多類似的錯誤,會強(qiáng)迫其以后的多個調(diào)用快速失敗,不再訪問遠(yuǎn)程服務(wù)器,從而防止應(yīng)用程序不斷地嘗試執(zhí)行可能會失敗的操作,使得應(yīng)用程序繼續(xù)執(zhí)行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產(chǎn)生。熔斷器也可以使應(yīng)用程序能夠診斷錯誤是否已經(jīng)修正,如果已經(jīng)修正,應(yīng)用程序會再次嘗試調(diào)用操作。
更多優(yōu)質(zhì)文章:
- www.ityouknow.com/springcloud…
- www.fangzhipeng.com/springcloud…
- blog.didispace.com/tags/Hystri…
最后
如果對 Java、大數(shù)據(jù)感興趣請長按二維碼關(guān)注一波,我會努力帶給你們價值。覺得對你哪怕有一丁點幫助的請幫忙點個贊或者轉(zhuǎn)發(fā)哦。
轉(zhuǎn)載于:https://juejin.im/post/5ca96bdce51d452b573e2a1c
總結(jié)
以上是生活随笔為你收集整理的SpringCloud之Hystrix的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模块与包
- 下一篇: 144. Binary Tree Pre