Sentinel 簡介 Sentinel 是阿裡中間件團隊開源的,面向分散式服務架構的高可用流量防護組件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護、熱點防護等多個維度來幫助開發者保障微服務的穩定性 Sentinel 提供了兩個服務組件: Sentinel 用來實現微服務系統中服務 ...
Sentinel 簡介
Sentinel 是阿裡中間件團隊開源的,面向分散式服務架構的高可用流量防護組件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護、熱點防護等多個維度來幫助開發者保障微服務的穩定性
Sentinel 提供了兩個服務組件:
- Sentinel 用來實現微服務系統中服務熔斷、降級等功能
- Sentinel Dashboard 用來監控微服務系統中流量調用等情況
限流演算法
限流的方式有很多,常用的有計數器、漏桶和令牌桶等
1. 計數器
採用計數器是一種比較簡單的限流演算法,一般會限制一秒鐘能夠通過的請求數。比如限流 QPS 為 100,演算法的實現思路就是從第一個請求進來開始計時,在接下來的 1 秒內每來一個請求就把計數加 1,如果累加的數字達到了 100,後續的請求就會被全部拒絕。等到 1 秒結束後,把計數恢覆成 0,重新開始計數。如果在單位時間 1 秒內的前 10 毫秒處理了 100 個請求,那麼後面的 990 毫秒會請求拒絕所有的請求,我們把這種現象稱為突刺現象
2. 漏桶演算法
漏桶演算法的思路很簡單,一個固定容量的漏桶按照常量固定速率流出水滴。如果桶是空的,就不需要流出水滴。我們可以按照任意速率流入水滴到漏桶。如果流入的水滴超出了桶的容量,流入的水滴就會溢出(被丟棄),而漏桶容量是不變的。漏桶演算法提供了一種機制,通過它可以讓突發流量被整形,以便為網路提供穩定的流量
3. 令牌桶演算法
令牌桶演算法是比較常見的限流演算法之一,可以使用它進行介面限流。令牌按固定的速率被放入令牌桶中,當桶裝滿時,新添加的令牌會被丟棄或拒絕。當請求到達時,將從桶中刪除 1 個令牌。令牌桶中的令牌不僅可以被移除,還可以往裡添加,所以為了保證介面隨時有數據通過,必須不停地往桶裡加令牌。由此可見,往桶裡加令牌的速度決定了數據通過介面的速度。我們通過控制往令牌桶裡加令牌的速度來控制介面的流量
4. 漏桶演算法和令牌桶演算法的區別
- 漏桶演算法是按照常量固定選率流出請求的,流入請求速率任意,當流入的請求數累積到漏桶容量時,新流入的請求被拒絕
- 令牌桶演算法是按照固定速率往桶中添加令牌的,請求是否被處理需要看桶中的令牌是否足夠,當令牌數減為零時,拒絕新的請求
- 令牌桶演算法允許突發請求,只要有令牌就可以處理,允許一定程度的突發流量
- 漏桶演算法限制的是常量流出速率,從而使突發流入速率平滑
Sentinel Dashboard
Sentinel 提供一個輕量級的開源控制台,包含如下功能:
- 查看機器列表以及健康情況:收集 Sentinel 客戶端發送的心跳包,用於判斷機器是否線上
- 監控(單機和集群):通過 Sentinel 客戶端暴露的監控 API,定期拉取並且聚合應用監控信息,最終可以實現秒級的實時監控
- 規則管理和推送:統一管理推送規則
- 鑒權:在生產環境中,鑒權非常重要,這裡每個開發者需要根據自己的實際情況進行定製
從 GitHub 可以下載 Sentinel 安裝包:https://github.com/alibaba/Sentinel/
下載得到的是一個 jar 包(sentinel-dashboard-1.8.6.jar),可以直接通過 Java 命令啟動,如 java -jar 方式運行,預設埠為 8080,通過 http://localhost:8080/ 訪問,用戶名和密碼預設是 sentinel
客戶端接入控制台
引入依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置文件配置如下:
spring:
cloud:
sentinel:
transport:
port: 18000 # 指定應用與sentinel控制台交互的埠
dashboard: localhost:8080 # sentinel後臺地址
eager: true # 開啟sentinel,預設開啟
Sentinel 限流
Sentinel 流量控制的原理是監控應用流量的 QPS 或併發線程數等指標,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰衝垮,從而保障應用的高可用性
使用註解方式實現限流如下:
@Slf4j
@RestController
public class TestCon {
@GetMapping("/test/byResource")
@SentinelResource(value = "byResource", blockHandler = "handleException")
public void byResource() {
log.info("按資源名稱限流");
}
public void handleException(BlockException exception) {
log.error("觸發失敗回調方法", exception);
}
}
@SentinelResource
註解用於定義資源,可選屬性如下:
-
value:指定資源名稱
-
blockHandler / blockHandlerClass:指定處理 BlockExccption 異常函數名稱。函數要求必須是 public,返回類型與原方法必須一致,函數參數類型需要和原方法相匹配併在最後加 BlockException 類型的參數,函數預設和原方法在同一個類中。若希望使用其他類的函數可配置 blockHandlerClass,並指定 blockHandlerClass 裡面的方法,註意對應的函數必需為 static 函數,否則無法解析
// TestCon.java @GetMapping("/test/byResource") @SentinelResource(value = "byResource", blockHandler="handleBolckForTest", blockHandlerClass={BlockHandlerClassTest}) public void byResource() { log.info("按資源名稱限流"); } // BlockHandlerClassTest.java public static String handleBolckForTest(String name,int age, BlockException exception){ xxxxx }
-
fallback / fallbackClass:用於在拋出異常的時候提供 fallback 處理邏輯,可以針對所有類型的異常(除了 exceptionsToIgnore 裡面排除掉的異常類型)進行處理,返回值類型必須與原函數返回值類型一致,方法參數列表需要和原函數一致,或者可以額外多一個 Throwable 類型的參數用於接收對應的異常,fallback 函數預設需要和原方法在同一個類中,若希望使用其他類的函數,則可以指定 fallbackClass 為對應的類的 Class 對象,註意對應的函數必需為 static 函數,否則無法解析
在 Sentinel 控制台的流控規則中,新增流控規則,如圖:
- 資源名:需要和
@SentineResource
註解的 value 屬性值保持一致 - 針對來源:預設 default,表示對所有來源進行限流,有時候我們會希望根據上級微服務或者請求來源進行限流,可以根據自身的需求進行相應的配置
- 閾值類型:Sentinel 限流策略有兩種統計類型,一種是統計併發線程數,另一種是統計 QPS
- 當 QPS 超過某個閾值的時候,採取措施進行流量控制,包括:
- 直接拒絕:預設的流量控制方式,當 QPS 超過任意規則的閾值,新的請求會被立即拒絕並拋出 FlowExccption
- Warm Up:預熱/冷啟動方式,在系統長期處於低水位的情況下,當流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮,通過冷啟動讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮
- 勻速排隊:嚴格控制請求通過的間隔時間,即讓請求以均勻的速度通過,對應的是漏桶演算法
- 當 QPS 超過某個閾值的時候,採取措施進行流量控制,包括:
- 流控模式:
- 直接:介面達到限流條件時,開啟限流
- 關聯:當指定介面關聯的介面達到限流條件時,開啟對指定介面開啟限流,舉例:設置關聯資源為 byResource2,那麼當 byResource2 達到限流條件時,byResource 將不可用
- 鏈路:當從某個介面過來的資源達到限流條件時,開啟限流,舉例:有兩個介面 getResource1 和 getResource2 能調用 byResource 資源,如果設置了 getResource1 並達到限流條件,那麼將無法再通過 getResource1 調用 byResource,而 getResource2 不受影響