1. 程式人生 > >五. SpringCloud服務降級和熔斷

五. SpringCloud服務降級和熔斷

#### 1. Hystrix斷路器概述 ##### 1.1 分散式系統面臨的問題 複雜分散式體系結構中的應用程式有數十個依賴關係,每個依賴關係在某些時候將不可避免地失敗。這就造成有可能會發生**服務雪崩**。那麼什麼是服務雪崩呢? 多個微服務之間呼叫的時候,假設微服務A呼叫微服務B和微服務C,微服務B和微服務C又呼叫其他的微服務,這就是所謂的“**扇出**”(像一把開啟的摺扇)。如果扇出的鏈路上某個微服務的呼叫響應時間過長或者不可用,對微服務A的呼叫就會佔用越來越多的系統資源,進而引起系統崩潰,這就是所謂的”**雪崩效應**“。也就是系統的 **高可用** 受到了破壞。 對於高流量的應用來說,單一的後端依賴可能會導致所有伺服器上的所有資源在幾秒內飽和。比失敗更糟的是,這些應用程式還可能導致 服務之間的延遲增加,備份佇列,執行緒和其他系統資源緊張,導致整個系統傳送更過的級聯故障。這些都表示需要對故障和延遲進行隔離和管理,以便 單個依賴關係的失敗,不能取消整個應用程式或系統。 所以,通常當發現一個模組下的某個例項失敗後,這時候這個模組依然還會接受流量,然後這個有問題的模組還呼叫了其他的模組,這樣就會發生級聯故障,或者叫做雪崩。而面對這種糟糕的問題,我們就應該採取 **服務降級、服務熔斷** 等方式來解決。 ##### 1.2 Hystrix是什麼 Hystrix是一個用於處理分散式系統的 `延遲` 和 `容錯` 的開源庫,在分散式系統裡,許多依賴不可避免的會呼叫失敗,比如超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整個服務失敗,避免級聯故障,以提高分散式系統的彈性。 “斷路器”本身是一種開關裝置,當某個服務單元發生故障之後,通過斷路器的故障監控(類似於物理的熔斷保險絲),向呼叫方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者丟擲呼叫方無法處理的異常,這樣就保證了服務呼叫方的執行緒不會被長時間、不必要的佔用,從而避免了故障在分散式系統中的蔓延,乃至雪崩。 ##### 1.3 Hystrix作用 主要有服務降級、服務熔斷、接近實時的監控、限流、隔離等等,其[官方文件](https://github.com/Netflix/Hystrix/wiki/How-To-Use)參考。當然Hystrix現在已經停更了,雖然有一些替代品,但是學習Hystrix及其裡面的思想還是非常重要的! ##### 1.4 Hystrix重要概念 **` 服務降級(Fall Back)`** 假設微服務A要呼叫的服務B不可用了,需要服務B提供一個兜底的解決方法,而不是讓服務A在那裡傻等,耗死。不讓客戶端等待並立刻返回一個友好提示,比如像客戶端提示伺服器忙,請稍後再試等。哪些情況會觸發服務降級呢?比如 `程式執行異常`、`超時`、`服務熔斷觸發服務降級`、`執行緒池/訊號量打滿`也會導致服務降級。 **`服務熔斷(Break)`** 服務熔斷就相當於物理上的**熔斷保險絲**。類比保險絲達到最大服務訪問後,直接拒絕訪問,拉閘斷電,然後呼叫服務降級的方法並返回友好提示。 **`服務限流(Flow Limit)` ** 秒殺高併發等操作,嚴禁一窩蜂的過來擁擠,大家排隊,一秒鐘N個,有序進行。 #### 2. Hystrix案例 ##### 2.1 服務提供者8003模組 **建Module** cloud-provider-hystrix-payment8003 **pom.xml** ```xml org.springframework.cloud spring-cloud-starter-netflix-hystrix ``` **yml配置檔案 / 主啟動類** ```yml server: port: 8003 spring: application: name: cloud-provider-hystrix-payment eureka: client: register-with-eureka: true fetchRegistry: true service-url: # 單機版 defaultZone: http://localhost:7001/eureka # 入駐的服務註冊中心地址 ``` ```java @SpringBootApplication @EnableEurekaClient public class PaymentHystrixMain8003 { public static void main(String[] args) { SpringApplication.run(PaymentHystrixMain8003.class,args); } } ``` **業務類** - service ```java @Service public class PaymentService { /**能夠正常訪問的方法*/ public String paymentInfo_OK(Integer id) { return "執行緒池: " + Thread.currentThread().getName() + " paymentInfo_OK,id: " + id + "\t" + "哈~"; } /**模擬出錯的方法*/ public String paymentInfo_FAIL(Integer id) { int timeNumber = 3; //暫停幾秒鐘執行緒,程式本身沒有錯誤,就是模擬超時 try { TimeUnit.SECONDS.sleep(timeNumber); }catch (InterruptedException e) { e.printStackTrace(); } return "執行緒池: " + Thread.currentThread().getName() + " paymentInfo_FAIL,id: " + id + "\t" + "哈~ " + "耗時" + timeNumber + "s"; } } ``` - controller ```java @RestController @Slf4j @RequestMapping("/payment/hystrix") public class PaymentController { @Resource private PaymentService paymentService; @Value("$server.port") private String serverPort; @GetMapping("ok/{id}") public String paymentInfo_OK(@PathVariable("id")Integer id) { String result = paymentService.paymentInfo_OK(id); log.info("===>
result: " + result); return result; } @GetMapping("timeout/{id}") public String paymentInfo_TimeOut(@PathVariable("id")Integer id) { String result = paymentService.paymentInfo_FAIL(id); log.info("===> result: " + result); return result; } } ``` 也就是說**cloud-provider-hystrix-payment**服務提供了兩個方法,**paymentInfo_OK** 方法可以很快訪問,**paymentInfo_TimeOut** 方法我們模擬了一個複雜的業物邏輯,通過執行緒休眠的方式使其模擬一個需要執行3秒的服務方法。 在啟動了註冊中心和8003服務後,我們對服務的 **paymentInfo_OK**(下面用**OK**代替) 和 **paymentInfo_TimeOut**(下面用**TO**代替)分別進行訪問,我們發現http://localhost:8003/payment/hystrix/ok/1 可以很快的訪問,而http://localhost:8003/payment/hystrix/timeout/1 每次訪問大約需要3秒的時間。 >
上述為根基平臺,開始演示:正確 => 錯誤 => 降級熔斷 => 正確 ##### 2.2 8003高併發測試 **服務提供方自測壓力測試:** 需要3秒的複雜業務邏輯 **TO** 訪問時,需要時間很少的 **OK** 是完全可以正常訪問的,但是在高併發的情況下,也就是說 **TO** 有很多訪問量的時候,**OK** 還能夠這麼正常的訪問嗎?下面我們用 Jmeter 進行高併發壓力測試,用20000個請求都去訪問 **TO** 服務。 在 Jmeter 中新建一個**執行緒組**:測試Hystrix用來模擬高併發訪問 **TO** 服務,執行緒組配置引數如下: 然後我們用該執行緒組傳送HTTP請求給 **TO** 服務,建立如下的HTTP請求進行壓力測試:
我們觀察8001服務的後端控制檯,可以看到對 **TO** 服務進行了大量的訪問。而此時我們再去訪問 **OK** 服務時什麼樣的呢?=> 可以看到,**OK** 服務無法像之前一樣很快能夠得到訪問,這裡我們模擬的是20000的訪問量(沒敢模擬數字太大的訪問量,怕把系統直接搞死),實際中可能會有遠大於20000的訪問量,當訪問量更多的時候,甚至可能卡死服務,原因就是 Tomcat的預設的工作執行緒數被打滿了,沒有多餘的執行緒來分解壓力和處理。 而剛才做的壓力測試還只是服務提供方8001自己實現的測試,如果此時是外部的服務消費方80來訪問該服務,那麼服務消費方只能夠進行乾等,消費方顯然會對這樣的等待時間不滿意,服務提供方很有可能直接被拖死。我們發現8001自測都會出現問題,那如果我們再用服務消費方測試呢? ##### 2.3 服務消費者80模組進行壓力測試 新建一個Module:cloud-consumer-feign-hystrix-order80作為服務消費方,服務消費方利用feign訪問提供方的服務,編寫對應的service介面如下: ```java @Component @FeignClient("CLOUD-PROVIDER-HYSTRIX-PAYMENT") public interface PaymentHystrixService { @GetMapping("/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id); @GetMapping("/payment/hystrix/timeout/{id}") public String paymentInfo_FAIL(@PathVariable("id") Integer id); } ``` 然後編寫其Controller: ```java @RestController @Slf4j public class OrderHystrixController { @Resource private PaymentHystrixService paymentHystrixService; @GetMapping("/consumer/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id) { String result = paymentHystrixService.paymentInfo_OK(id); return result; } @GetMapping("/consumer/payment/hystrix/timeout/{id}") public String paymentInfo_TimeOut(@PathVariable("id") Integer id) { String result = paymentHystrixService.paymentInfo_FAIL(id); return result; } } ``` 將80服務啟動,用http://localhost/consumer/payment/hystrix/ok/1 對服務提供方的 **OK** 服務進行訪問,再進行壓力測試,和之前一樣,無法迅速訪問該服務,如果壓力測試中的執行緒數更多的時候,很可能會造成超時錯誤,出現以下錯誤提示: 故障原因:8003同一層次的其他介面服務被困死,因為Tomcat執行緒池裡面的工作執行緒已經被擠佔完畢,80此時再呼叫8003,必然導致客戶端訪問響應緩慢。正是因為出現了這種現象,所以我們才需要 服務降級、容錯、服務限流 等技術。 ##### 2.4 發現問題 要解決的問題: - 超時導致伺服器變慢(轉圈) => 超時不再等待 - 出錯(宕機或程式執行出錯) => 出錯要有兜底 解決方案: - 對方服務(8003)超時了,呼叫者(80)不能一直卡死等待,必須有服務降級 - 對方服務(8003)宕機了,呼叫者(80)不能一直卡死等待,必須有服務降級 - 對方服務(8003)OK,呼叫者(80)自己出故障或有自我要求(自己的等待時間小於服務提供者),自己處理降級 #### 3. Hystrix服務降級Fall Back ##### 3.1 服務端服務提供方的服務降級 降級的配置用 `@HystrixCommand `註解,在服務提供方自身找問題,設定自身呼叫超時時間的峰值,在峰值內可以正常執行,超過了峰值需要有兜底的方法處理,用作服務降級。 首先在服務提供方的業務類上啟用 `@HystrixCommand`實現報異常後如何處理,也就是一旦呼叫服務方法失敗並丟擲了錯誤資訊後,會自動呼叫` @HystrixCommand` 標註好的fallbackMethod服務降級方法。在服務提供方的service中我們修改 TO 服務: ```java @Service public class PaymentService { /**能夠正常訪問的方法*/ public String paymentInfo_OK(Integer id) { return "執行緒池: " + Thread.currentThread().getName() + " paymentInfo_OK,id: " + id + "\t" + "哈~"; } /**模擬出錯的方法*/ @HystrixCommand(fallbackMethod = "paymentInfo_FailHandler", commandProperties = { @HystrixProperty( name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") }) public String paymentInfo_FAIL(Integer id) { //int age = 10/0; //模擬異常,也會兜底 int timeNumber = 5; //暫停幾秒鐘執行緒,程式本身沒有錯誤,就是模擬超時 try { TimeUnit.SECONDS.sleep(timeNumber); }catch (InterruptedException e) { e.printStackTrace(); } return "執行緒池: " + Thread.currentThread().getName() + " paymentInfo_FAIL,id: " + id + "\t" + "哈~ " + "耗時" + timeNumber + "s"; } /** 定製服務降級方法*/ public String paymentInfo_FailHandler(Integer id) { return "系統忙,請稍後再試"; } } ``` 然後在主啟動類上新增 `@EnableCircuitBreaker` 註解對熔斷器進行啟用,TO服務的訪問時間5秒,而我們用Hystrix配置的時間峰值為3秒,也就是當**服務超時或服務出錯**時,會訪問我們設定的fallbackMethod服務降級方法,再次訪問TO服務,我們發現其執行的方法確實為服務降級方法: > 注意:我們自己配置過的熱部署方式對Java程式碼的改動明顯,但對 @HystrixCommand內屬性的修改建議重啟微服務(有時不能及時生效) ##### 3.2 客戶端服務消費方的服務降級 既然服務的提供方可以進行降級保護,那麼服務的消費方,也可以更好的保護自己,也可以對自己進行降級保護,也就是說Hystrix服務降級既可以放在服務端(服務提供方),也可以放在客戶端(服務消費方),但是!通常是用客戶端做服務降級,下面在服務消費方即客戶端配置自己的服務降級保護,修改80消費方的配置檔案,新增如下配置已使其支援Hystrix: ```yml feign: hystrix: enabled: true ``` 在80消費方的主啟動類上新增 `@EnableHystrix` 啟用Hystrix服務。然後在80的Controller中同樣加入`@HystrixCommand`註解已實現服務降級: ```java @RestController @Slf4j public class OrderHystrixController { @Resource private PaymentHystrixService paymentHystrixService; @GetMapping("/consumer/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id) { String result = paymentHystrixService.paymentInfo_OK(id); return result; } @GetMapping("/consumer/payment/hystrix/timeout/{id}") @HystrixCommand(fallbackMethod = "paymentInfo_FailHandler", commandProperties = { @HystrixProperty( name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500") }) public String paymentInfo_TimeOut(@PathVariable("id") Integer id) { String result = paymentHystrixService.paymentInfo_FAIL(id); return result; } /** 定製服務降級方法*/ public String paymentInfo_FailHandler(Integer id) { return "我是消費者80,系統忙,請稍後再試"; } } ``` 也就是說如果消費方訪問服務提供方的時間超過了1.5秒,那麼就會訪問自己的降級服務方法。 ##### 3.3 統一全域性服務降級方法 而當前的這種處理方式是有問題的,也就是**每個業務方法都對應了一個服務降級方法,這會導致程式碼膨脹**,所以我們應該定義一個統一的服務降級方法,統一的方法和自定義的方法分開。而且我們**將服務降級方法和業務邏輯混合在了一起,這會導致程式碼混亂,業務邏輯不清晰。** 對於第一個問題,我們可以用feign介面中的 `@DefaultProperties(defaultFallback = "") `註解來配置全域性的服務降級方法,也就是說 自己配置過`@HystrixCommand(fallbackMethod = "")`fallbackMethod方法的採用自己配置的服務降級方法,而沒有配置過的就採用`@DefaultProperties(defaultFallback = "")` 配置的全域性的服務降級方法。這樣的話通用的服務降級方法和獨享的服務降級方法分開,避免了程式碼膨脹,合理減少了程式碼量,修改服務消費方80的Controller入下: ```java @RestController @Slf4j //沒有特別指明就用這個統一的 @DefaultProperties(defaultFallback = "payment_Global_FailHandler") public class OrderHystrixController { @Resource private PaymentHystrixService paymentHystrixService; @GetMapping("/consumer/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id) { String result = paymentHystrixService.paymentInfo_OK(id); return result; } @GetMapping("/consumer/payment/hystrix/timeout/{id}") //特別指明使用哪一個兜底方法 // @HystrixCommand(fallbackMethod = "paymentInfo_FailHandler", // commandProperties = { // @HystrixProperty( // name = "execution.isolation.thread.timeoutInMilliseconds", // value = "1500") // }) @HystrixCommand //沒有具體指明就使用全域性的 public String paymentInfo_TimeOut(@PathVariable("id") Integer id) { String result = paymentHystrixService.paymentInfo_FAIL(id); return result; } /** 定製服務降級方法*/ public String paymentInfo_FailHandler(Integer id) { return "我是消費者80,系統忙,請稍後再試"; } /** * 全域性服務降級方法 * @return */ public String payment_Global_FailHandler() { return "全域性異常處理資訊"; } } ``` 這裡需要注意的是,**無論是否配置了定製服務降級方法,都要在其服務上加入註解 `@HystrixCommand`**, 否則服務降級和該服務沒關係。 而對於第二個問題, 我們可以為Feign客戶端定義的介面新增一個服務降級處理的實現類即可實現解耦,我們的80客戶端已經有了PaymentHystrixService介面,我們新建一個類`PaymentFallbackService`實現該介面,並重寫介面中的方法,為接口裡的方法進行異常處理,並且我們在`PaymentHystrixService`@FeignClient註解中宣告其服務降級方法所在的類: ```java @Service //當出現錯誤是到PaymentFallbackService類中找服務降級方法 @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallbackService.class) public interface PaymentHystrixService { @GetMapping("/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id); @GetMapping("/payment/hystrix/timeout/{id}") public String paymentInfo_FAIL(@PathVariable("id") Integer id); } ``` ```java @Service public class PaymentFallbackService implements PaymentHystrixService{ @Override public String paymentInfo_OK(Integer id) { return "PaymentHystrixService paymentInfo_OK出現異常"; } @Override public String paymentInfo_FAIL(Integer id) { return "PaymentHystrixService paymentInfo_Fail出現異常"; } } ``` 然後我們將Controller中耦合的程式碼都取消: ```java @RestController @Slf4j public class OrderHystrixController { @Resource private PaymentHystrixService paymentHystrixService; @GetMapping("/consumer/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id) { String result = paymentHystrixService.paymentInfo_OK(id); return result; } @GetMapping("/consumer/payment/hystrix/timeout/{id}") public String paymentInfo_TimeOut(@PathVariable("id") Integer id) { String result = paymentHystrixService.paymentInfo_FAIL(id); return result; } } ``` 然後我們關閉8001服務提供方服務,模擬伺服器宕機,在服務訪問出現錯誤時,訪問了我們配置的PaymentFallbackService類中的服務降級方法,這樣就實現了程式碼的解耦,使業務邏輯不再混亂。 #### 4. Hystrix服務熔斷Break ##### 4.1 熔斷機制概述 > 服務的降級 => 進而熔斷 => 恢復呼叫鏈路 熔斷機制是應對雪崩效應的一種微服務鏈路保護機制,當扇出鏈路的某個微服務出錯不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的呼叫,也就是說服務熔斷會導致服務降級,快速返回錯誤的響應資訊。當檢測到該節點微服務呼叫響應正常後,恢復呼叫鏈路。也就是說,服務熔斷在服務好了之後會重新允許訪問服務。 在SpringCloud框架中,熔斷機制通過Hystrix實現。Hystrix會監控微服務間的呼叫狀況,**當失敗的呼叫到一定閾值,預設是5秒內20次呼叫失敗,就會啟動熔斷機制。**熔斷機制的註解是 `@HystrixCommand`。關於熔斷機制,具體可以參考論文[CircuitBreaker](https://martinfowler.com/bliki/CircuitBreaker.html)。 ##### 4.2 例項 **在8003服務提供方的Service中新增如下程式碼:** ```java /** * 服務熔斷 * fallbackMethod 服務降級方法 * circuitBreaker.enabled 是否開啟斷路器 * circuitBreaker.requestVolumeThreshold 請求次數 * circuitBreaker.sleepWindowInMilliseconds 時間視窗期 * circuitBreaker.errorThresholdPercentage 失敗率達到多少後跳閘 * * 以下配置意思是在10秒時間內請求10次,如果有6次是失敗的,就觸發熔斷器 * * 註解@HystrixProperty中的屬性在com.netflix.hystrix.HystrixCommandProperties類中檢視 */ @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_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 paymentCircuitBreaker(@PathVariable("id") Integer id) { if (id < 0) { throw new RuntimeException("===> id 不能為負數"); } //hutool工具類的使用,等價於UUID.randomUUID().toString() String serialNumber = IdUtil.simpleUUID(); return Thread.currentThread().getName() + " 呼叫成功,流水號: " + serialNumber; } /** * 服務熔斷觸發的服務降級方法 * @param id * @return */ public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) { return "id 不能為負數,請稍後再試。id:" + id; } ``` 在 `@HystrixCommand` 註解中配置熔斷機制的引數,配置的引數含義如下: | 屬性名 | 含義 | 預設值 | | ---------------------------------------- | -------------------- | ------ | | circuitBreaker.enabled | 是否開啟斷路器 | true | | circuitBreaker.requestVolumeThreshold | 請求次數 | 20次 | | circuitBreaker.sleepWindowInMilliseconds | 時間視窗期 | 5000ms | | circuitBreaker.errorThresholdPercentage | 失敗率達到多少後跳閘 | 50% | 這些屬性名的具體含義以及其預設值可以在 `com.netflix.hystrix.HystrixCommandProperties` 類中進行檢視。而我們在service中配置的意思就是**在10秒時間內請求10次,如果有6次是失敗的,就觸發熔斷器**。 **在Controller中新增該服務:** ```java @GetMapping("circuit/{id}") public String paymentCircuitBreaker(@PathVariable("id") Long id) { String result = paymentService.paymentCircuitBreaker(id); log.info("====> result:" + result); return result; } ``` ##### 4.3 測試 根據我們的業物邏輯,也就是當我們的id為整數時,服務可以正常訪問,而當id為負數時,訪問服務出錯。我們先訪問 http://localhost:8003/payment/hystrix/circuit/11 代表正確的服務請求,可以發現一切正常! 然後我們進行大量的錯誤訪問,強行觸發服務熔斷,然後在進行正確的訪問。我們發現在進行超出我們閾值的錯誤訪問後,觸發了服務熔斷,即使再進行正確的訪問也無法進行,但是一定時間後,正確的服務訪問又可以順利進行,這就是服務熔斷的整體過程:在觸發了服務熔斷後,先進行服務的降級,再**逐漸恢復呼叫鏈路**。 ##### 4.4 總結 結合[官網](https://github.com/Netflix/Hystrix/wiki/How-it-Works)中對熔斷機制的描述,其熔斷過程可以如下描述: **熔斷器開啟和關閉的精確方式如下:** - 假設電路上的訪問達到某個閾值(`HystrixCommandProperties.circuitBreakerRequestVolumeThreshold()`)… - 並假設誤差百分比超過閾值誤差百分比(`HystrixCommandProperties.circuitBreakerErrorThresholdPercentage()`)… - 然後,斷路器從`CLOSED`為`OPEN`,觸發熔斷機制。 - 當它斷開時,它會使針對該斷路器的所有請求短路。 - 經過一段時間(`HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds()`)後,下一個單個請求被允許通過(這是`HALF-OPEN`狀態)。如果請求失敗,斷路器將`OPEN`在睡眠視窗期間返回到該狀態。如果請求成功則斷路器切換到`CLOSED`,並且第一條中的邏輯再次接管。 **也就是在熔斷機制中,熔斷器分為三個狀態:** | 狀態 | 說明 | | ------------------- | ------------------------------------------------------------ | | 熔斷器開啟OPEN | 請求不再進行呼叫當前服務,內部設定時鐘一般為MTTR(平均故障處理時間),當開啟時長達到所設時鐘則進入半熔斷狀態(HALF-OPEN)。 | | 熔斷器關閉CLOSED | 熔斷關閉不會對服務進行熔斷。 | | 熔斷器半開HALF-OPEN | 部分請求根據規則呼叫當前服務,如果請求成功且符合規則則認為當前服務恢復正常,關閉熔斷。 | **下面是官網上的熔斷器流程圖:** **那麼熔斷器在什麼情況下開始起作用呢?** 涉及到熔斷器的三個重要引數:快照時間窗,請求總數閾值,錯誤百分比閾值 - 快照時間視窗期`circuitBreaker.sleepWindowInMilliseconds`:熔斷器是否開啟需要統計一些請求和錯誤資料,而統計的時間範圍就是快找時間窗,預設為最近的10秒; - 請求總數閾值`circuitBreaker.requestVolumeThreshold`:在快照時間窗內,必須滿足請求總數閾值才有資格觸發熔斷,預設為20次,這意味著在快照時間窗規定的時間內,如果該Hystrix命令的呼叫次數不足20次,即使所有請求都超時或其他原因失敗,熔斷器都不會開啟; - 錯誤百分比閾值`circuitBreaker.errorThresholdPercentage`:當請求總數在快照時間窗內超過了閾值,且在這些呼叫中,超過錯誤百分比閾值比例的錯誤呼叫,熔斷器就會開啟。 **在熔斷器開啟後** 熔斷器開啟後再有請求呼叫的時候,將不會呼叫主邏輯,而是直接呼叫服務降級的方法,實現了自動發現錯誤並將降級邏輯切換為主邏輯,減少響應延遲的效果。 原來的主邏輯如何恢復呢? => 當熔斷器開啟後,對主邏輯進行熔斷之後,Hystrix會啟動一個 **休眠時間窗** , 在這個時間窗內,降級邏輯是臨時的主邏輯,當休眠時間窗到期,熔斷器會進入半開狀態,釋放一次請求到原來的主邏輯上,如果此次請求能夠正常訪問,則熔斷器會進入閉合狀態,從而恢復主邏輯,如果註冊請求依然有問題,則熔斷器繼續保持開啟狀態,並且休眠時間窗重新計時。 **Hystrix所有常用配置** > 服務限流在Alibaba的Sentinel框架中會詳解 #### 5. Hystrix工作流程 [官網說明(Hystrix怎麼實操降級熔斷限流](https://github.com/Netflix/Hystrix/wiki/How-it-Works) 整體的Hystrix工作流程圖入下: 步驟說明: #### 6. Hystrix服務監控Hystrix Dashboard ##### 6.1 理解 除了隔離依賴服務的呼叫以外,Hystrix還提供了準實時的呼叫監控——Hystrix Dashboard,Hystrix會持續的記錄所有通過Hystrix發起的請求的執行資訊,並以統計報表和圖形的形式展示給使用者,包括每秒執行多少請求,多少成功,多少失敗等。SpringCloud也提供了Hystrix Dashboard的整合,對監控內容轉化成視覺化介面。 ##### 6.2 使用步驟 新建Module:cloud-consumer-hystrix-dashboard9001作為Hystrix Dashboard服務 新增Hystrix Dashboard的依賴: ```xml org.springframework.cloud spring-cloud-starter-netflix-hystrix-dashboard org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test ``` 寫配置檔案application.yml,加個埠即可: ```yml server: port: 9001 ``` 編寫主啟動類,在主啟動類上新增`@EnableHystrixDashboard`註解開啟Hystrix Dashboard功能: ```java @SpringBootApplication @EnableHystrixDashboard public class HystrixDashboardMain9001 { public static void main(String[] args) { SpringApplication.run(HystrixDashboardMain9001.class); } } ``` 注意:所有的服務提供方微服務(如我們的8001/8002/8003)都需要監控依賴配置: ```xml org.springframework.boot spring-boot-starter-actuator ``` 訪問 http://localhost:9001/hystrix 我們就可以看見Hystrix Dashboard的圖形化介面 注意:新版本Hystrix需要在主啟動類中指定監控路徑(否則會報錯:Unable to connect to Command Metric Stream)。為了讓服務提供方的服務能被Hystrix Dashboard監控到,需要在提供方服務的主啟動類中新增如下配置: ```java /** * 此配置是為了服務監控而配置,與服務容錯本身無關,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的圖形化介面中輸入要監控的服務提供者: 下面就是Dashboard對服務的監控狀態: 如何看? - 七色 - 一圈 實現圓共有兩種含義。它通過顏色的變化代表了例項的健康程度,它的健康度從綠色<黃色<橙色<紅色遞減。該實心圓除了顏色的變化之外,它的大小也會根據例項的請求流量發生變化,流量越大該實心圓也就越大。所以通過該實心圓的展示,就可以在大量的例項中快速的發現 故障例項和高壓力例項。 - 一線 曲線用來記錄2分鐘內流量的相對變化,可以通過它來觀察到流量的上升和下降趨勢 - 整圖說明1 - 整圖說明2 - 一些複雜的情況

相關推薦

. SpringCloud服務降級熔斷

#### 1. Hystrix斷路器概述 ##### 1.1 分散式系統面臨的問題 複雜分散式體系結構中的應用程式有數十個依賴關係,每個依賴關係在某些時候將不可避免地失敗。這就造成有可能會發生**服務雪崩**。那麼什麼是服務雪崩呢? 多個微服務之間呼叫的時候,假設微服務A呼叫微服務B和微服務C,微服務B

高並發之服務降級服務熔斷

height 靜態 遠程服務 很多 可用性 場景 模式 quest 部分 服務降級: 服務壓力劇增的時候根據當前的業務情況及流量對一些服務和頁面有策略的降級,以此環節服務器的壓力,以保證核心任務的進行。 同時保證部分甚至大部分任務客戶能得到正確的相應。也就是當前的請求處理不

SpringCloud-Hystrix 服務降級熔斷

Hystrix 是什麼? Hystrix 是一個用於處理分散式系統的延遲和容錯的開源庫,在分散式系統裡,許多依賴不可避免的會呼叫失敗,比如超時、異常等,Hystrix 能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分散式系統的彈性。 「斷路器」本身是一種開關裝置,當某個服務單元發

springcloud服務註冊發現

微服務架構中,服務發現元件是一個非常關鍵的元件,服務消費者、服務提供者、服務發現元件的關係大致如下: 各個微服務啟動時,將自己的網路地址等資訊註冊到服務發現元件中,服務發現元件會儲存這些資訊 服務消費者可從服務發現元件查詢服務提供者的網路地址,並使用改地址呼叫服務提供者的介面 各個微服務與服務

Swoft:服務降級熔斷器的基本使用

服務降級 那麼如果服務C崩潰了,就回影響到服務B和服務A。 為了解決這個問題,就需要用到服務降級功能了。 回顧 (示例,介面只有一個通過商品id獲取庫存的方法,並且在實現類中我們寫死了所有商品返回的庫存都是100) 如果我們的服務發生了異常(也就是app/S

Spring Cloud Hystrix 定義服務降級異常 處理

概述 原來的計劃是寫一篇大而全的文章,用來介紹spring cloud Hystrix,但是想了想,這樣的做法其實也並不是特別好,所以 打算把原來的文章拆分,這樣能夠看起來比較清晰。 服務降級 繼承H

降級特技之使用Hystrix實現降級熔斷—《億級流量網站架構核心技術》

使用Hystrix實現降級   通過配置中心可以人工進行降級,而我們也需要根據服務的超時時間進行自動降級,本部分將演示使用Hystrix實現超時自動降級。Hystrix介紹請參考“第3章 隔離術”中的Hystrix簡介部分。   public class GetStockS

白話:服務降級熔斷的區別

雖然之前在《Spring Cloud構建微服務架構》系列文章中介紹了Hystrix服務降級與Hystrix斷路器的概念。但是,還是一直收到這樣的提問:降級與熔斷區別是什麼?並且在很多交流過程中,發現有不少童鞋對降級和熔斷的概念有混淆的情況。所以,這篇博文準備換一種方式來說說這兩個概念,以幫助讀者更好的理解

SpringCloud Netflix () : Hystrix 服務熔斷服務降級

什麼是Hystrix 在分散式環境中,許多服務依賴項中的一些服務依賴不可避免地會失敗。Hystrix是一個庫,通過新增延遲容忍和容錯邏輯,幫助您控制這些分散式服務之間的互動。Hystrix通過隔離服務之間的訪問點、防止服務之間的級聯故障以及提供回退選項來實現這一點,所有這些都提高了系統的總體彈性。 (

springcloud 服務熔斷降級 服務監控

一、概念部分 1.什麼是熔斷器? 熔斷,就是斷開與伺服器的連線,熔斷器是在服務不可用的時候主動斷開,以免造成更多的雪崩效應,他是保護服務高可用的最後一道防線。 2.為什麼需要熔斷器? 為保證服務高可用,最先想到的是服務叢集,但叢集並不能完全的保證服務高可用, 當某個服務出現

SpringCloud系列七:Hystrix 熔斷機制(Hystrix基本配置、服務降級、HystrixDashboard服務監控、Turbine聚合監控)

bsp 但是 mem style 查詢 packages discover seconds ID 1、概念:Hystrix 熔斷機制 2、具體內容 所謂的熔斷機制和日常生活中見到電路保險絲是非常相似的,當出現了問題之後,保險絲會自動燒斷,以保護我們的電器, 那麽如果換到了程

Feign + Hystrix 服務熔斷服務降級

  本機IP為  192.168.1.102   1.    新建 Maven 專案   feign   2.   pom.xml <project xmlns="http://maven.apa

服務學習筆記(4)--Hystrix服務降級限流熔斷

分散式系統中,會出現哪些問題? 分散式系統中一定會遇到的一個問題:服務雪崩效應 或者叫級聯效應 那麼什麼是服務雪崩效應呢? 在一個高度服務化的系統中,我們實現的一個業務邏輯通常會依賴多個服務,比如:商品詳情展示服務會依賴商品服務, 價格服務, 商品評論服務. 如圖所示: 呼叫

SpringCloud(六)Hystrix斷路器《1》(服務熔斷服務降級

1、Hystrix概述 1.1、分散式系統面臨的問題 複雜分散式體系結構中的應用程式有數十個依賴關係,每個依賴關係在某些時候將不可避免地失敗。服務雪崩: 多個微服務之間呼叫的時候,假設微服務A呼叫微服務B和微服務C,微服務B和微服務C又呼叫其它的微服務,這就是所謂的“扇出”。如果扇

SpringCloud(3) 整合Hystrix實現服務容錯服務降級

SpringCloud整合Hystrix實現服務容錯和服務降級 ###SpringBoot版本2.0.5 什麼是Hystrix 在分散式環境中,許多服務依賴項中的一些將不可避免地失敗。Hystrix是一

springcloud系列—Hystrix—第3章-3: Hystrix 服務降級(fallback)與異常處理,Hystrix依賴隔離(命令名稱-分組執行緒池)、請求快取與清除快取、斷路器

資料參考:《Spring Cloud 微服務實戰》 目錄 服務降級 在HystrixCommand中可以通過過載getFallback()方法來實現服務降級邏輯。 在 HystrixObservableCommand 實現得 Hystrix 命令中,我們可以通過過載 resumenW

從Netflix的Hystrix框架理解服務熔斷服務降級

伴隨著微服務架構被宣傳得如火如荼,一些概念也被推到了我們面前,其實大多數概念以前就有,但很少被提的這麼頻繁。想起有人總結的一句話,微服務架構的特點就是:“一解釋就懂,一問就不知,一討論就吵架”。 圖片 來自網路,如果涉及版權請與我們聯絡。 其實對老外的總結能力一

服務架構 SpringCloud(二)Eureka(服務註冊服務發現基礎篇)

col false -c conf gis 功能 pri desc sch 一:Eureka簡介 Eureka是Spring Cloud Netflix的一個子模塊,也是核心模塊之一。用於雲端服務發現,一個基於REST的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移

SpringCloud系列八:Zuul 路由訪問(Zuul 的基本使用、Zuul 路由功能、zuul 過濾訪問、Zuul 服務降級

定義 頭信息 操作 客戶 response art lB face bubuko 1、概念:Zuul 路由訪問 2、具體內容 在現在為止所有的微服務都是通過 Eureka 找到的,但是在很多的開發之中為了規範微服務的使用,提供有一個路由的處理控制組件:Zuul,也就是說 Z

Hystrix請求熔斷服務降級

thread 我不 返回值 factor 1.4 第一次 ceo 步驟 AC 我們知道大量請求會阻塞在Tomcat服務器上,影響其它整個服務.在復雜的分布式架構的應用程序有很多的依賴,都會不可避免地在某些時候失敗.高並發的依賴失敗時如果沒有隔離措施,當前應用服務就有被拖垮的