Sentinel學習(一) —— 快速實現限流

Sentinel簡介

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

Sentinel 具有以下特徵:

  • 豐富的應用場景: Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峯填谷、集羣流量控制、實時熔斷下游不可用應用等。
  • 完備的實時監控: Sentinel 同時提供實時的監控功能。您可以在控制檯中看到接入應用的單臺機器秒級數據,甚至 500 臺以下規模的集羣的彙總運行情況。
  • 廣泛的開源生態: Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel。
  • 完善的 SPI 擴展點: Sentinel 提供簡單易用、完善的 SPI 擴展接口。您可以通過實現擴展接口來快速地定製邏輯。例如定製規則管理、適配動態數據源等。

Sentinel 的主要特性:
在這裏插入圖片描述
Sentinel 的開源生態:

在這裏插入圖片描述
Sentinel 和之前常用的熔斷降級庫 Netflix Hystrix 的對比
在這裏插入圖片描述

本地 Demo

1. 引入 Sentinel 依賴

如果您的應用使用了 Maven,則在 pom.xml 文件中加入以下代碼即可:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.7.2</version>
</dependency>

2. 定義資源

資源 是 Sentinel 中的核心概念之一。最常用的資源是我們代碼中的 Java 方法。 當然,您也可以更靈活的定義你的資源,例如,把需要控制流量的代碼用 Sentinel API SphU.entry("HelloWorld")entry.exit() 包圍起來即可。在下面的例子中,我們將 System.out.println("hello world"); 作爲資源(被保護的邏輯),用 API 包裝起來。參考代碼如下:

public static void main(String[] args) {
    // 配置規則.
    initFlowRules();

  while (true) {
    // 1.5.0 版本開始可以直接利用 try-with-resources 特性,自動 exit entry
    try (Entry entry = SphU.entry("HelloWorld")) {
        // 被保護的邏輯
        System.out.println("hello world");
	} catch (BlockException ex) {
            // 處理被流控的邏輯
	    System.out.println("blocked!");
	} finally {
        if (entry != null) {
            entry.exit();
        }
    }
  }
}

除了通過跑出異常的方式定義資源外,返回布爾值的方式也是一樣的,這裏不具體展開了。

PS:如果你不想對原有的業務代碼進行侵入,也可以通過註解 SentinelResource 來進行資源埋點。

3. 定義規則

接下來,通過流控規則來指定允許該資源通過的請求次數,例如下面的代碼定義了資源 HelloWorld 每秒最多隻能通過 20 個請求。

private static void initFlowRules(){
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule();
    rule.setResource("HelloWorld");
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    // Set limit QPS to 20.
    rule.setCount(20);
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}

我們需要對流控規則做個詳細的瞭解,以便更好的進行限流的操作,流控的規則對應的是 FlowRule。

一條FlowRule有以下幾個重要的屬性組成:

  • resource: 規則的資源名
  • grade: 限流閾值類型,qps 或線程數
  • count: 限流的閾值
  • limitApp: 被限制的應用,授權時候爲逗號分隔的應用集合,限流時爲單個應用
  • strategy: 基於調用關係的流量控制
  • controlBehavior:流控策略

前三個屬性比較好理解,最後三個比較難理解,讓我們來詳細看下最後三個屬性:

limitApp

首先讓我們來看下limitApp,從字面上看是指要限制哪個應用的意思,主要是用於根據調用方進行流量控制。
他有三種情況可以選擇:

  • default

表示不區分調用者,來自任何調用者的請求都將進行限流統計。

  • {someoriginname}

表示針對特定的調用者,只有來自這個調用者的請求才會進行流量控制。

例如:資源 NodeA 配置了一條針對調用者 caller1 的規則,那麼當且僅當來自 caller1 對 NodeA的請求才會觸發流量控制。

  • other

表示除 {someoriginname} 以外的其餘調用方的流量進行流量控制。

例如:資源 NodeA 配置了一條針對調用者 caller1 的限流規則,同時又配置了一條調用者爲 other 的規則,那麼任意來自非 caller1 對 NodeA 的調用,都不能超過 other 這條規則定義的閾值。

strategy

基於調用關係的流量控制,也有三種情況可以選擇:

  • STRATEGY_DIRECT

根據調用方進行限流。ContextUtil.enter(resourceName, origin) 方法中的 origin 參數標明瞭調用方的身份。

如果 strategy 選擇了DIRECT ,則還需要根據限流規則中的 limitApp 字段根據調用方在不同的場景中進行流量控制,包括有:”所有調用方“、”特定調用方origin“、”除特定調用方origin之外的調用方“。

  • STRATEGY_RELATE

根據關聯流量限流。當兩個資源之間具有資源爭搶或者依賴關係的時候,這兩個資源便具有了關聯,可使用關聯限流來避免具有關聯關係的資源之間過度的爭搶。

比如對數據庫同一個字段的讀操作和寫操作存在爭搶,讀的速度過高會影響寫得速度,寫的速度過高會影響讀的速度。

舉例來說:readdb 和 writedb 這兩個資源分別代表數據庫讀寫,我們可以給 readdb 設置限流規則來達到寫優先的目的:設置 FlowRule.strategy 爲 RuleConstant.STRATEGYRELATE,同時設置 FlowRule.refResource 爲 write_db。這樣當寫庫操作過於頻繁時,讀數據的請求會被限流。

  • STRATEGY_CHAIN

根據調用鏈路入口限流。假設來自入口 Entrance1 和 Entrance2 的請求都調用到了資源 NodeA,Sentinel 允許根據某個入口的統計信息對資源進行限流。

舉例來說:我們可以設置 FlowRule.strategy 爲 RuleConstant.CHAIN,同時設置 FlowRule.refResource 爲 Entrance1 來表示只有從入口 Entrance1 的調用纔會記錄到 NodeA 的限流統計當中,而對來自 Entrance2 的調用可以放行。

controlBehavior

流控策略,主要是發生攔截後具體的流量整形和控制策略,目前有三種策略,分別是:

  • CONTROLBEHAVIORDEFAULT

這種方式是:直接拒絕,該方式是默認的流量控制方式,當 qps 超過任意規則的閾值後,新的請求就會被立即拒絕,拒絕方式爲拋出FlowException。

這種方式適用於對系統處理能力確切已知的情況下,比如通過壓測確定了系統的準確水位。

  • CONTROLBEHAVIORWARM_UP

這種方式是:排隊等待 ,又稱爲 冷啓動。該方式主要用於當系統長期處於低水位的情況下,流量突然增加時,直接把系統拉昇到高水位可能瞬間把系統壓垮。

通過"冷啓動",讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮的情況。

  • CONTROLBEHAVIORRATE_LIMITER

這種方式是:慢啓動,又稱爲 勻速器模式。這種方式嚴格控制了請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶算法。

這種方式主要用於處理間隔性突發的流量,例如消息隊列。想象一下這樣的場景,在某一秒有大量的請求到來,而接下來的幾秒則處於空閒狀態,我們希望系統能夠在接下來的空閒期間逐漸處理這些請求,而不是在第一秒直接拒絕多餘的請求。

具體的 FlowRule 可以用下面這張圖表示:

在這裏插入圖片描述
規則定義好了之後,啓動應用後,就會自動對我們的業務代碼進行保護了,當然實際生產環境中不可能通過硬編碼的方式來定義規則的,sentinel 爲我們提供了 DataSource 接口,通過實現該接口可以自定義規則的存儲數據源。

通過 DataSource 接口可以有很多種方式對規則進行持久化,例如:

  • 整合動態配置系統,如 ZooKeeper、Nacos 等,動態地實時刷新配置規則
  • 結合 RDBMS、NoSQL、VCS 等來實現該規則
  • 配合 Sentinel Dashboard 使用

本篇文章不對規則的持久化做具體的介紹,本篇文章主要是實現一個簡單的限流的例子的接入。

PS:DateSource 接口在後期已經被拆成 ReadableDataSource 和 WritableDataSource 接口了。

4. 檢查效果

Demo 運行之後,我們可以在日誌 ~/logs/csp/${appName}-metrics.log.xxx 裏看到下面的輸出:

|--timestamp-|------date time----|--resource-|p |block|s |e|rt
1529998904000|2018-06-26 15:41:44|hello world|20|0    |20|0|0
1529998905000|2018-06-26 15:41:45|hello world|20|5579 |20|0|728
1529998906000|2018-06-26 15:41:46|hello world|20|15698|20|0|0
1529998907000|2018-06-26 15:41:47|hello world|20|19262|20|0|0
1529998908000|2018-06-26 15:41:48|hello world|20|19502|20|0|0
1529998909000|2018-06-26 15:41:49|hello world|20|18386|20|0|0

可以看到我們請求了很多次該資源後,sentinel 把每秒的統計信息都打印出來了,用 | 來分隔不同的參數,一共有8個參數,從左至右分別是:
在這裏插入圖片描述

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