Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景java
本文介紹阿里開源限流熔斷方案Sentinel功能、原理、架構、快速入門以及相關框架比較linux
服務限流 :當系統資源不夠,不足以應對大量請求,對系統按照預設的規則進行流量限制或功能限制git
服務熔斷:當調用目標服務的請求和調用大量超時或失敗,服務調用方爲避免形成長時間的阻塞形成影響其餘服務,後續對該服務接口的調用再也不通過進行請求,直接執行本地的默認方法github
服務降級:爲了保證核心業務在大量請求下能正常運行,根據實際業務狀況及流量,對部分服務下降優先級,有策略的不處理或用簡單的方式處理spring
服務降級的實現能夠基於人工開關降級(秒殺、電商大促等)和自動檢測(超時、失敗次數、故障),熔斷能夠理解爲一種服務故障降級處理bash
系統承載的訪問量是有限的,若是不作流量控制,會致使系統資源佔滿,服務超時,從而全部用戶沒法使用,經過服務限流控制請求的量,服務降級省掉非核心業務對系統資源的佔用,最大化利用系統資源,儘量服務更多用戶架構
Sentinel: 分佈式系統的流量防衛兵,是阿里中間件團隊2018年7月開源的,面向分佈式服務架構的輕量級流量控制產品,主要以流量爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度來保護系統服務的穩定性併發
Sentinel 的開源生態:app
Sentinel 具備如下特徵:框架
豐富的應用場景:秒殺限流,消息削峯填谷、集羣流量控制、實時熔斷下游不可用應用等
完備的實時監控:Sentinel 同時提供實時的監控功能。能夠在控制檯中看到接入應用的單臺機器秒級數據,甚至 500 臺如下規模的集羣的彙總運行狀況
普遍的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。只須要引入相應的依賴並進行簡單的配置便可快速地接入 Sentinel
完善的 SPI 擴展點:Sentinel 提供簡單易用、完善的 SPI 擴展接口。能夠經過實現擴展接口來快速地定製邏輯。例如定製規則管理、適配動態數據源等
Sentinel 分爲兩個部分:
控制檯(Dashboard) 基於 Spring Boot 開發,打包後能夠直接運行,不須要額外的 Tomcat 等應用容器
核心庫(Java 客戶端) 不依賴任何框架/庫,可以運行於全部 Java 運行時環境,同時對 Dubbo / Spring Cloud 等框架也有較好的支持
實時監控 支持自動發現集羣機器列表、服務健康狀態、服務調用經過/拒絕QPS、調用耗時、圖表統計
規則管理及推送 支持在界面配置流控、降級、熱點規則,並實時推送
鑑權 控制檯支持自定義鑑權接口,提供基本登陸功能
針對指定應用實例的流量控制,監控應用流量QPS或併發線程數,當達到指定的閾值時對流量進行控制,以免被瞬時的流量高峯沖垮,從而保障應用的高可用性
流量控制的手段包括:
不一樣於應用流控根據單個應用實例閾值執行限流檢查,集羣流控只對整個集羣調用總量進行限流,例如如下場景:
僅靠單機維度去限制的話會沒法精確地限制整體流量,經過集羣精確地控制整個集羣的調用總量,結合單機限流兜底,能夠更好地發揮流量控制的效果
Sentinel 支持對 Spring Cloud Gateway、Zuul 等主流的 API Gateway 進行限流
網關流控針對 API網關的場景定製的限流規則,能夠針對不一樣 route 或自定義的 API 分組進行限流,支持針對請求中的路徑、參數、Header、來源 IP 等進行定製化的限流
若是調用鏈路中的某個資源不穩定,最終會致使請求發生堆積,經過熔斷降級能在調用鏈路中某個資源出現不穩定狀態時(包括調用超時、異常比例升高、異常數升高),對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而致使級聯錯誤
當資源被降級後,在接下來的降級時間窗口以內,對該資源的調用都自動熔斷(默認行爲是拋出 DegradeException),通過時間窗口以後,退出熔斷,並在下一次資源出現不穩定狀態再次自動熔斷
參數限流 熱點即常常訪問的數據,熱點參數限流會統計傳入參數中的熱點參數,並根據配置的限流閾值與模式,對包含熱點參數的資源調用進行限流 例如如下場景:
爲了解決傳統方案:基於操做系統負載(load1,linux下用uptime查看)作進行自適應限流,帶來的存在延時、系統性能恢復慢的問題,Sentinel採用新的思路:根據系統可以處理的請求,和容許進來的請求,來作平衡,而不是根據一個間接的指標(系統 load)來作限流
目標在於:在系統不被拖垮的狀況下,儘量提升系統的吞吐率,而不是 負載 必定要到低於某個閾值
系統保護規則是從應用級別的入口流量進行控制,從單臺機器的整體 Load、RT、入口 QPS 和線程數四個維度監控應用數據,當實際運行達到限定閾值進行限流保護,支持的閾值類型:
Sentinel黑白名單根據資源的請求來源(origin)限制資源是否經過,若配置白名單則只有請求來源位於白名單內時纔可經過;若配置黑名單則請求來源位於黑名單時不經過,其他的請求經過
從github release頁面(github.com/alibaba/Sen…)下載最新控制檯jar包
命令行啓動控制檯:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
複製代碼
Sentinel適配了常見主流框架,包括Dubbo、Spring Boot、Spring WebFlux、gRPC、Zuul、Spring Cloud Gateway、RocketMQ、Web Servlet,對於須要限流的資源,支持用原生Java的try-catch 接入或者使用註解
下面以常見的Spring Boot註解的方式做爲示例: 引入sentinel適配Spring Cloud的依賴:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
複製代碼
application.yml指定控制檯地址:
spring:
cloud:
sentinel:
transport:
dashboard: IP:端口號
複製代碼
定義須要限流的資源:
@RestController
public class TestController {
@GetMapping(value = "/hello")
// 定義須要限流的資源名稱爲hello
@SentinelResource("hello")
public String hello() {
return "Hello Sentinel";
}
}
複製代碼
請求一次上面的http hello接口後,觸發Sentinel客戶端初始化,才能在控制檯看到接口
添加流控規則:
頻繁請求接口,能夠看到部分請求被拒絕:
注意:上面的配置方式是沒有作持久化的,生產環境不建議使用
Sentinel 提供 動態規則數據源 支持來動態地管理、讀取配置的規則。Sentinel 提供的 ReadableDataSource 和 WritableDataSource 接口簡單易用,很是方便使用。
Sentinel 動態規則源針對常見的配置中心和遠程存儲進行適配,目前已支持 Nacos、ZooKeeper、Apollo、Redis 等多種動態規則源,能夠覆蓋到不少的生產場景
下面介紹Sentinel客戶端基本原理
Resource 資源 Sentinel中,須要被流量保護的方法、代碼塊均可以稱爲資源,每一個資源都須要定義一個惟一的資源名詞,用於匹配相關規則
Entry Sentinel功能入口類,Entry 能夠經過對主流框架的適配自動建立,也能夠經過註解的方式或調用 SphU API 顯式建立,建立後執行資源和規則匹配和校驗
Slot 功能插槽,由Enty類建立,每一個資源對應一系列Slot,Slot實現資源信息收集、規則匹配、校驗的,多個Slot經過組成Slot Chain,在進入資源和退出資源時分別基於責任鏈模式調用entry()和exit()方法
String resourceName = "resourceName";
Entry entry = null;
try {
entry = SphU.entry(resourceName);
System.out.println("resource running");
} catch (BlockException e) {
// 限流
throw e;
} catch (Throwable e) {
e.printStackTrace();
throw e;
} finally {
if (entry != null) {
entry.exit();
}
}
複製代碼
主要流程以下:
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔離策略 | 信號量隔離(併發線程數限流) | 線程池隔離/信號量隔離 | 信號量隔離 |
熔斷降級策略 | 基於響應時間、異常比率、異常數 | 基於異常比率 | 基於異常比率、響應時間 |
實時統計實現 | 滑動窗口(LeapArray) | 滑動窗口(基於 RxJava) | Ring Bit Buffer |
動態規則配置 | 支持多種數據源 | 支持多種數據源 | 有限支持 |
擴展性 | 多個擴展點 | 插件的形式 | 接口的形式 |
基於註解的支持 | 支持 | 支持 | 支持 |
限流 | 基於 QPS,支持基於調用關係的限流 | 有限的支持 | Rate Limiter |
流量整形 | 支持預熱模式、勻速器模式、預熱排隊模式 | 不支持 | 簡單的 Rate Limiter 模式 |
系統自適應保護 | 支持 | 不支持 | 不支持 |
控制檯 | 提供開箱即用的控制檯,可配置規則、查看秒級監控、機器發現等 | 簡單的監控查看 | 不提供控制檯,可對接其它監控系統 |
值得補充的是:相比Hystrix基於線程池隔離進行限流,這種方案雖然隔離性比較好,可是代價就是線程數目太多,線程上下文切換的 overhead 比較大,特別是對低延時的調用有比較大的影響。
Sentinel 併發線程數限流不負責建立和管理線程池,而是簡單統計當前請求上下文的線程數目,若是超出閾值,新的請求會被當即拒絕,效果相似於信號量隔離
《Sentinel官方文檔》
《從 Hystrix 遷移到 Sentinel》