扛住阿里雙十一高併發流量,Sentinel是怎麼做到的?
Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景
本文介紹阿里開源限流熔斷方案 Sentinel 功能、原理、架構、快速入門以及相關框架比較
基本介紹
1 名詞解釋
服務限流 :當系統資源不夠,不足以應對大量請求,對系統按照預設的規則進行流量限制或功能限制
服務熔斷:當呼叫目標服務的請求和呼叫大量超時或失敗,服務呼叫方為避免造成長時間的阻塞造成影響其他服務,後續對該服務介面的呼叫不再經過進行請求,直接執行本地的預設方法
服務降級:為了保證核心業務在大量請求下能正常執行,根據實際業務情況及流量,對部分服務降低優先順序,有策略的不處理或用簡單的方式處理
服務降級的實現可以基於人工開關降級(秒殺、電商大促等)和自動檢測(超時、失敗次數、故障),熔斷可以理解為一種服務故障降級處理
2 為什麼需要限流降級
系統承載的訪問量是有限的,如果不做流量控制,會導致系統資源佔滿,服務超時,從而所有使用者無法使用,通過服務限流控制請求的量,服務降級省掉非核心業務對系統資源的佔用,最大化利用系統資源,儘可能服務更多使用者
3 Sentinel 簡介
Sentinel: 分散式系統的流量防衛兵,是阿里中介軟體團隊 2018 年 7 月開源的,面向分散式服務架構的輕量級流量控制產品,主要以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度來保護系統服務的穩定性
Sentinel 的開源生態:
功能特性
1 總體介紹
Sentinel 具有以下特徵:
豐富的應用場景:秒殺限流,訊息削峰填谷、叢集流量控制、實時熔斷下游不可用應用等
完備的實時監控:Sentinel 同時提供實時的監控功能。可以在控制檯中看到接入應用的單臺機器秒級資料,甚至 500 臺以下規模的叢集的彙總執行情況
廣泛的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模組,例如與 Spring Cloud、Dubbo、gRPC 的整合。只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel
完善的 SPI 擴充套件點:Sentinel 提供簡單易用、完善的 SPI 擴充套件介面。可以通過實現擴充套件介面來快速地定製邏輯。例如定製規則管理、適配動態資料來源等
Sentinel 分為兩個部分:
控制檯(Dashboard) 基於 Spring Boot 開發,打包後可以直接執行,不需要額外的 Tomcat 等應用容器
核心庫(Java 客戶端) 不依賴任何框架/庫,能夠執行於所有 Java 執行時環境,同時對 Dubbo / Spring Cloud 等框架也有較好的支援
2 控制檯特性
實時監控 支援自動發現叢集機器列表、服務健康狀態、服務呼叫通過/拒絕 QPS、呼叫耗時、圖表統計
規則管理及推送 支援在介面配置流控、降級、熱點規則,並實時推送
鑑權 控制檯支援自定義鑑權介面,提供基本登入功能
3 核心庫功能特性
(1) 應用流控
針對指定應用例項的流量控制,監控應用流量 QPS 或併發執行緒數,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰沖垮,從而保障應用的高可用性
流量控制的手段包括:
直接拒絕
Warm Up,即預熱/冷啟動方式,讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被瞬間壓垮
勻速排隊,嚴格控制請求通過的間隔時間,讓請求以均勻的速度通過
(2) 叢集流控
不同於應用流控根據單個應用例項閾值執行限流檢查,叢集流控只對整個叢集呼叫總量進行限流,例如以下場景:
限制某個使用者呼叫某個 API 的總 QPS,提供 API 的應用在多個機器上部署了多個例項
因為多個應用例項流量不均勻,導致叢集呼叫總量沒有到的情況下某些機器就開始限流
僅靠單機維度去限制的話會無法精確地限制總體流量,通過叢集精確地控制整個叢集的呼叫總量,結合單機限流兜底,可以更好地發揮流量控制的效果
(3) 閘道器流控
Sentinel 支援對 Spring Cloud Gateway、Zuul 等主流的 API Gateway 進行限流
閘道器流控針對 API 閘道器的場景定製的限流規則,可以針對不同 route 或自定義的 API 分組進行限流,支援針對請求中的路徑、引數、Header、來源 IP 等進行定製化的限流
(4) 熔斷降級
如果呼叫鏈路中的某個資源不穩定,最終會導致請求發生堆積,通過熔斷降級能在呼叫鏈路中某個資源出現不穩定狀態時(包括呼叫超時、異常比例升高、異常數升高),對這個資源的呼叫進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯錯誤
當資源被降級後,在接下來的降級時間視窗之內,對該資源的呼叫都自動熔斷(預設行為是丟擲 DegradeException),經過時間視窗之後,退出熔斷,並在下一次資源出現不穩定狀態再次自動熔斷
(5) 熱點引數限流
熱點即經常訪問的資料,熱點引數限流會統計傳入引數中的熱點引數,並根據配置的限流閾值與模式,對包含熱點引數的資源呼叫進行限流 例如以下場景:
使用者 ID 為引數,限制使用者對介面的範圍 QPS
商品 ID 為引數,限制商品下單介面頻率
(6) 系統自適應限流
為了解決傳統方案:基於作業系統負載(load1,linux 下用 uptime 檢視)做進行自適應限流,帶來的存在延時、系統效能恢復慢的問題,Sentinel 採用新的思路:根據系統能夠處理的請求,和允許進來的請求,來做平衡,而不是根據一個間接的指標(系統 load)來做限流
目標在於:在系統不被拖垮的情況下,儘可能提高系統的吞吐率,而不是 負載 一定要到低於某個閾值
系統保護規則是從應用級別的入口流量進行控制,從單臺機器的總體 Load、RT、入口 QPS 和執行緒數四個維度監控應用資料,當實際執行達到限定閾值進行限流保護,支援的閾值型別:
Load:當系統 load1 超過閾值,且系統當前的併發執行緒數超過系統容量時才會觸發系統保護。系統容量由系統時間執行監測到的的 maxQps * minRt (最小響應時間)計算得出
RT:當單臺機器上所有入口流量的平均 RT(響應時間)
執行緒數:當單臺機器上所有入口流量的併發執行緒數
入口 QPS:當單臺機器上所有入口流量的 QPS
(7) 黑白名單控制
Sentinel 黑白名單根據資源的請求來源(origin)限制資源是否通過,若配置白名單則只有請求來源位於白名單內時才可通過;若配置黑名單則請求來源位於黑名單時不通過,其餘的請求通過
快速入門
1 安裝控制檯
從 github release 頁面(https://github.com/alibaba/Sentinel/releases)下載最新控制檯 jar 包
命令列啟動控制檯:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
2 應用接入 Sentinel
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 客戶端初始化,才能在控制檯看到介面
新增流控規則:
頻繁請求介面,可以看到部分請求被拒絕:
注意:上面的配置方式是沒有做持久化的,生產環境不建議使用
3 規則配置
Sentinel 提供 動態規則資料來源 支援來動態地管理、讀取配置的規則。Sentinel 提供的 ReadableDataSource 和 WritableDataSource 介面簡單易用,非常方便使用。
Sentinel 動態規則源針對常見的配置中心和遠端儲存進行適配,目前已支援 Nacos、ZooKeeper、Apollo、Redis 等多種動態規則源,可以覆蓋到很多的生產場景
實現原理
下面介紹 Sentinel 客戶端基本原理
1 基本概念
Resource 資源 Sentinel 中,需要被流量保護的方法、程式碼塊都可以稱為資源,每個資源都需要定義一個唯一的資源名詞,用於匹配相關規則
Entry Sentinel 功能入口類,Entry 可以通過對主流框架的適配自動建立,也可以通過註解的方式或呼叫 SphU API 顯式建立,建立後執行資源和規則匹配和校驗
Slot 功能插槽,由 Enty 類建立,每個資源對應一系列 Slot,Slot 實現資源資訊收集、規則匹配、校驗的,多個 Slot 通過組成 Slot Chain,在進入資源和退出資源時分別基於責任鏈模式呼叫 entry()和 exit()方法
2 工作原理
一個簡單的 demo:
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();
}
}
主要流程如下:
進入資源方法之前,基於 SphU 建立 Entry,Entry 獲取查詢資源關聯的 Slot Chain 資訊,如果找不到則建立,並基於責任鏈模式呼叫 Slot 的 entry()方法
資源方法呼叫
資源方法呼叫完成後,通過 Entry 觸發 Slot 的 exit()邏輯
框架比較
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔離策略 | 訊號量隔離(併發執行緒數限流) | 執行緒池隔離/訊號量隔離 | 訊號量隔離 |
熔斷降級策略 | 基於響應時間、異常比率、異常數 | 基於異常比率 | 基於異常比率、響應時間 |
實時統計實現 | 滑動視窗(LeapArray) | 滑動視窗(基於 RxJava) | Ring Bit Buffer |
動態規則配置 | 支援多種資料來源 | 支援多種資料來源 | 有限支援 |
擴充套件性 | 多個擴充套件點 | 外掛的形式 | 介面的形式 |
基於註解的支援 | 支援 | 支援 | 支援 |
限流 | 基於 QPS,支援基於呼叫關係的限流 | 有限的支援 | Rate Limiter |
流量整形 | 支援預熱模式、勻速器模式、預熱排隊模式 | 不支援 | 簡單的 Rate Limiter 模式 |
系統自適應保護 | 支援 | 不支援 | 不支援 |
控制檯 | 提供開箱即用的控制檯,可配置規則、檢視秒級監控、機器發現等 | 簡單的監控檢視 | 不提供控制檯,可對接其它監控系統 |
值得補充的是:相比 Hystrix 基於執行緒池隔離進行限流,這種方案雖然隔離性比較好,但是代價就是執行緒數目太多,執行緒上下文切換的 overhead 比較大,特別是對低延時的呼叫有比較大的影響。
Sentinel 併發執行緒數限流不負責建立和管理執行緒池,而是簡單統計當前請求上下文的執行緒數目,如果超出閾值,新的請求會被立即拒絕,效果類似於訊號量隔離
參考
《Sentinel 官方文件》
https://github.com/alibaba/Sentinel/wiki
《從 Hystrix 遷移到 Sentinel》
https://github.com/alibaba/Sentinel/wiki/Guideline:-從-Hystrix-遷移到-Sentinel
相關文章
- go-zero 如何扛住流量衝擊(一)Go
- go-zero 如何扛住流量衝擊(二)Go
- 阿里P8面試官:如何設計一個扛住千萬級併發的架構?阿里面試架構
- 流量治理神器-Sentinel 究竟是怎麼做到讓業務方接入簡單?
- OceanBase X 成都有惠 | 扛住資料流量洪峰,找對 CP 是關鍵!
- 面試官:十問泛型,你能扛住嗎?面試泛型
- 如何扛住遊戲流量高峰?Evil Dead 主創這樣說遊戲
- 阿里 雙11 同款,流量防衛兵 Sentinel go 原始碼解讀阿里Go原始碼
- 阿里雙11同款,流量防衛兵 Sentinel go 原始碼解讀阿里Go原始碼
- 從步履蹣跚到舉重若輕,阿里基礎架構如何扛住全球最猛的流量洪峰?阿里架構
- 阿里P8面試官:如何設計一個扛住千萬級併發的架構(超級詳細)-續阿里面試架構
- 特殊時期,釘釘如何透過單元化扛住流量高峰?
- 為什麼阿里巴巴這一次能扛得起 11 億的流量?阿里
- GitHub 標星 11000+,阿里開源的微服務元件如何連續 10 年扛住雙十一大促?Github阿里微服務元件
- 什麼是高併發,怎麼解決高併發
- “雙十一、二” 業務高峰如何扛住?韻達快遞選擇 TDengine
- MySQL 到底是如何做到多版本併發的?MySql
- 大佬你是怎麼解決高併發的
- Python 如果做到高併發?Python
- 我們是怎麼做到的:Google I/O Photo BoothGoboot
- 流量治理神器-Sentinel的限流模式,選單機還是叢集?模式
- 運維告警管理困難重重,我是怎麼做到的運維
- 區塊鏈是怎麼做到保護食品安全的區塊鏈
- 缺陷不少卻好評如潮,《騎砍2》是怎麼做到的?
- 直播回顧 | 點選率提升400%,Ta是怎麼做到的?
- 幽默:Twitter延遲降低到400ms是怎麼做到的?
- 併發數、併發以及高併發分別是什麼意思?
- IoT裝置訊息洪峰怎麼扛? 阿里雲AIoT訊息佇列深度解讀阿里AI佇列
- 區塊鏈發行代幣怎麼做到合規的?區塊鏈
- [php]如何做到高併發優化PHP優化
- 流量劫持是什麼?流量劫持的手法有哪些?
- 阿里的秒殺系統是怎麼設計的?阿里
- 絕了!雙11千億流量「高併發秒殺架構設計」先睹為快架構
- 記憶體資料庫的行存表索引是怎麼做到加速的記憶體資料庫索引
- Vue3中defineEmits、defineProps 是怎麼做到不用引入就能直接用的VueMIT
- Supercell分享:《荒野亂鬥》是怎麼做到全球收入破10億美元的
- 分散式流量控制框架sentinel初探分散式框架
- Webpack的熱更新是如何做到的?原理是什麼?Web