字節(jié)二面:Sentinel 是如何實(shí)現(xiàn)限流的?
合理的限流策略是保障系統(tǒng)穩(wěn)定運(yùn)行的關(guān)鍵,這篇文章,我們來分析一個(gè)在微服務(wù)架構(gòu)中廣受歡迎的流量控制組件:Sentinel。

一、什么是 Sentinel?
簡(jiǎn)單來說,Sentinel 是阿里巴巴開源的一個(gè)流量控制組件,用于防止系統(tǒng)過載,保障服務(wù)的穩(wěn)定性和可用性。它不僅支持限流,還具備熔斷、降級(jí)、系統(tǒng)負(fù)載保護(hù)等多種功能,非常適合微服務(wù)架構(gòu)下的復(fù)雜需求。
比如,你的電商平臺(tái)在“雙十一”期間,面對(duì)巨大的訪問量,Sentinel 可以幫你合理分配流量,防止某個(gè)服務(wù)因壓力過大而崩潰。
二、基本原理
要了解 Sentinel 的限流原理,首先得明白 限流 是什么。簡(jiǎn)單來說,限流是控制流量的大小,防止系統(tǒng)因請(qǐng)求過多而崩潰。常見的限流策略有以下幾種:
- QPS(每秒查詢數(shù))限流:限制單位時(shí)間內(nèi)的請(qǐng)求數(shù)。
- 線程數(shù)限流:限制處理請(qǐng)求的線程數(shù)。
- 熱點(diǎn)參數(shù)限流:對(duì)特定參數(shù)的請(qǐng)求進(jìn)行限流。
- 關(guān)聯(lián)限流:根據(jù)多條規(guī)則進(jìn)行綜合限流。
- 預(yù)留規(guī)則:為關(guān)鍵業(yè)務(wù)預(yù)留一定的資源。
其中,令牌桶(Token Bucket) 和 漏桶(Leaky Bucket) 是兩種常見的限流算法。Sentinel 主要采用令牌桶算法,通過生成固定速率的令牌,控制請(qǐng)求的流入。
想象一下,令牌桶就像一個(gè)隔離閥,水管(請(qǐng)求)進(jìn)入時(shí),必須先獲取一個(gè)水龍頭(令牌)的開關(guān)。沒有令牌,就暫時(shí)不讓水(請(qǐng)求)流過。
三、實(shí)現(xiàn)機(jī)制
1. 核心組件
Sentinel 的限流機(jī)制主要由以下幾個(gè)核心組件組成:
- 資源(Resource):被保護(hù)的資源,比如 HTTP 接口、方法等。
- 規(guī)則(Rule):定義對(duì)資源的限流方式和閾值。
- 攔截器(Interceptor):在請(qǐng)求進(jìn)入資源之前,進(jìn)行流量控制判斷。
2. 流量統(tǒng)計(jì)與動(dòng)態(tài)判斷
Sentinel 會(huì)實(shí)時(shí)統(tǒng)計(jì)每個(gè)資源的請(qǐng)求情況,并根據(jù)預(yù)設(shè)的規(guī)則動(dòng)態(tài)判斷是否允許請(qǐng)求通過。當(dāng)請(qǐng)求到達(dá)時(shí),攔截器會(huì):
- 檢查當(dāng)前時(shí)間窗口內(nèi)請(qǐng)求數(shù)是否超出限流閾值。
- 如果未超出,允許請(qǐng)求執(zhí)行,并記錄相應(yīng)的統(tǒng)計(jì)信息。
- 如果超出,拒絕請(qǐng)求,并返回相應(yīng)的錯(cuò)誤信息。
這個(gè)過程幾乎是實(shí)時(shí)且高效的,確保系統(tǒng)在高并發(fā)情況下依然能夠穩(wěn)定運(yùn)行。
四、示例演示
為了更好地理解 Sentinel 的工作原理,接下來,通過一個(gè)簡(jiǎn)單的 Java 示例,來演示如何使用 Sentinel 進(jìn)行限流。
1. 準(zhǔn)備環(huán)境
首先,確保你已經(jīng)搭建好了一個(gè)基本的 Java 項(xiàng)目,并引入了 Sentinel 依賴??梢栽?nbsp;pom.xml 中添加:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.4</version>
</dependency>2. 編寫限流代碼
下面是一個(gè)簡(jiǎn)單的示例,展示如何為一個(gè)資源設(shè)置 QPS 限流規(guī)則,并進(jìn)行流量控制。
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import java.util.Collections;
publicclass SentinelDemo {
// 定義資源名稱
privatestaticfinal String RESOURCE_NAME = "resource";
public static void main(String[] args) {
// 初始化限流規(guī)則
initFlowRules();
// 模擬高并發(fā)請(qǐng)求
for (int i = 0; i < 20; i++) {
new Thread(() -> {
try (Entry entry = SphU.entry(RESOURCE_NAME)) {
// 資源訪問邏輯
System.out.println("資源訪問成功: " + Thread.currentThread().getName());
} catch (BlockException ex) {
// 資源被限流
System.out.println("資源被限流: " + Thread.currentThread().getName());
}
}).start();
}
}
private static void initFlowRules() {
FlowRule rule = new FlowRule();
rule.setResource(RESOURCE_NAME);
rule.setGrade(com.alibaba.csp.sentinel.slots.block.RuleConstant.FLOW_GRADE_QPS);
rule.setCount(5); // 設(shè)置 QPS 閾值為5
FlowRuleManager.loadRules(Collections.singletonList(rule));
}
}3. 運(yùn)行與測(cè)試
運(yùn)行上述代碼,你會(huì)看到類似如下的輸出:
資源訪問成功: Thread-0
資源訪問成功: Thread-1
資源訪問成功: Thread-2
資源訪問成功: Thread-3
資源訪問成功: Thread-4
資源被限流: Thread-5
資源被限流: Thread-6
...這里,我們?cè)O(shè)置了 QPS 閾值為 5,當(dāng)并發(fā)請(qǐng)求超過這個(gè)值時(shí),多余的請(qǐng)求會(huì)被 限流,即被拒絕。這有助于保護(hù)系統(tǒng)不被突發(fā)的高流量沖擊。
Sentinel 的功能遠(yuǎn)不止于簡(jiǎn)單的限流,它還支持 熔斷降級(jí)、系統(tǒng)負(fù)載保護(hù)、豐富的規(guī)則配置等等。比如,在服務(wù)出現(xiàn)異常時(shí),Sentinel 可以自動(dòng)觸發(fā)熔斷,暫時(shí)關(guān)閉對(duì)該服務(wù)的訪問,給予系統(tǒng)恢復(fù)的時(shí)間。
此外,Sentinel 提供了豐富的監(jiān)控和管理界面,方便開發(fā)者實(shí)時(shí)查看系統(tǒng)狀態(tài),并動(dòng)態(tài)調(diào)整規(guī)則。
五、總結(jié)
本文,我們分析了 Sentinel 是如何實(shí)現(xiàn)限流的以及了解了它的基本原理,并通過一個(gè)簡(jiǎn)單的示例演示了 Sentinel 是如何實(shí)現(xiàn)限流的。從基本原理到實(shí)際代碼,再到更深入的功能拓展,希望這篇文章能幫助大家更好地理解和應(yīng)用 Sentinel。

































