前言
在
從0到1建構分布式秒殺系統和
打造十萬博文系統中,限流是不可缺少的一個環節,在系統能承受的範圍内既能減少資源開銷又能防禦惡意攻擊。
在前面的文章中,我們使用了開源工具包 Guava 提供的限流工具類 RateLimiter 和 OpenResty 的 Lua 腳本分别進行 API 和應用層面的限流。今天,我們來聊聊阿裡開源的分布式系統的流量防衛兵 Sentinel。
Sentinel 是什麼?
随着微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel 以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個次元保護服務的穩定性。
Sentinel 具有以下特征:
- 豐富的應用場景:Sentinel 承接了阿裡巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峰填谷、叢集流量控制、實時熔斷下遊不可用應用等。
- 完備的實時監控:Sentinel 同時提供實時的監控功能。您可以在控制台中看到接入應用的單台機器秒級資料,甚至 500 台以下規模的叢集的彙總運作情況。
- 廣泛的開源生态:Sentinel 提供開箱即用的與其它開源架構/庫的整合子產品,例如與 Spring Cloud、Dubbo、gRPC 的整合。您隻需要引入相應的依賴并進行簡單的配置即可快速地接入 Sentinel。
- 完善的 SPI 擴充點:Sentinel 提供簡單易用、完善的 SPI 擴充接口。您可以通過實作擴充接口來快速地定制邏輯。例如定制規則管理、适配動态資料源等。
Sentinel 的主要特性:

Sentinel 的開源生态:
Sentinel 分為兩個部分:
- 核心庫(Java 用戶端)不依賴任何架構/庫,能夠運作于所有 Java 運作時環境,同時對 Dubbo / Spring Cloud 等架構也有較好的支援。
- 控制台(Dashboard)基于 Spring Boot 開發,打包後可以直接運作,不需要額外的 Tomcat 等應用容器。
控制台配置
Sentinel 控制台最少應該包含如下功能:
- 檢視機器清單以及健康情況:收集 Sentinel 用戶端發送的心跳包,用于判斷機器是否線上。
- 監控 (單機和叢集聚合):通過 Sentinel 用戶端暴露的監控 API,定期拉取并且聚合應用監控資訊,最終可以實作秒級的實時監控。
- 規則管理和推送:統一管理推送規則。
- 鑒權:生産環境中鑒權非常重要。這裡每個開發者需要根據自己的實際情況進行定制。
可以直接從
release 頁面下載下傳最新版本的控制台 jar 包,啟動 Sentinel 控制台需要 JDK 版本為 1.8 及以上版本。。
啟動腳本 sentinel.sh:
#!/bin/bash
java -Dsentinel.dashboard.auth.username=admin \
-Dsentinel.dashboard.auth.password=admin \
-Dserver.port=8084 -Dcsp.sentinel.dashboard.server=localhost:8084 \
-Dproject.name=sentinel-dashboard \
-jar sentinel-dashboard-1.6.3.jar &
使用者可以通過如下參數進行配置:
-
用于指定控制台的登入使用者名為 admin;-Dsentinel.dashboard.auth.username=admin
-
用于指定控制台的登入密碼為 admin;如果省略這兩個參數,預設使用者和密碼均為 sentinel;-Dsentinel.dashboard.auth.password=admin
-
用于指定 Spring Boot 服務端 session 的過期時間,如 7200 表示 7200 秒;60m 表示 60 分鐘,預設為 30 分鐘;-Dserver.servlet.session.timeout=7200
用戶端配置
pom.xml 引入以下依賴:
<!-- https://blog.52itstyle.vip -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<!--注意跟 SpringBoot 保持一緻 2.1.x for Spring Boot 2.1.x-->
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
配置檔案:
# 應用名稱 https://blog.52itstyle.vip
spring.application.name=blog
spring.cloud.sentinel.transport.port=8720
# 測試請替換為自己的位址
spring.cloud.sentinel.transport.dashboard=116.190.247.112:8084
這裡的
spring.cloud.sentinel.transport.port
端口配置會在應用對應的機器上啟動一個 Http Server,該 Server 會與 Sentinel 控制台做互動。比如 Sentinel 控制台添加了1個限流規則,會把規則資料 push 給這個 Http Server 接收,Http Server 再将規則注冊到 Sentinel 中。
代碼配置:
/**
* 博文 https://blog.52itstyle.vip
*/
@RequestMapping("{id}.shtml")
@SentinelResource("blogView")
public String page(@PathVariable("id") Long id, ModelMap model) {
try{
Blog blog = blogService.getById(id);
String key = "blog_"+id;
Long views = redisUtil.size(key);
blog.setViews(views+blog.getViews());
model.addAttribute("blog",blog);
} catch (Throwable e) {
return "error/404";
}
return "article";
}
@SentinelResource
注解用來辨別資源是否被限流、降級。上述例子上該注解的屬性
'blogView'
表示資源名。
預設情況,Sentinel 會攔截所有的 Controller 請求,這裡辨別資源名,是因為所有的文章都會走這個請求,為了友善統計和流控,這裡自定義資源辨別。
更多注解支援,請參考:
Sentinel/wiki/注解支援。
通路用戶端項目,随便點選幾個頁面,然後登入 Sentinel 控制台,如果看到以下界面,說明配置成功。
配置限流,搜尋我們剛才配置的資源名稱,選擇流控功能。
輸入門檻值參數,為了測試友善,這裡直接輸入2,連續重新整理浏覽器,如果背景出現以下錯誤,并伴随着前台頁面無法正常顯示說明配置生效。
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null
當然,Sentinel 流程功能不僅僅這麼簡單,還支援叢集模式,在終極版十萬博文中,我們可以為叢集中的節點,設定單機均分,也可以設定一個總體的門檻值。
生産環境中使用
Sentinel 核心庫目前已可用于生産環境,目前除了阿裡巴巴以外,也有多家企業在生産環境中使用它們。
規則管理及推送
原生版本的規則管理通過API 将規則推送至用戶端并直接更新到記憶體中,并不能直接用于生産環境。
不過 Sentinel提供了擴充讀資料源
ReadableDataSource
,規則中心統一推送,用戶端通過注冊監聽器的方式時刻監聽變化,比如使用 Nacos、Zookeeper 等配置中心。這種方式有更好的實時性和一緻性保證。
監控
Sentinel 會記錄資源通路的秒級資料(若沒有通路則不進行記錄)并儲存在本地日志中。Sentinel 控制台可以通過 Sentinel 用戶端預留的 HTTP API 從秒級監控日志中拉取監控資料,并進行聚合。
目前 Sentinel 控制台中監控資料聚合後直接存在記憶體中,未進行持久化,且僅保留最近 5 分鐘的監控資料。若需要監控資料持久化的功能,可以自行擴充實作。
注意事項
由于一開始沒有認真讀文檔,把控制台部署到了外網,而用戶端在内網啟動,導緻用戶端無法被通路到,實時鍊路和簇點鍊路資料無法正常顯示。
測試的小夥伴注意了,原始模式下,用戶端和控制台必須互相被通路到,用戶端會向控制台定時發送心跳請求,控制台會向用戶端推送規則、拉取流控資料并聚合。