-
在分布式環境中,許多服務依賴項不可避免地會失敗。Hystrix是一個庫,它通過添加延遲容忍和容錯邏輯來幫助您控制這些分布式服務之間的交互。Hystrix通過隔離服務之間的訪問點、停止它們之間的級聯故障以及提供后備選項來實現這一點,所有這些都可以提高系統的整體彈性。
-
通俗定義: Hystrix是一個用於處理分布式系統的延遲和容錯的開源庫,在分布式系統中,許多依賴不可避免的會調用失敗,超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障(服務雪崩現象),提高分布式系統的彈性。
1.服務雪崩
1.服務雪崩
- 在微服務之間進行服務調用是由於某一個服務故障,導致級聯服務故障的現象,稱為雪崩效應。雪崩效應描述的是提供方不可用,導致消費方不可用並將不可用逐漸放大的過程。
2.圖解雪崩效應
- 如存在如下調用鏈路:
- 而此時,Service A的流量波動很大,流量經常會突然性增加!那么在這種情況下,就算Service A能扛得住請求,Service B和Service C未必能扛得住這突發的請求。此時,如果Service C因為抗不住請求,變得不可用。那么Service B的請求也會阻塞,慢慢耗盡Service B的線程資源,Service B就會變得不可用。緊接着,Service A也會不可用,這一過程如下圖所示
2.服務熔斷
1.服務熔斷
- “熔斷器”本身是一種開關裝置,當某個服務單元發生故障之后,通過斷路器的故障監控,某個異常條件被觸發,直接熔斷整個服務。向調用方法返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者拋出調用方法無法處理的異常,就保證了服務調用方的線程不會被長時間占用,避免故障在分布式系統中蔓延,乃至雪崩。如果目標服務情況好轉則恢復調用。服務熔斷是解決服務雪崩的重要手段。
2.服務熔斷圖示
3.服務降級
1.服務降級說明
-
服務壓力劇增的時候根據當前的業務情況及流量對一些服務和頁面有策略的降級,以此環節服務器的壓力,以保證核心任務的進行。同時保證部分甚至大部分任務客戶能得到正確的相應。也就是當前的請求處理不了了或者出錯了,給一個默認的返回。
-
通俗: 關閉系統中邊緣服務 保證系統核心服務的正常運行 稱之為服務降級
淘寶 刪除地址 確認收貨 刪除訂單 取消支付 節省cpu 內存
4.降級和熔斷總結
1.共同點
- 目的很一致,都是從可用性可靠性着想,為防止系統的整體緩慢甚至崩潰,采用的技術手段;
- 最終表現類似,對於兩者來說,最終讓用戶體驗到的是某些功能暫時不可達或不可用;
- 粒度一般都是服務級別,當然,業界也有不少更細粒度的做法,比如做到數據持久層(允許查詢,不允許增刪改);
- 自治性要求很高,熔斷模式一般都是服務基於策略的自動觸發,降級雖說可人工干預,但在微服務架構下,完全靠人顯然不可能,開關預置、配置中心都是必要手段;
2.異同點
- 觸發原因不太一樣,服務熔斷一般是某個服務(下游服務)故障引起,而服務降級一般是從整體負荷考慮;
- 管理目標的層次不太一樣,熔斷其實是一個框架級的處理,每個微服務都需要(無層級之分),而降級一般需要對業務有層級之分(比如降級一般是從最外圍服務開始)
3.總結
- 熔斷必會觸發降級,所以熔斷也是降級一種,區別在於熔斷是對調用鏈路的保護,而降級是對系統過載的一種保護處理
5.服務熔斷的實現
服務熔斷的實現思路
- 引入hystrix依賴,並開啟熔斷器(斷路器)
- 模擬降級方法
- 進行調用測試
1.項目中引入hystrix依賴
在商品服務下面
<!--引入hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.開啟斷路器
@SpringBootApplication
@EnableCircuitBreaker //用來開啟斷路器
public class Products9998Application {
public static void main(String[] args) {
SpringApplication.run(Products9998Application.class, args);
}
}
3.使用HystrixCommand注解實現斷路
//服務熔斷
@GetMapping("/product/break")
@HystrixCommand(fallbackMethod = "testBreakFall" )
public String testBreak(int id){
log.info("接收的商品id為: "+ id);
if(id<=0){
throw new RuntimeException("數據不合法!!!");
}
return "當前接收商品id: "+id;
}
// 觸發熔斷的方法
public String testBreakFall(int id){
return "當前數據不合法: "+id;
}
4.訪問測試
- 正常參數訪問
- 錯誤參數訪問
一直使用錯誤參數訪問,那么再使用正常參數訪問也會顯示不合法,因為觸發了斷路器,但過一點時間又會自動的關閉,訪問又合法了
5.總結
- 從上面演示過程中會發現如果觸發一定條件斷路器會自動打開,過了一點時間正常之后又會關閉。那么斷路器打開條件是什么呢?
6.斷路器打開條件
A service failure in the lower level of services can cause cascading failure all the way up to the user. When calls to a particular service exceed circuitBreaker.requestVolumeThreshold
(default: 20 requests) and the failure percentage is greater than circuitBreaker.errorThresholdPercentage
(default: >50%) in a rolling window defined by metrics.rollingStats.timeInMilliseconds
(default: 10 seconds), the circuit opens and the call is not made. In cases of error and an open circuit, a fallback can be provided by the developer. --摘自官方
原文翻譯之后,總結打開關閉的條件:
- 1 當滿足一定的閥值的時候(默認10秒內超過20個請求次數)
- 2、當失敗率達到一定的時候(默認10秒內超過50%的請求失敗)
- 3、到達以上閥值,斷路器將會開啟
- 4、當開啟的時候,所有請求都不會進行轉發
- 5、一段時間之后(默認是5秒),這個時候斷路器是半開狀態,會讓其中一個請求進行轉發。如果成功,斷路器會關閉,若失敗,繼續開啟。重復4和5。
7.默認的服務FallBack處理方法
- 如果為每一個服務方法開發一個降級,對於我們來說,可能會出現大量的代碼的冗余,不利於維護,這個時候就需要加入默認服務降級處理方法
@GetMapping("/product/hystrix")
@HystrixCommand(defaultFallback = "testHystrixFallBack") //通過HystrixCommand降級處理 指定出錯的方法
public String testHystrix(String name) {
log.info("接收名稱為: " + name);
int n = 1/0;
return "服務[" + port + "]響應成功,當前接收名稱為:" + name;
}
//服務降級處理
public String testHystrixFallBack(String name) {
return port + "當前服務已經被降級處理!!!,接收名稱為: "+name;
}
6.服務降級的實現
還是再之前項目的基礎之上
1.客戶端openfeign + hystrix實現服務降級實現
- 引入hystrix依賴
- 配置文件開啟feign支持hystrix
- 在feign客戶端調用加入fallback指定降級處理
- 開發降級處理方法
2.開啟openfeign支持服務降級
feign.hystrix.enabled=true #開啟openfeign支持降級
3.在openfeign客戶端中加如Hystrix
// 創建一個ProductClientFallBack類實現這個接口,並實現這個接口的所有方法,為了對每個方法做不同的響應錯略
// 指定當前的接口是openfeign組件,value是調用的服務名
@FeignClient(value = "products",fallback = ProductClientFallBack.class)
public interface ProductClient {
@GetMapping("/product/findOne")
Map<String, Object> findOne(@RequestParam("productId") String productId);
}
4.開發fallback處理類
package com.md.fallback;
@Component
public class ProductClientFallBack implements ProductClient {
@Override
public Map<String, Object> findOne(String productId) {
HashMap<String, Object> map = new HashMap<>();
map.put("status","false");
map.put("msg","當前查詢不可以使用,服務已經被降級");
return map;
}
}
正常訪問
然后直接將產品服務關閉,再進行訪問
注意:如果服務端降級和客戶端降級同時開啟,要求服務端降級方法的返回值必須與客戶端方法降級的返回值一致!!!
7.Hystrix Dashboard
0.說明
- Hystrix Dashboard的一個主要優點是它收集了關於每個HystrixCommand的一組度量。Hystrix儀表板以高效的方式顯示每個斷路器的運行狀況。
只是一個有UI頁面的組件,創建一個新的項目,還是根據之前的springcloud的環境搭建
1.項目中引入依賴
<!--引入hystrix dashboard 依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
2.入口類中開啟hystrix dashboard
@SpringBootApplication
@EnableHystrixDashboard //開啟監控面板
public class Hystrixdashboard9990Application {
public static void main(String[] args) {
SpringApplication.run(Hystrixdashboard9990Application.class, args);
}
}
在配置文件中指定端口號9990
3.啟動hystrix dashboard應用
- http://localhost:9990(dashboard端口)/hystrix
4.監控的項目中入口類中加入監控路徑配置[新版本坑],並啟動監控項目
@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;
}
5.通過監控界面監控
后面的hystrix.stream是固定的
6.點擊監控,一致loading,打開控制台發現報錯[特別坑]
# 解決方案
- 新版本中springcloud將jquery版本升級為3.4.1,定位到monitor.ftlh文件中,js的寫法如下:
$(window).load(function()
- jquery 3.4.1已經廢棄上面寫法
- 修改方案 修改monitor.ftlh為如下調用方式:
$(window).on("load",function()
- 編譯jar源文件,重新打包引入后,界面正常響應。
8.Hystrix停止維護
官方地址:https://github.com/Netflix/Hystrix
- 翻譯:Hystrix(版本1.5.18)足夠穩定,可以滿足Netflix對我們現有應用的需求。同時,我們的重點已經轉移到對應用程序的實時性能作出反應的更具適應性的實現,而不是預先配置的設置(例如,通過自適應並發限制)。對於像Hystrix這樣的東西有意義的情況,我們打算繼續在現有的應用程序中使用Hystrix,並在新的內部項目中利用諸如resilience4j這樣的開放和活躍的項目。我們開始建議其他人也這樣做。
- Dashboard也被廢棄