1 背景
雪崩效應:微服務架構的應用系統通常包含多個服務層。微服務之間通過網絡進行通信,進而支撐 起整個應用系統。每一個服務并不保證一直都可用,當某一個服務的提供者不可用就會導緻服務的調用者不可用,進而将不可用放大的現象。
當出現雪崩效應後,整個服務都可能不可用,要想防止雪崩效應,必須有一個強大的容錯機制。
2 Hystrix簡介
Hystrix是一個用于處理分布式系統的延遲和容錯的開源庫,在分布式系統中,很多依賴不可避免的會調用失敗,比如逾時、異常等,Hystrix能夠保證一個依賴出問題後,不會導緻整體服務失敗,避免聯級錯誤,以提高分布式系統的彈性。
Hystrix三個重要概念:
服務降級(fallback):伺服器忙,請稍後再試,不讓用戶端等待立即傳回一個友好提示。
情況:
1、程式運作異常
2、逾時
3、服務熔斷出發服務降級
4、線程池/信号量打滿也會導緻服務降級
服務熔斷(break):達到最大通路量時,直接拒絕通路,然後調用服務降級傳回友好提示。
服務降級-->進而熔斷-->恢複調用鍊路
服務限流(flowlimit):秒殺高并發操作時,禁止一起通路,排隊請求,有序進行。
3 Hystrix使用
3.1 服務降級(單個方法)
添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
主啟動類添加@EnableHystrix注解,開啟Hystrix功能
@EnableHystrix
public class HystrixMain {
public static void main(String[] args) {
SpringApplication.run(HystrixMain.class,args);
}
}
修改controller,為某一個方法添加容錯功能
@GetMapping("/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "timeOutFallBackMethod",commandProperties = {
//設定這個線程的逾時時間是3s,3s内是正常的業務邏輯,超過3s調用fallbackMethod指定的方法進行處理
@HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public String test_TimeOut(@PathVariable("id") Integer id){
try{
TimeUnit.SECONDS.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
return hystrixService.test_TimeOut(id);
}
public String timeOutFallBackMethod(@PathVariable("id") Integer id){
return "系統逾時";
}
3.2 服務降級(全局方法)
有時候為每個方法提供容錯功能挺麻煩,Hystrix提供一個可以設定全局fallback的功能。
給controller添加注解@DefaultProperties,并設定defaultFallback屬性,此屬性值為全局fallback方法名
@DefaultProperties(defaultFallback = "global_FallbackMethod")
public class HystrixController {
//省略...
/**
* 全局 fallback 方法
*
*/
public String global_FallbackMethod(){
return "全局fallback方法";
}
}
3.3 服務降級(Feign實作)
在SpringCloud中,Feign實作fallback更加簡單,因為Spring Cloud預設已為Feign整合了 Hystrix。
修改application.yml為Feign開啟Hystrix
feign:
hystrix:
enabled: true
添加一個類實作Feign接口,專門處理fallback方法
@Component
public class FallbackService implements HystrixService {
@Override
public String test_TimeOut(Integer id) {
return "Fegin fall back method";
}
}
修改Fegin接口
@Component
//value值為服務提供者的服務名 fallback值為實作此接口的用于提供fallback方法的類
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT" ,fallback = FallbackService.class)
public interface HystrixService {
@GetMapping("/payment/hystrix/timeout/{id}")
public String test_TimeOut(@PathVariable("id") Integer id);
}
3.4 服務熔斷
當某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速傳回”錯誤”的響應資訊。在SpringCloud架構機制通過Hystrix實作,Hystrix會監控微服務見調用的狀況,當失敗的調用到一個門檻值,預設是5秒内20次調用失敗就會啟動熔斷機制,當檢測到該節點微服務響應正常後恢複調用鍊路。
controller添加一個方法,用于測試熔斷機制
//服務熔斷
@GetMapping("/circuit/{id}")
public String circuitBreaker(@PathVariable("id") Integer id){
String result = circuitService.circuitBreaker(id);
log.info("****result:"+result);
return result;
}
通過通路這個路徑,調用service對應的方法,如果滿足條件即可觸發熔斷
//服務熔斷
@HystrixCommand(fallbackMethod = "circuitBreaker_fallback",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(@PathVariable("id") Integer id){
if(id < 0){
throw new RuntimeException("******id 不能為負數");
}
String serialNumber = IdUtil.simpleUUID(); //UUID.randomUUID();
return Thread.currentThread().getName()+"\t"+"調用成功,流水号:"+serialNumber;
}
public String circuitBreaker_fallback(@PathVariable("id") Integer id){
return "id 不能負數,請稍後再試,o(╥﹏╥)o id:"+id;
}
解釋:可以看到@HystrixCommand注解中設定了幾個值,這說明在一個時間視窗期内,滿足規定的請求次數後并且達到失敗率就會觸發熔斷機制,打開斷路器,調用fallback方法。
requestVolumeThreshold(請求總數門檻值):在快照視窗期内,必須滿足請求總數門檻值才有資格熔斷。預設是20,也就是說在10秒内該Hystrix指令調用次數不足20次,即使所有的請求都失敗,斷路器也不會打開。
sleepWindowInMilliseconds(快照時間視窗):斷路器确定是否打開需要統計一些請求和錯誤資料,而統計的時間範圍就是快照時間視窗,預設為10秒。
errorThresholdPercentage(錯誤百分比門檻值):當請求總數在快照時間視窗内超過了門檻值,假設30次,其中有15次發生了錯誤,有50%的錯誤百分比,在預設設定50%的錯誤百分比門檻值情況下,斷路器就會打開。
在這個例子中,在10秒的視窗期内,10次請求中有6次id為負值的請求就會顯示fallback方法傳回的内容。當觸發熔斷機制後,即使id為正值也會調用fallback方法,不會進行請求的轉發。一段時間後(休眠時間視窗期,預設是5秒),這時候斷路器是半開狀态,讓一個請求進行轉發,如果成功斷路器關閉,服務恢複正常;失敗則繼續開啟。
注:當斷路器打開後将不會調用主邏輯,直接調用fallback方法。通過斷路器,實作了自動發現錯誤并從主邏輯切換到降級邏輯,減少響應延遲的效果。關于主邏輯的恢複,當斷路器打開對主邏輯熔斷後,Hystrix會啟動一個休眠視窗期,在這個時間内降級邏輯臨時成為主邏輯。當休眠時間視窗期到,斷路器進入半開狀态,釋放一次請求到主邏輯上。如果這次請求正常傳回,斷路器将關閉主邏輯恢複;如果這次請求依然出錯,斷路器繼續進入打開狀态,休眠時間視窗重新計時。
寫在最後,關于服務熔斷參考了相關教程後不知道自己了解的是否正确,如果有誤歡迎在評論區指出,謝謝。
參考連結:https://b23.tv/Ih97SA