熔斷、限流、降級 —— SpringCloud Alibaba Sentinel

Sentinel 簡介

Sentinel 是阿里中間件團隊開源的,面向分佈式服務架構的高可用流量防護組件,主要以流量爲切入點,從限流、流量整形、熔斷降級、系統負載保護、熱點防護等多個維度來幫助開發者保障微服務的穩定性

Sentinel 提供了兩個服務組件:

  • Sentinel 用來實現微服務系統中服務熔斷、降級等功能
  • Sentinel Dashboard 用來監控微服務系統中流量調用等情況

限流算法

限流的方式有很多,常用的有計數器、漏桶和令牌桶等

1. 計數器

採用計數器是一種比較簡單的限流算法,一般會限制一秒鐘能夠通過的請求數。比如限流 QPS 爲 100,算法的實現思路就是從第一個請求進來開始計時,在接下來的 1 秒內每來一個請求就把計數加 1,如果累加的數字達到了 100,後續的請求就會被全部拒絕。等到 1 秒結束後,把計數恢復成 0,重新開始計數。如果在單位時間 1 秒內的前 10 毫秒處理了 100 個請求,那麼後面的 990 毫秒會請求拒絕所有的請求,我們把這種現象稱爲突刺現象

2. 漏桶算法

漏桶算法的思路很簡單,一個固定容量的漏桶按照常量固定速率流出水滴。如果桶是空的,就不需要流出水滴。我們可以按照任意速率流入水滴到漏桶。如果流入的水滴超出了桶的容量,流入的水滴就會溢出(被丟棄),而漏桶容量是不變的。漏桶算法提供了一種機制,通過它可以讓突發流量被整形,以便爲網絡提供穩定的流量

3. 令牌桶算法

令牌桶算法是比較常見的限流算法之一,可以使用它進行接口限流。令牌按固定的速率被放入令牌桶中,當桶裝滿時,新添加的令牌會被丟棄或拒絕。當請求到達時,將從桶中刪除 1 個令牌。令牌桶中的令牌不僅可以被移除,還可以往裏添加,所以爲了保證接口隨時有數據通過,必須不停地往桶裏加令牌。由此可見,往桶裏加令牌的速度決定了數據通過接口的速度。我們通過控制往令牌桶裏加令牌的速度來控制接口的流量

4. 漏桶算法和令牌桶算法的區別

  • 漏桶算法是按照常量固定選率流出請求的,流入請求速率任意,當流入的請求數累積到漏桶容量時,新流入的請求被拒絕
  • 令牌桶算法是按照固定速率往桶中添加令牌的,請求是否被處理需要看桶中的令牌是否足夠,當令牌數減爲零時,拒絕新的請求
  • 令牌桶算法允許突發請求,只要有令牌就可以處理,允許一定程度的突發流量
  • 漏桶算法限制的是常量流出速率,從而使突發流入速率平滑

Sentinel Dashboard

Sentinel 提供一個輕量級的開源控制檯,包含如下功能:

  • 查看機器列表以及健康情況:收集 Sentinel 客戶端發送的心跳包,用於判斷機器是否在線
  • 監控(單機和集羣):通過 Sentinel 客戶端暴露的監控 API,定期拉取並且聚合應用監控信息,最終可以實現秒級的實時監控
  • 規則管理和推送:統一管理推送規則
  • 鑑權:在生產環境中,鑑權非常重要,這裏每個開發者需要根據自己的實際情況進行定製

從 GitHub 可以下載 Sentinel 安裝包:https://github.com/alibaba/Sentinel/

下載得到的是一個 jar 包(sentinel-dashboard-1.8.6.jar),可以直接通過 Java 命令啓動,如 java -jar 方式運行,默認端口爲 8080,通過 http://localhost:8080/ 訪問,用戶名和密碼默認是 sentinel


客戶端接入控制檯

引入依賴

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

配置文件配置如下:

spring:
    cloud:
        sentinel:
            transport:
                port: 18000  # 指定應用與sentinel控制檯交互的端口
                dashboard: localhost:8080   # sentinel後臺地址
            eager: true	# 開啓sentinel,默認開啓

Sentinel 限流

Sentinel 流量控制的原理是監控應用流量的 QPS 或併發線程數等指標,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峯沖垮,從而保障應用的高可用性

使用註解方式實現限流如下:

@Slf4j
@RestController
public class TestCon {

    @GetMapping("/test/byResource")
    @SentinelResource(value = "byResource", blockHandler = "handleException")
    public void byResource() {
        log.info("按資源名稱限流");
    }

    public void handleException(BlockException exception) {
        log.error("觸發失敗回調方法", exception);
    }
}

@SentinelResource 註解用於定義資源,可選屬性如下:

  • value:指定資源名稱

  • blockHandler / blockHandlerClass:指定處理 BlockExccption 異常函數名稱。函數要求必須是 public,返回類型與原方法必須一致,函數參數類型需要和原方法相匹配並在最後加 BlockException 類型的參數,函數默認和原方法在同一個類中。若希望使用其他類的函數可配置 blockHandlerClass,並指定 blockHandlerClass 裏面的方法,注意對應的函數必需爲 static 函數,否則無法解析

    // TestCon.java
    @GetMapping("/test/byResource")
    @SentinelResource(value = "byResource", blockHandler="handleBolckForTest", blockHandlerClass={BlockHandlerClassTest})
    public void byResource() {
        log.info("按資源名稱限流");
    }
    
    // BlockHandlerClassTest.java
    public static String handleBolckForTest(String name,int age, BlockException exception){
    	xxxxx
    }
    
  • fallback / fallbackClass:用於在拋出異常的時候提供 fallback 處理邏輯,可以針對所有類型的異常(除了 exceptionsToIgnore 裏面排除掉的異常類型)進行處理,返回值類型必須與原函數返回值類型一致,方法參數列表需要和原函數一致,或者可以額外多一個 Throwable 類型的參數用於接收對應的異常,fallback 函數默認需要和原方法在同一個類中,若希望使用其他類的函數,則可以指定 fallbackClass 爲對應的類的 Class 對象,注意對應的函數必需爲 static 函數,否則無法解析

在 Sentinel 控制檯的流控規則中,新增流控規則,如圖:

  • 資源名:需要和 @SentineResource 註解的 value 屬性值保持一致
  • 針對來源:默認 default,表示對所有來源進行限流,有時候我們會希望根據上級微服務或者請求來源進行限流,可以根據自身的需求進行相應的配置
  • 閾值類型:Sentinel 限流策略有兩種統計類型,一種是統計併發線程數,另一種是統計 QPS
    • 當 QPS 超過某個閾值的時候,採取措施進行流量控制,包括:
      • 直接拒絕:默認的流量控制方式,當 QPS 超過任意規則的閾值,新的請求會被立即拒絕並拋出 FlowExccption
      • Warm Up:預熱/冷啓動方式,在系統長期處於低水位的情況下,當流量突然增加時,直接把系統拉昇到高水位可能瞬間把系統壓垮,通過冷啓動讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮
      • 勻速排隊:嚴格控制請求通過的間隔時間,即讓請求以均勻的速度通過,對應的是漏桶算法
  • 流控模式:
    • 直接:接口達到限流條件時,開啓限流
    • 關聯:當指定接口關聯的接口達到限流條件時,開啓對指定接口開啓限流,舉例:設置關聯資源爲 byResource2,那麼當 byResource2 達到限流條件時,byResource 將不可用
    • 鏈路:當從某個接口過來的資源達到限流條件時,開啓限流,舉例:有兩個接口 getResource1 和 getResource2 能調用 byResource 資源,如果設置了 getResource1 並達到限流條件,那麼將無法再通過 getResource1 調用 byResource,而 getResource2 不受影響

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