Hystrix 是什麼?
Hystrix 是一個用於處理分散式系統的延遲和容錯的開源庫,在分散式系統裡,許多依賴不可避免的會呼叫失敗,比如超時、異常等,Hystrix 能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分散式系統的彈性。
「斷路器」本身是一種開關裝置,當某個服務單元發生故障之後,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者丟擲呼叫方無法處理的異常,這樣就保證了服務呼叫方的執行緒不會被長時間、不必要地佔用,從而避免了故障在分散式系統中的蔓延,乃至雪崩。
Hystrix 的幾個概念
服務降級
不讓客戶端等待,並立即返回一個友好的提示(伺服器忙,請稍後再試)
? 哪些情況會發生服務降級:
- 程式執行異常
- 超時
- 服務熔斷引起服務降級
- 執行緒池/訊號量打滿也會導致服務降級
服務熔斷
類似保險絲,電流過大時,直接熔斷斷電。
熔斷機制是應對雪崩效應的一種微服務鏈路保護機制,當扇出鏈路的某個微服務出錯不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的呼叫,快速返回錯誤的響應資訊,當檢測到該節點微服務呼叫響應正常後,恢復呼叫鏈路。
服務降級 → 服務熔斷 → 恢復呼叫鏈路
服務限流
對於高併發的操作,限制單次訪問數量
服務降級的用法與分析
超時導致伺服器變慢:超時不再等待; 出錯(當機或程式執行出錯):要有備選方案
- 服務提供者超時了,呼叫者不能一直卡死等待,必須要服務降級
- 服務提供者當機了,呼叫者不能一直卡死等待,必須要服務降級
- 服務提供者沒問題,呼叫者自己出現故障或者有自我要求(自己的等待時間必須小於服務提供者)
給服務提供方設定服務降級
1、在需要服務降級的方法上標註註解,fallbackMethod 代表回退方法,需要自己定義,@HystrixProperty
中設定的是該方法的超時時間,如果超過該事件則自動降級
當執行超時或服務內部出錯都會呼叫回退方法
@HystrixCommand(
fallbackMethod = "timeoutHandler",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
public String timeout(Long id) {
int time = 3000;
try {
TimeUnit.MILLISECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
//模擬異常
//int i = 10 / 0;
return "執行緒:" + Thread.currentThread().getName();
}
2、在啟動類上新增註解,開啟降級
@EnableCircuitBreaker
給服務消費方設定服務降級
1、新增配置
# 在feign中開啟hystrix
feign:
hystrix:
enabled: true
2、和服務提供方一樣,照葫蘆畫瓢
@HystrixCommand(
fallbackMethod = "timeoutHandler",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
public String timeout(@PathVariable("id") Long id) {
int i = 1/0;
return hystrixService.timeout(id);
}
3、在啟動類上新增註解
@EnableHystrix
問題
以上配置方式存在的問題:
- 每個業務方法對應一個回退方法,程式碼膨脹
- 每個業務方法上都配置相同的處理,程式碼冗餘
? 解決方式1:在類上配置一個全域性回退方法,相當於是一個通用處理,當此回退方法能滿足你的需求,就無需在方法上指定其它回退方法,如果需要使用特定的處理方法可以再在業務方法上定義
@DefaultProperties(defaultFallback = "globalFallbackMethod")
? 解決方式2:但此時處理程式碼和依然和業務程式碼混合在一起,我們還可以使用另一種方式:編寫一個類實現 Feign 的呼叫介面,並重寫其方法作為回退方法,然後在 @FeignClient
註解上新增 fallback
屬性,值為前面的類。
服務熔斷的用法與分析
在SpringCloud中,熔斷機制通過 Hystrix 實現。Hystrix 監控微服務間的呼叫狀況,當失敗的呼叫到一定閾值,預設 5 秒內 20 次呼叫失敗就會啟動熔斷機制。熔斷機制的註解是 @HystrixCommand
@HystrixCommand(
fallbackMethod = "paymentCircuitBreakerFallback",
commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //是否開啟斷路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //請求次數
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //時間視窗期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") //失敗率達到多少後跳閘
})
public String circuitBreaker(Long id) {
if (id < 0) {
throw new RuntimeException("id 不能為負數");
}
return Thread.currentThread().getName() + "\t" + "呼叫成功,流水號:" + IdUtil.simpleUUID();
}
public String circuitBreakerFallback(Long id) {
return "id 不能為負數,你的id = " + id;
}
@HystrixProperty
中的配置可以參考 com.netflix.hystrix.HystrixCommandProperties
類
詳見官方文件:https://github.com/Netflix/Hystrix/wiki/Configuration
也有雷鋒同志做了翻譯:https://www.jianshu.com/p/39763a0bd9b8
? 熔斷型別
- 熔斷開啟:請求不再呼叫當前服務,內部設定時鐘一般為MTTR(平均故障處理時間),當開啟時長達到所設時鐘則進入半熔斷狀態。
- 熔斷半開:部分請求根據規則呼叫服務,如果請求成功且符合規則,則關閉熔斷。
- 熔斷關閉:不會對服務進行熔斷。
? 斷路器什麼時候起作用?
根據上面配置的引數,有三個重要的影響斷路器的引數
- 快照時間窗:迴路被開啟、拒絕請求到再嘗試請求並決定迴路是否繼續開啟的時間範圍,預設是 5 秒
- 請求總數閾值:在一個滾動視窗中,開啟斷路器需要的最少請求數,預設是 20 次(就算前 19 次都失敗了,斷路器也不會被開啟)
- 錯誤百分比閾值:錯誤請求數在總請求數所佔的比例,達到設定值才會觸發,預設是 50%
? 斷路器開啟或關閉的條件
- 當請求達到一定閾值時(預設 20 次)
- 當錯誤率達到一定閾值時(預設 50%)
- 達到以上條件斷路器開啟
- 當開啟的時候,所有請求都不會轉發
- 當斷路器開啟一段時間後(預設 5 秒)進入半開狀態,並讓其中一個請求進行轉發,如果成功斷路器關閉,如果失敗繼續開啟,重複第 4 和 5 步
? 斷路器開啟之後會發生什麼?
- 再有請求呼叫時,不再呼叫主邏輯,而是呼叫降級 fallback。
- 斷路器開啟之後,Hytrix 會啟動一個休眠時間窗,在此時間內,fallback 會臨時稱為主邏輯,當休眠期到了之後,斷路器進入半開狀態,釋放一個請求到原來的主邏輯上,如果請求成功返回,則斷路器關閉,如果請求失敗,則繼續進入開啟狀態,休眠時間窗重新計時。
Hystrix服務熔斷的工作流程
詳見官方文件:https://github.com/Netflix/Hystrix/wiki/How-it-Works
Hystrix DashBoard 上手
搭建
1、新建一個專案,匯入 maven 依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、新增配置
server:
port: 9001
3、開啟 Hystrix DashBoard
@SpringBootApplication
@EnableHystrixDashboard
public class ConsumerHystrixDashBoard9001 {
public static void main(String[] args){
SpringApplication.run(ConsumerHystrixDashBoard9001.class, args);
}
}
4、瀏覽器輸入 http://localhost:9001/hystrix
,出現以下介面即啟動成功
使用
注意:想要被 Hystrix DashBoard 監控的服務必須匯入此依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在被監控服務的主啟動類裡新增如下程式碼,否則某些舊版本可能報錯 Unable to connect to Command Metric Stream.
/**
* 此配置是為了服務監控而配置,與服務容錯本身無關,SpringCloud升級後的坑
* ServletRegistrationBean因為springboot的預設路徑不是"/hystrix.stream",
* 只要在自己的專案裡配置上下面的servlet就可以了
*/
@Bean
public ServletRegistrationBean getServlet(){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
在 Hystrix DashBoard 頁面輸入基本資訊,進入儀表盤介面
大致情況如下所示
操作介面分析:
程式碼地址:https://github.com/songjilong/springcloud-hoxton-learning