Sentinel(五)之流量控制
轉載自??流量控制
概述
流量控制(flow control),其原理是監控應用流量的 QPS 或并發線程數等指標,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰沖垮,從而保障應用的高可用性。
FlowSlot?會根據預設的規則,結合前面?NodeSelectorSlot、ClusterBuilderSlot、StatisticSlot?統計出來的實時信息進行流量控制。
限流的直接表現是在執行?Entry nodeA = SphU.entry(resourceName)?的時候拋出?FlowException?異常。FlowException?是?BlockException?的子類,您可以捕捉?BlockException?來自定義被限流之后的處理邏輯。
同一個資源可以創建多條限流規則。FlowSlot?會對該資源的所有限流規則依次遍歷,直到有規則觸發限流或者所有規則遍歷完畢。
一條限流規則主要由下面幾個因素組成,我們可以組合這些元素來實現不同的限流效果:
- resource:資源名,即限流規則的作用對象
- count: 限流閾值
- grade: 限流閾值類型(QPS 或并發線程數)
- limitApp: 流控針對的調用來源,若為?default?則不區分調用來源
- strategy: 調用關系限流策略
- controlBehavior: 流量控制效果(直接拒絕、Warm Up、勻速排隊)
基于QPS/并發數的流量控制
流量控制主要有兩種統計類型,一種是統計并發線程數,另外一種則是統計 QPS。類型由?FlowRule?的?grade?字段來定義。其中,0 代表根據并發數量來限流,1 代表根據 QPS 來進行流量控制。其中線程數、QPS 值,都是由?StatisticSlot?實時統計獲取的。
我們可以通過下面的命令查看實時統計信息:
curl http://localhost:8719/cnode?id=resourceName輸出內容格式如下:
idx id thread pass blocked success total Rt 1m-pass 1m-block 1m-all exception 2 abc647 0 46 0 46 46 1 2763 0 2763 0其中:
- thread: 代表當前處理該資源的并發數;
- pass: 代表一秒內到來到的請求;
- blocked: 代表一秒內被流量控制的請求數量;
- success: 代表一秒內成功處理完的請求;
- total: 代表到一秒內到來的請求以及被阻止的請求總和;
- RT: 代表一秒內該資源的平均響應時間;
- 1m-pass: 則是一分鐘內到來的請求;
- 1m-block: 則是一分鐘內被阻止的請求;
- 1m-all: 則是一分鐘內到來的請求和被阻止的請求的總和;
- exception: 則是一秒內業務本身異常的總和。
2.1 并發線程數控制
并發數控制用于保護業務線程池不被慢調用耗盡。例如,當應用所依賴的下游應用由于某種原因導致服務不穩定、響應延遲增加,對于調用者來說,意味著吞吐量下降和更多的線程數占用,極端情況下甚至導致線程池耗盡。為應對太多線程占用的情況,業內有使用隔離的方案,比如通過不同業務邏輯使用不同線程池來隔離業務自身之間的資源爭搶(線程池隔離)。這種隔離方案雖然隔離性比較好,但是代價就是線程數目太多,線程上下文切換的 overhead 比較大,特別是對低延時的調用有比較大的影響。Sentinel 并發控制不負責創建和管理線程池,而是簡單統計當前請求上下文的線程數目(正在執行的調用數目),如果超出閾值,新的請求會被立即拒絕,效果類似于信號量隔離。并發數控制通常在調用端進行配置。
例子參見:ThreadDemo
2.2 QPS流量控制
當 QPS 超過某個閾值的時候,則采取措施進行流量控制。流量控制的效果包括以下幾種:直接拒絕、Warm Up、勻速排隊。對應?FlowRule?中的?controlBehavior?字段。
注意:若使用除了直接拒絕之外的流量控制效果,則調用關系限流策略(strategy)會被忽略。
直接拒絕
直接拒絕(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是默認的流量控制方式,當QPS超過任意規則的閾值后,新的請求就會被立即拒絕,拒絕方式為拋出FlowException。這種方式適用于對系統處理能力確切已知的情況下,比如通過壓測確定了系統的準確水位時。具體的例子參見?FlowQpsDemo。
Warm Up
Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即預熱/冷啟動方式。當系統長期處于低水位的情況下,當流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮。通過"冷啟動",讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。詳細文檔可以參考?流量控制 - Warm Up 文檔,具體的例子可以參見?WarmUpFlowDemo。
通常冷啟動的過程系統允許通過的 QPS 曲線如下圖所示:
勻速排隊
勻速排隊(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式會嚴格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶算法。詳細文檔可以參考?流量控制 - 勻速器模式,具體的例子可以參見?PaceFlowDemo。
該方式的作用如下圖所示:
這種方式主要用于處理間隔性突發的流量,例如消息隊列。想象一下這樣的場景,在某一秒有大量的請求到來,而接下來的幾秒則處于空閑狀態,我們希望系統能夠在接下來的空閑期間逐漸處理這些請求,而不是在第一秒直接拒絕多余的請求。
注意:勻速排隊模式暫時不支持 QPS > 1000 的場景。
基于調用關系的流量控制
調用關系包括調用方、被調用方;一個方法又可能會調用其它方法,形成一個調用鏈路的層次關系。Sentinel 通過?NodeSelectorSlot?建立不同資源間的調用的關系,并且通過?ClusterBuilderSlot?記錄每個資源的實時統計信息。
有了調用鏈路的統計信息,我們可以衍生出多種流量控制手段。
3.1 根據調用方限流
ContextUtil.enter(resourceName, origin)?方法中的?origin?參數標明了調用方身份。這些信息會在?ClusterBuilderSlot?中被統計??赏ㄟ^以下命令來展示不同的調用方對同一個資源的調用數據:
curl http://localhost:8719/origin?id=nodeA調用數據示例:
id: nodeA idx origin threadNum passedQps blockedQps totalQps aRt 1m-passed 1m-blocked 1m-total 1 caller1 0 0 0 0 0 0 0 0 2 caller2 0 0 0 0 0 0 0 0上面這個命令展示了資源名為?nodeA?的資源被兩個不同的調用方調用的統計。
流控規則中的?limitApp?字段用于根據調用來源進行流量控制。該字段的值有以下三種選項,分別對應不同的場景:
- default:表示不區分調用者,來自任何調用者的請求都將進行限流統計。如果這個資源名的調用總和超過了這條規則定義的閾值,則觸發限流。
- {some_origin_name}:表示針對特定的調用者,只有來自這個調用者的請求才會進行流量控制。例如?NodeA?配置了一條針對調用者caller1的規則,那么當且僅當來自?caller1?對?NodeA?的請求才會觸發流量控制。
- other:表示針對除?{some_origin_name}?以外的其余調用方的流量進行流量控制。例如,資源NodeA配置了一條針對調用者?caller1?的限流規則,同時又配置了一條調用者為?other?的規則,那么任意來自非?caller1?對?NodeA?的調用,都不能超過?other?這條規則定義的閾值。
同一個資源名可以配置多條規則,規則的生效順序為:{some_origin_name} > other > default
3.2 根據調用鏈路入口限流:鏈路限流
NodeSelectorSlot?中記錄了資源之間的調用鏈路,這些資源通過調用關系,相互之間構成一棵調用樹。這棵樹的根節點是一個名字為?machine-root?的虛擬節點,調用鏈的入口都是這個虛節點的子節點。
一棵典型的調用樹如下圖所示:
machine-root/ \/ \Entrance1 Entrance2/ \/ \DefaultNode(nodeA) DefaultNode(nodeA)上圖中來自入口?Entrance1?和?Entrance2?的請求都調用到了資源?NodeA,Sentinel 允許只根據某個入口的統計信息對資源限流。比如我們可以設置?strategy?為?RuleConstant.STRATEGY_CHAIN,同時設置?refResource?為?Entrance1?來表示只有從入口?Entrance1?的調用才會記錄到?NodeA?的限流統計當中,而不關心經?Entrance2?到來的調用。
調用鏈的入口(上下文)是通過 API 方法?ContextUtil.enter(contextName)?定義的,其中 contextName 即對應調用鏈路入口名稱。詳情可以參考?ContextUtil 文檔。
3.3 具有關系的資源流量控制:關聯流量控制
當兩個資源之間具有資源爭搶或者依賴關系的時候,這兩個資源便具有了關聯。比如對數據庫同一個字段的讀操作和寫操作存在爭搶,讀的速度過高會影響寫得速度,寫的速度過高會影響讀的速度。如果放任讀寫操作爭搶資源,則爭搶本身帶來的開銷會降低整體的吞吐量??墒褂藐P聯限流來避免具有關聯關系的資源之間過度的爭搶,舉例來說,read_db?和?write_db?這兩個資源分別代表數據庫讀寫,我們可以給?read_db?設置限流規則來達到寫優先的目的:設置?strategy?為?RuleConstant.STRATEGY_RELATE?同時設置?refResource?為?write_db。這樣當寫庫操作過于頻繁時,讀數據的請求會被限流。
總結
以上是生活随笔為你收集整理的Sentinel(五)之流量控制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Sentinel(四)之工作主流程
- 下一篇: 用ps玩转胶片漏光效果photoshop