扛住阿里雙十一高並發流量,Sentinel是怎麼做到的?

java的小本家 發佈 2020-01-08T10:14:41+00:00

Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景本文介紹阿里開源限流熔斷方案 Sentinel 功能、原理、架構、快速入門以及相關框架比較基本介紹1 名詞解釋服務限流 :當系統資源不夠,不足以應對大量請求,對系統按照預設的規則進行流量限制或功能限制服務熔斷:

Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景

本文介紹阿里開源限流熔斷方案 Sentinel 功能、原理、架構、快速入門以及相關框架比較

基本介紹

1 名詞解釋

  • 服務限流 :當系統資源不夠,不足以應對大量請求,對系統按照預設的規則進行流量限制或功能限制
  • 服務熔斷:當調用目標服務的請求和調用大量超時或失敗,服務調用方為避免造成長時間的阻塞造成影響其他服務,後續對該服務接口的調用不再經過進行請求,直接執行本地的默認方法
  • 服務降級:為了保證核心業務在大量請求下能正常運行,根據實際業務情況及流量,對部分服務降低優先級,有策略的不處理或用簡單的方式處理

服務降級的實現可以基於人工開關降級(秒殺、電商大促等)和自動檢測(超時、失敗次數、故障),熔斷可以理解為一種服務故障降級處理

2 為什麼需要限流降級

系統承載的訪問量是有限的,如果不做流量控制,會導致系統資源占滿,服務超時,從而所有用戶無法使用,通過服務限流控制請求的量,服務降級省掉非核心業務對系統資源的占用,最大化利用系統資源,儘可能服務更多用戶

3 Sentinel 簡介

Sentinel: 分布式系統的流量防衛兵,是阿里中間件團隊 2018 年 7 月開源的,面向分布式服務架構的輕量級流量控制產品,主要以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度來保護系統服務的穩定性

Sentinel 的開源生態:


功能特性

1 總體介紹

Sentinel 具有以下特徵:

豐富的應用場景:秒殺限流,消息削峰填谷、集群流量控制、實時熔斷下游不可用應用等

完備的實時監控:Sentinel 同時提供實時的監控功能。可以在控制台中看到接入應用的單台機器秒級數據,甚至 500 台以下規模的集群的匯總運行情況

廣泛的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel

完善的 SPI 擴展點:Sentinel 提供簡單易用、完善的 SPI 擴展接口。可以通過實現擴展接口來快速地定製邏輯。例如定製規則管理、適配動態數據源等


Sentinel 分為兩個部分:

控制台(Dashboard) 基於 Spring Boot 開發,打包後可以直接運行,不需要額外的 Tomcat 等應用容器

核心庫(Java 客戶端) 不依賴任何框架/庫,能夠運行於所有 Java 運行時環境,同時對 Dubbo / Spring Cloud 等框架也有較好的支持

2 控制台特性

  • 實時監控 支持自動發現集群機器列表、服務健康狀態、服務調用通過/拒絕 QPS、調用耗時、圖表統計
  • 規則管理及推送 支持在介面配置流控、降級、熱點規則,並實時推送
  • 鑒權 控制台支持自定義鑒權接口,提供基本登錄功能


3 核心庫功能特性


(1) 應用流控

針對指定應用實例的流量控制,監控應用流量 QPS 或並發線程數,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰衝垮,從而保障應用的高可用性

流量控制的手段包括:

  • 直接拒絕
  • Warm Up,即預熱/冷啟動方式,讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被瞬間壓垮
  • 勻速排隊,嚴格控制請求通過的間隔時間,讓請求以均勻的速度通過


(2) 集群流控

不同於應用流控根據單個應用實例閾值執行限流檢查,集群流控只對整個集群調用總量進行限流,例如以下場景:

  • 限制某個用戶調用某個 API 的總 QPS,提供 API 的應用在多個機器上部署了多個實例
  • 因為多個應用實例流量不均勻,導致集群調用總量沒有到的情況下某些機器就開始限流

僅靠單機維度去限制的話會無法精確地限制總體流量,通過集群精確地控制整個集群的調用總量,結合單機限流兜底,可以更好地發揮流量控制的效果

(3) 網關流控

Sentinel 支持對 Spring Cloud Gateway、Zuul 等主流的 API Gateway 進行限流

網關流控針對 API 網關的場景定製的限流規則,可以針對不同 route 或自定義的 API 分組進行限流,支持針對請求中的路徑、參數、Header、來源 IP 等進行定製化的限流

(4) 熔斷降級

如果調用鏈路中的某個資源不穩定,最終會導致請求發生堆積,通過熔斷降級能在調用鏈路中某個資源出現不穩定狀態時(包括調用超時、異常比例升高、異常數升高),對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯錯誤

當資源被降級後,在接下來的降級時間窗口之內,對該資源的調用都自動熔斷(默認行為是拋出 DegradeException),經過時間窗口之後,退出熔斷,並在下一次資源出現不穩定狀態再次自動熔斷

(5) 熱點參數限流

熱點即經常訪問的數據,熱點參數限流會統計傳入參數中的熱點參數,並根據配置的限流閾值與模式,對包含熱點參數的資源調用進行限流 例如以下場景:

  • 用戶 ID 為參數,限制用戶對接口的範圍 QPS
  • 商品 ID 為參數,限制商品下單接口頻率

(6) 系統自適應限流

為了解決傳統方案:基於作業系統負載(load1,linux 下用 uptime 查看)做進行自適應限流,帶來的存在延時、系統性能恢復慢的問題,Sentinel 採用新的思路:根據系統能夠處理的請求,和允許進來的請求,來做平衡,而不是根據一個間接的指標(系統 load)來做限流

目標在於:在系統不被拖垮的情況下,儘可能提高系統的吞吐率,而不是 負載 一定要到低於某個閾值

系統保護規則是從應用級別的入口流量進行控制,從單台機器的總體 Load、RT、入口 QPS 和線程數四個維度監控應用數據,當實際運行達到限定閾值進行限流保護,支持的閾值類型:

  • Load:當系統 load1 超過閾值,且系統當前的並發線程數超過系統容量時才會觸發系統保護。系統容量由系統時間運行監測到的的 maxQps * minRt (最小響應時間)計算得出
  • RT:當單台機器上所有入口流量的平均 RT(響應時間)
  • 線程數:當單台機器上所有入口流量的並發線程數
  • 入口 QPS:當單台機器上所有入口流量的 QPS


(7) 黑白名單控制

Sentinel 黑白名單根據資源的請求來源(origin)限制資源是否通過,若配置白名單則只有請求來源位於白名單內時才可通過;若配置黑名單則請求來源位於黑名單時不通過,其餘的請求通過


快速入門

1 安裝控制台

從 github release 頁面(https://github.com/alibaba/Sentinel/releases)下載最新控制台 jar 包

命令行啟動控制台:

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar


2 應用接入 Sentinel

Sentinel 適配了常見主流框架,包括 Dubbo、Spring Boot、Spring WebFlux、gRPC、Zuul、Spring Cloud Gateway、RocketMQ、Web Servlet,對於需要限流的資源,支持用原生 Java 的 try-catch 接入或者使用註解

下面以常見的 Spring Boot 註解的方式作為示例:引入 sentinel 適配 Spring Cloud 的依賴:

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

application.yml 指定控制台地址:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: IP:埠號

定義需要限流的資源:

@RestController
public class TestController {

    @GetMapping(value = "/hello")
    // 定義需要限流的資源名稱為hello
    @SentinelResource("hello")
    public String hello() {
        return "Hello Sentinel";
    }
}

請求一次上面的 http hello 接口後,觸發 Sentinel 客戶端初始化,才能在控制台看到接口

添加流控規則:

頻繁請求接口,可以看到部分請求被拒絕:



注意:上面的配置方式是沒有做持久化的,生產環境不建議使用

3 規則配置

Sentinel 提供 動態規則數據源 支持來動態地管理、讀取配置的規則。Sentinel 提供的 ReadableDataSource 和 WritableDataSource 接口簡單易用,非常方便使用。

Sentinel 動態規則源針對常見的配置中心和遠程存儲進行適配,目前已支持 Nacos、ZooKeeper、Apollo、Redis 等多種動態規則源,可以覆蓋到很多的生產場景

實現原理

下面介紹 Sentinel 客戶端基本原理

1 基本概念

  • Resource 資源 Sentinel 中,需要被流量保護的方法、代碼塊都可以稱為資源,每個資源都需要定義一個唯一的資源名詞,用於匹配相關規則
  • Entry Sentinel 功能入口類,Entry 可以通過對主流框架的適配自動創建,也可以通過註解的方式或調用 SphU API 顯式創建,創建後執行資源和規則匹配和校驗
  • Slot 功能插槽,由 Enty 類創建,每個資源對應一系列 Slot,Slot 實現資源信息收集、規則匹配、校驗的,多個 Slot 通過組成 Slot Chain,在進入資源和退出資源時分別基於責任鏈模式調用 entry()和 exit()方法

2 工作原理

一個簡單的 demo:

String resourceName = "resourceName";
Entry entry = null;
try {
        entry = SphU.entry(resourceName);
        System.out.println("resource running");
} catch (BlockException e) {
        // 限流
        throw e;
} catch (Throwable e) {
        e.printStackTrace();
        throw e;
} finally {
        if (entry != null) {
                entry.exit();
        }
}

主要流程如下:

  • 進入資源方法之前,基於 SphU 創建 Entry,Entry 獲取查找資源關聯的 Slot Chain 信息,如果找不到則創建,並基於責任鏈模式調用 Slot 的 entry()方法
  • 資源方法調用
  • 資源方法調用完成後,通過 Entry 觸發 Slot 的 exit()邏輯

框架比較


值得補充的是:相比 Hystrix 基於線程池隔離進行限流,這種方案雖然隔離性比較好,但是代價就是線程數目太多,線程上下文切換的 overhead 比較大,特別是對低延時的調用有比較大的影響。

Sentinel 並發線程數限流不負責創建和管理線程池,而是簡單統計當前請求上下文的線程數目,如果超出閾值,新的請求會被立即拒絕,效果類似於信號量隔離

關鍵字: