簡介
在分散式環境中,許多服務依賴關係中的一些必然會失敗。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 aFuture
with which you can obtain the single response from the dependencyobserve()
— subscribes to theObservable
that represents the response(s) from the dependency and returns anObservable
that replicates that sourceObservable
toObservable()
— returns anObservable
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 exceptionHystrixObservableCommand.construct()
— returns an Observable that emits the response(s) or sends anonError
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
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
複製程式碼
該註解對該方法建立了熔斷器的功能,並指定了fallbackMethod熔斷方法,熔斷方法直接返回了一個字串,字串為"hi,"+name+",sorry,error!"
@Service
public class TestService {
@Autowired
RestTemplate 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-feign
feign.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{
@Override
public String sayHiFromClientOne(String name) {
return "sorry "+name;
}
}
複製程式碼
更多使用技巧可參考官網: github.com/Netflix/Hys…
總結
在微服務架構中通常會有多個服務層呼叫,基礎服務的故障可能會導致級聯故障,進而造成整個系統不可用的情況,這種現象被稱為服務雪崩效應。服務雪崩效應是一種因“服務提供者”的不可用導致“服務消費者”的不可用,並將不可用逐漸放大的過程。
熔斷器的原理很簡單,如同電力過載保護器。它可以實現快速失敗,如果它在一段時間內偵測到許多類似的錯誤,會強迫其以後的多個呼叫快速失敗,不再訪問遠端伺服器,從而防止應用程式不斷地嘗試執行可能會失敗的操作,使得應用程式繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產生。熔斷器也可以使應用程式能夠診斷錯誤是否已經修正,如果已經修正,應用程式會再次嘗試呼叫操作。
更多優質文章:
最後
如果對 Java、大資料感興趣請長按二維碼關注一波,我會努力帶給你們價值。覺得對你哪怕有一丁點幫助的請幫忙點個贊或者轉發哦。