1. 程式人生 > 實用技巧 >熱點引數的流量控制

熱點引數的流量控制

概述

何為熱點?熱點即經常訪問的資料。很多時候我們希望統計某個熱點資料中訪問頻次最高的 Top K 資料,並對其訪問進行限制。比如:

  • 商品 ID 為引數,統計一段時間內最常購買的商品 ID 並進行限制
  • 使用者 ID 為引數,針對一段時間內頻繁訪問的使用者 ID 進行限制

熱點引數限流會統計傳入引數中的熱點引數,並根據配置的限流閾值與模式,對包含熱點引數的資源呼叫進行限流。熱點引數限流可以看做是一種特殊的流量控制,僅對包含熱點引數的資源呼叫生效。

Sentinel 利用 LRU 策略統計最近最常訪問的熱點引數,結合令牌桶演算法來進行引數級別的流控。

基本使用

要使用熱點引數限流功能,需要引入以下依賴:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-parameter-flow-control</artifactId>
    <version>x.y.z</version>
</dependency>

然後為對應的資源配置熱點引數限流規則,並在 entry 的時候傳入相應的引數,即可使熱點引數限流生效。
注:若自行擴充套件並註冊了自己實現的 SlotChainBuilder,並希望使用熱點引數限流功能,則可以在 chain 裡面合適的地方插入 ParamFlowSlot。

那麼如何傳入對應的引數以便 Sentinel 統計呢?我們可以通過 SphU 類裡面幾個 entry 過載方法來傳入:

public static Entry entry(String name, EntryType type, int count, Object... args) throws BlockException
public static Entry entry(Method method, EntryType type, int count, Object... args) throws BlockException

其中最後的一串 args 就是要傳入的引數,有多個就按照次序依次傳入。比如要傳入兩個引數 paramA 和 paramB,則可以:

// paramA in index 0, paramB in index 1.
// 若需要配置例外項或者使用叢集維度流控,則傳入的引數只支援基本型別。
SphU.entry(resourceName, EntryType.IN, 1, paramA, paramB);

注意:若 entry 的時候傳入了熱點引數,那麼 exit 的時候也一定要帶上對應的引數(exit(count, args)),否則可能會有統計錯誤。正確的示例:

Entry entry = null;
try {
    entry = SphU.entry(resourceName, EntryType.IN, 1, paramA, paramB);
    // Your logic here.
} catch (BlockException ex) {
    // Handle request rejection.
} finally {
    if (entry != null) {
        entry.exit(1, paramA, paramB);
    }
}

對於 @SentinelResource 註解方式定義的資源,若註解作用的方法上有引數,Sentinel 會將它們作為引數傳入 SphU.entry(res, args)。比如以下的方法裡面 uid 和 type 會分別作為第一個和第二個引數傳入 Sentinel API,從而可以用於熱點規則判斷:

@SentinelResource("myMethod")
public Result doSomething(String uid, int type) {
  // some logic here...
}

熱點引數規則

熱點引數規則(ParamFlowRule)類似於流量控制規則(FlowRule):
屬性 說明 預設值

屬性說明預設值
resource 資源名,必填
count 限流閾值,必填
grade 限流模式 QPS 模式
durationInSec 統計視窗時間長度(單位為秒),1.6.0 版本開始支援 1s
controlBehavior 流控效果(支援快速失敗和勻速排隊模式),1.6.0 版本開始支援
maxQueueingTimeMs 最大排隊等待時長(僅在勻速排隊模式生效),1.6.0 版本開始支援 0ms
paramIdx 熱點引數的索引,必填,對應 SphU.entry(xxx, args) 中的引數索引位置
paramFlowItemList 引數例外項,可以針對指定的引數值單獨設定限流閾值,不受前面 count 閾值的限制。僅支援基本型別和字串型別
clusterMode 是否是叢集引數流控規則 false
clusterConfig 叢集流控相關配置

我們可以通過 ParamFlowRuleManager 的 loadRules 方法更新熱點引數規則,下面是一個熱點流控規則:

ParamFlowRule rule = new ParamFlowRule(resourceName)
    .setParamIdx(0)
    .setCount(5);
// 針對 int 型別的引數 PARAM_B,單獨設定限流 QPS 閾值為 10,而不是全域性的閾值 5.
ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
    .setClassType(int.class.getName())
    .setCount(10);
rule.setParamFlowItemList(Collections.singletonList(item));

ParamFlowRuleManager.loadRules(Collections.singletonList(rule));

示例
示例可參見sentinel-demo-parameter-flow-control

概述

何為熱點?熱點即經常訪問的資料。很多時候我們希望統計某個熱點資料中訪問頻次最高的 Top K 資料,並對其訪問進行限制。比如:

  • 商品 ID 為引數,統計一段時間內最常購買的商品 ID 並進行限制
  • 使用者 ID 為引數,針對一段時間內頻繁訪問的使用者 ID 進行限制

熱點引數限流會統計傳入引數中的熱點引數,並根據配置的限流閾值與模式,對包含熱點引數的資源呼叫進行限流。熱點引數限流可以看做是一種特殊的流量控制,僅對包含熱點引數的資源呼叫生效。

Sentinel 利用 LRU 策略統計最近最常訪問的熱點引數,結合令牌桶演算法來進行引數級別的流控。

基本使用

要使用熱點引數限流功能,需要引入以下依賴:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-parameter-flow-control</artifactId>
    <version>x.y.z</version>
</dependency>

然後為對應的資源配置熱點引數限流規則,並在 entry 的時候傳入相應的引數,即可使熱點引數限流生效。
注:若自行擴充套件並註冊了自己實現的 SlotChainBuilder,並希望使用熱點引數限流功能,則可以在 chain 裡面合適的地方插入 ParamFlowSlot。
那麼如何傳入對應的引數以便 Sentinel 統計呢?我們可以通過 SphU 類裡面幾個 entry 過載方法來傳入:

public static Entry entry(String name, EntryType type, int count, Object... args) throws BlockException
public static Entry entry(Method method, EntryType type, int count, Object... args) throws BlockException

其中最後的一串 args 就是要傳入的引數,有多個就按照次序依次傳入。比如要傳入兩個引數 paramA 和 paramB,則可以:

// paramA in index 0, paramB in index 1.
// 若需要配置例外項或者使用叢集維度流控,則傳入的引數只支援基本型別。
SphU.entry(resourceName, EntryType.IN, 1, paramA, paramB);

注意:若 entry 的時候傳入了熱點引數,那麼 exit 的時候也一定要帶上對應的引數(exit(count, args)),否則可能會有統計錯誤。正確的示例:

Entry entry = null;
try {
    entry = SphU.entry(resourceName, EntryType.IN, 1, paramA, paramB);
    // Your logic here.
} catch (BlockException ex) {
    // Handle request rejection.
} finally {
    if (entry != null) {
        entry.exit(1, paramA, paramB);
    }
}

對於 @SentinelResource 註解方式定義的資源,若註解作用的方法上有引數,Sentinel 會將它們作為引數傳入 SphU.entry(res, args)。比如以下的方法裡面 uid 和 type 會分別作為第一個和第二個引數傳入 Sentinel API,從而可以用於熱點規則判斷:

@SentinelResource("myMethod")
public Result doSomething(String uid, int type) {
  // some logic here...
}

熱點引數規則

熱點引數規則(ParamFlowRule)類似於流量控制規則(FlowRule):
屬性 說明 預設值

屬性說明預設值
resource 資源名,必填
count 限流閾值,必填
grade 限流模式 QPS 模式
durationInSec 統計視窗時間長度(單位為秒),1.6.0 版本開始支援 1s
controlBehavior 流控效果(支援快速失敗和勻速排隊模式),1.6.0 版本開始支援
maxQueueingTimeMs 最大排隊等待時長(僅在勻速排隊模式生效),1.6.0 版本開始支援 0ms
paramIdx 熱點引數的索引,必填,對應 SphU.entry(xxx, args) 中的引數索引位置
paramFlowItemList 引數例外項,可以針對指定的引數值單獨設定限流閾值,不受前面 count 閾值的限制。僅支援基本型別和字串型別
clusterMode 是否是叢集引數流控規則 false
clusterConfig 叢集流控相關配置

我們可以通過 ParamFlowRuleManager 的 loadRules 方法更新熱點引數規則,下面是一個熱點流控規則:

ParamFlowRule rule = new ParamFlowRule(resourceName)
    .setParamIdx(0)
    .setCount(5);
// 針對 int 型別的引數 PARAM_B,單獨設定限流 QPS 閾值為 10,而不是全域性的閾值 5.
ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
    .setClassType(int.class.getName())
    .setCount(10);
rule.setParamFlowItemList(Collections.singletonList(item));

ParamFlowRuleManager.loadRules(Collections.singletonList(rule));

示例
示例可參見sentinel-demo-parameter-flow-control

輸出結果:

下一節
1-7 附:流量控制(flow control)文件說明

播放下一節 重新觀看 章節問答課籤筆記資料 階段一 單體電商專案架構,開發與上線(1~5周) 階段二 從單體到高可用叢集演進(6-8周) 階段三 分散式架構-逐個擊破分散式核心問題(9-17周) 階段四 基於SpringCloud改造微服務(18-25周) ·微服務架構認知、服務治理-Eureka ·負載均衡、服務通訊與呼叫 ·服務容錯-Hystrix ·分散式配置中心-Config ·訊息匯流排、服務閘道器 ·服務呼叫鏈追蹤、訊息驅動 ·微服務下Sentinel流量防控衛兵

第1章 Sentinel流量防控衛兵急速入門與進階提升

第2章 Sentinel 生產環境應用與持久化規則實戰

·服務治理的另一條路 - Dubbo 階段五 服務容器化-Docker與K8S(26-30周) 階段六 高效能網路通訊-Netty與效能調優(31~40周)