SpringCloud-Hystrix 服務降級、熔斷


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%

🎨 斷路器開啟或關閉的條件

  1. 當請求達到一定閾值時(默認 20 次)
  2. 當錯誤率達到一定閾值時(默認 50%)
  3. 達到以上條件斷路器開啟
  4. 當開啟的時候,所有請求都不會轉發
  5. 當斷路器開啟一段時間后(默認 5 秒)進入半開狀態,並讓其中一個請求進行轉發,如果成功斷路器關閉,如果失敗繼續開啟,重復第 4 和 5 步

🎨 斷路器開啟之后會發生什么?

  • 再有請求調用時,不再調用主邏輯,而是調用降級 fallback。
  • 斷路器開啟之后,Hytrix 會啟動一個休眠時間窗,在此時間內,fallback 會臨時稱為主邏輯,當休眠期到了之后,斷路器進入半開狀態,釋放一個請求到原來的主邏輯上,如果請求成功返回,則斷路器關閉,如果請求失敗,則繼續進入打開狀態,休眠時間窗重新計時。

Hystrix服務熔斷的工作流程

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM