Hystrix的原理及使用

在真正學習Hystrix之前,讓我們愉悅的談談Hystrix產生的背景

一、背景介紹
1、服務雪崩
分佈式系統環境下,服務間類似依賴非常常見,一個業務調用通常依賴多個基礎服務。如下圖,

如果各個服務正常運行,那大家齊樂融融,高高興興的,但是如果其中一個服務崩壞掉會出現什麼樣的情況呢?如下圖,

當Service A的流量波動很大,流量經常會突然性增加!那麼在這種情況下,就算Service A能扛得住請求,Service B和Service C未必能扛得住這突發的請求。
此時,如果Service C因爲抗不住請求,變得不可用。那麼Service B的請求也會阻塞,慢慢耗盡Service B的線程資源,Service B就會變得不可用。緊接着,Service A也會不可用。

So,簡單地講。一個服務失敗,導致整條鏈路的服務都失敗的情形,我們稱之爲服務雪崩。

2、引起雪崩的原因和服務雪崩的三個階段
原因大致有四:
1、硬件故障;
2、程序Bug;
3、緩存擊穿(用戶大量訪問緩存中沒有的鍵值,導致大量請求查詢數據庫,使數據庫壓力過大);
4、用戶大量請求;

服務雪崩的第一階段: 服務不可用;
第二階段:調用端重試加大流量(用戶重試/代碼邏輯重試);
第三階段:服務調用者不可用(同步等待造成的資源耗盡);

3、解決方案
1) 應用擴容(擴大服務器承受力)

加機器
升級硬件
2)流量控制(超出限定流量,返回類似重試頁面讓用戶稍後再試)

限流
關閉重試
3) 緩存

將用戶可能訪問的數據大量的放入緩存中,減少訪問數據庫的請求。

4)服務降級

服務接口拒絕服務
頁面拒絕服務
延遲持久化
隨機拒絕服務
5) 服務熔斷

如果對服務降級和服務熔斷的概念模糊點此瞭解 關於服務熔斷和服務降級的詳解

二、Hystrix入門
Hystrix簡介
Hystrix [hɪst’rɪks],中文含義是豪豬,因其背上長滿棘刺,從而擁有了自我保護的能力。

以項目案例開始,快速入門(使用IDEA)
場景假設1( 服務提供方報錯) : 在服務提供端中因爲訪問不到數據庫中的數據(比如數據不存在,或是數據庫壓力過大,查詢請求隊列中),在這種情況下,服務提供方這邊如何實現服務降級,以防止服務雪崩.

使用IDEA新建一個 microservice-provider-hystrix 工程
因爲此工程要受到Hystrix保護,所以加入依賴.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
1
2
3
4
在microservice-provider-hystrix 工程的啓動類上啓用斷路器
在啓動類上加入註解
@EnableCircuitBreaker //啓用斷路器
注意: 這裏其實也可以使用 spring cloud應用中的@SpringCloudApplication註解,因爲它已經自帶了這些註解,源碼如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {

}
1
2
3
4
5
6
7
8
9
10
在 ProductController中加入斷路邏輯
@RequestMapping("/get/{id}")
@HystrixCommand(fallbackMethod="errorCallBack") //模仿沒有這個數據時,服務降級
public Object get(@PathVariable("id") long id){
Product p=this.productService.findById(id);
if( p==null){
throw new RuntimeException("查無此產品");
}
return p;
}

//指定一個降級的方法
public Object errorCallBack( @PathVariable("id") long id ){
return id+"不存在,error";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
啓動provider服務後測試

小結: 服務降級 由服務提供方 處理

場景假設2: 因爲網絡抖動,或服務端維護導致的服務暫時不可用,此時是客戶端聯接不到服務器,因爲feign有重試機制,這樣會導致系統長時間不響應,那麼在這種情況上如何通過 feign+hystrix 在服務的消費方實現服務熔斷(回退機制)呢?

首先確認一下我們使用的客戶端是 microservice-consumer-feign , feign中自帶了 hystrix,但並沒有啓動,所以要配置啓用hystrix,修改 application.yml

feign:
hystrix:
enabled: true
1
2
3
我們的服務消費方的feign操作接口位於 microservice-interface中,所以要在這裏配置

建立一個包 fallback,用於存回退處理類 IProductClientServiceFallbackFactory,這個類有出現請求異常時的處理
package com.yc.springcloud2.fallback;

import com.yc.springcloud2.bean.Product;
import com.yc.springcloud2.service.IProductClientService;
import feign.hystrix.FallbackFactory;

import java.util.List;
@Component //必須被spring 託管
public class IProductClientServiceFallbackFactory implements FallbackFactory<IProductClientService> {
@Override
public IProductClientService create(Throwable throwable) {
//這裏提供請求方法出問題時回退處理機制
return new IProductClientService(){

@Override
public Product getProduct(long id) {
Product p=new Product();
p.setProductId(999999999L);
p.setProductDesc("error");
return p;
}

@Override
public List<Product> listProduct() {
return null;
}

@Override
public boolean addPorduct(Product product) {
return false;
}
};
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
在業務接口上加入 fallbackFactory屬性指定異常處理類
@FeignClient(name="MICROSERVICE-PROVIDER-PRODUCT",
configuration = FeignClientConfig.class,
fallbackFactory = IProductClientServiceFallbackFactory.class) // 配置要按自定義的類FeignClientConfig
public interface IProductClientService {
1
2
3
4
啓動 microservice-consumer-feign客戶端進行測試, 在測試時,嘗試關閉生產端,看它是否回退

小結: 服務熔斷在消費端 處理
三、Hystrix技術點
設計目標:

1. 對來自依賴的延遲和故障進行防護和控制——這些依賴通常都是通過網絡訪問的
2. 阻止故障的連鎖反應
3. 快速失敗並迅速恢復
4. 回退並優雅降級
5. 提供近實時的監控與告警
1
2
3
4
5
設計原則:

1. 防止任何單獨的依賴耗盡資源(線程)
2. 過載立即切斷並快速失敗,防止排隊
3. 儘可能提供回退以保護用戶免受故障
4. 使用隔離技術(例如隔板,泳道和斷路器模式)來限制任何一個依賴的影響
5. 通過近實時的指標,監控和告警,確保故障被及時發現
6. 通過動態修改配置屬性,確保故障及時恢復
7. 防止整個依賴客戶端執行失敗,而不僅僅是網絡通信
1
2
3
4
5
6
7
Hystrix如何實現:

使用命令模式將所有對外部服務(或依賴關係)的調用包裝在HystrixCommand或HystrixObservableCommand對象中,並將該對象放在單獨的線程中執行;
每個依賴都維護着一個線程池(或信號量),線程池被耗盡則拒絕請求(而不是讓請求排隊)。
記錄請求成功,失敗,超時和線程拒絕。
服務錯誤百分比超過了閾值,熔斷器開關自動打開,一段時間內停止對該服務的所有請求。
請求失敗,被拒絕,超時或熔斷時執行降級邏輯。
近實時地監控指標和配置的修改。
四、服務監控HystrixDashboard的使用
步驟:

新建一個模塊【microservice-consumer-hystrix-dashboard】

pom.xml配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
1
2
3
4
5
6
7
8
application.yml中配置端口
server:
port: 9001
1
2
創建啓動類,配置hystrix啓動
package com.yc.springcloud2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApp {
public static void main(String[] args) {
SpringApplication.run( HystrixDashboardApp.class,args);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
啓動後可通過 http://localhost:9001/hystrix 訪問此應用

dashboard有三種監控模式:
默認的集羣監控: http://turbine-hostname:port/turbine.stream
指定的集羣監控: http://turbine-hostname:port/turbine.stream?cluster=[clusterName]
單體應用的監控: http://hystrix-app:port/actuator/hystrix.stream

頁面上面的幾個參數局域:
最上面的輸入框: 輸入上面所說的三種監控方式的地址,用於訪問具體的監控信息頁面。
Delay: 該參數用來控制服務器上輪詢監控信息的延遲時間,默認2000毫秒。
Title: 該參數對應頭部標題Hystrix Stream之後的內容,默認會使用具體監控實例的Url。

注意點:
1.前兩種監控模式都是對集羣的監控,需要整合Turbine才能實現。
2.而單個服務實例的監控,從http://hystrix-app:port/actuator/hystrix.stream連接中可以看出,Hystrix Dashboard監控單節點實例需要訪問實例的actuator/hystrix.stream接口,我們自然就需要爲服務實例添加這個端點

在 [microservice-provider-hystrix] 中的pom中加入actuator監控模塊,以開啓監控相關的端點,並確保引入斷路器的依賴: spring-cloud-starter-hystrix
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
1
2
3
4
5
6
7
8
在 [microservice-provider-hystrix] 中修改 application.yml 文件,加入管理終端配置
management:
endpoints:
web:
exposure:
include: '*'
1
2
3
4
5
需要注意的是在Spring Cloud Finchley 版本以前訪問路徑是/hystrix.stream,如果是Finchley的話就需要加入上面的配置。因爲spring Boot 2.0.x以後的actuator default配置只暴露了info和health2個端點,這裏我們把所有端點開放,include: '*'代表開放所有端點

確保在 [microservice-provider-hystrix] 的啓動主類中使用@EnableCircuitBreaker 註解,開啓斷路器功能.
@SpringBootApplication
@EnableEurekaClient //啓動eureka客戶端
@EnableDiscoveryClient //啓用服務發現客戶端,以獲取當前provider的註冊信息
@EnableCircuitBreaker //啓用斷路器
@SpringCloudApplication
public class ProductApp_hystrix {
public static void main(String[] args) {
SpringApplication.run( ProductApp_hystrix.class,args);
}
}

1
2
3
4
5
6
7
8
9
10
11
瀏覽器訪問http://localhost:8888/actuator/hystrix.stream會看到如下頁面,因爲監控的實例( 即 【microservice-provider-hystrix]本身還沒有調用任何服務,所以監控端點也沒記錄任何信息


新開一個瀏覽器tab頁,訪問下 http://localhost:8888/product/get/1,重新刷新下剛纔的頁面可以看到已經有數據返回了,說明我們的埋點生效了


從瀏覽器中的信息可以看出這些信息是剛剛請求微服務時所記錄的監控信息,但是直接去看這些信息肯定是不友好的(根本看不懂),所以Hystrix Dashboard就派上用場了

在Hystrix Dashboard中間這個輸入框中,填入=服務的監控地址,也就是http://admin:a@localhost:8888/actuator/hystrix.stream,點擊Monitor Stream按鈕,就會跳轉到具體的監控頁面

 

多次請求http://localhost:8888/product/get/1,會發現監控頁面的數據也在實時的更新

小結:
以上我們可以使用dashboard對單個實例做信息監控,但在分佈式系統中,有很多實例要運維和監控,這樣要開啓多個窗口來監控,所以可以利用turbine和dashboard結合來對集羣監控.
————————————————
版權聲明:本文爲CSDN博主「Weichenghenxing」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_38149225/article/details/109454418

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章