Sentinel 集羣限流設計原理

作積極的人,越努力越幸運!
Sentinel 集羣限流設計原理node

一、集羣限流使用場景


首先一個服務有三個服務提供者,但這三臺集羣的硬件配置不同,如圖所示:
Sentinel 集羣限流設計原理
在這裏插入圖片描述緩存

爲了充分利用硬件的資源,諸如 Dubbo 都提供了基於權重的負載均衡機制,例如能夠將8C16G的機器設置的權重是4C8G的兩倍,這樣充分利用硬件資源,假如如今須要引入 Sentinel 的限流機制,例如爲一個 Dubbo 服務設置限流規則,這樣因爲三臺集羣分擔的流量不均勻,會致使沒法重複利用高配機器的資源。
假設通過壓測,機器配置爲C48G最高能承受的TPS爲 1500,而機器配置爲8C16G能承受的TPS爲2800,那若是採起單機限流,其闊值只能設置爲1500,由於若是超過1500,會將4C8G的機器壓垮。網絡

解決這種辦法的方式就是針對整個集羣進行限流,即爲整個集羣設置一個闊值,例如設置限流TPS爲6000。多線程

二、集羣限流與單機限流的異同思考


限流的一個基本做用就是按照限流規則生成訪問許可(Token),而後根據當前實時的調用信息進行判斷是否能夠得到許可而決定是否放行。架構

集羣與單機限流在實時調用信息收集方面應該差異不大,均可以基於滑動窗口進行統計信息的收集。app

集羣與單機限流的最主要區別在與許可的生成,單機模式的許可直接在本地生成,但集羣限流必須有一個統一的 Token 發放機制,以此來協調當前集羣內多機調用,從而基於當前「調用總數」進行限流。負載均衡

三、探究集羣限流實現原理


在探究集羣限流實現原理以前先來回顧一下單機限流的執行流程圖。
Sentinel 集羣限流設計原理
在這裏插入圖片描述ide

結合流程咱們能夠看出集羣限流的幾個關鍵點 ClusterBuilderSlot、FlowSlot。ui

3.1 ClusterBuilderSlot 詳解

在對一個資源進行流控規則判斷時,首先將進入到 NodeSelectorSlot,而後就會進入到 ClusterBuilderSlot,爲了與單機限流模式,介紹 ClusterBuilderSlot 時與 NodeSelectorSlot 進行一個對比。spa

NodeSelectorSlot 的核心實現截圖以下所示:
Sentinel 集羣限流設計原理
在這裏插入圖片描述

舒適提示:從該系列以前的文章也能得知,一個 資源對應的一個 NodeSelectorSlot 實例,即多線程訪問一個資源時,都會調用同一個 NodeSelectorSlot 實例。

NodeSelectorSlot 的關鍵點以下:

  • Map<String, DefaultNode> map
    在 NodeSelectorSlot 中是以 context Id 爲維度進行緩存的,例如官方給出的 Dubbo 適配方法,contexId 爲 dubbo 服務的全路徑名。即 Dubbo的入口節點對應的緩存 Key 爲 context
    id。
  • fireEntry 的 node 參數
    因爲 NodeSelectorSlot 是第一個過濾器,故第一次調用 fireEntry 方法時的 node 參數就是上面建立的 Node,即與 context 相關鏈的 Node,即所謂的入口節點即 Entrance Node。
    接下來重點關注一下 ClusterBuilderSlot 的關鍵點:
    Sentinel 集羣限流設計原理
    在這裏插入圖片描述

ClusterBuilderSlot 的關鍵點以下:

  • Map<ResourceWrapper, ClusterNode> clusterNodeMap
    持有的集羣節點緩存表,其鍵爲 Entrance Node 所對應的資源ID,即 Context 中關聯的節點信息。
  • Node originNode
    所謂的 orginNode,即在調用 ContextUtil 中 enter(String name, String origin) 方法中的第二個參數,表示這條調用鏈的源頭,在 Dubbo 中默認爲 應用的 application。
    通過上面兩個Slot,整個調用鏈就基本建立好了,接下來咱們來看一下 FlowSlot 關於集羣限流的相關處理邏輯。

3.2 集羣限流模式實現原理

Sentinel 集羣限流設計原理
在這裏插入圖片描述

FlowSlow FlowSlot 的核心處理邏輯主要是調用 FlowRuleChecker 的 canPassCheck 方法,正如上面看到的同樣,根據配置規則,若是是集羣模式,則調用的是其 passClusterCheck 方法,接下來咱們將重點探討該方法。
Sentinel 集羣限流設計原理
FlowRuleChecker#passClusterCheck

代碼@1:獲取一個 TokenService 服務類。這裏實現關鍵點:

  • 若是當前節點的角色爲 CLIENT,返回的 TokenService 爲 DefaultClusterTokenClient。
  • 若是當前節點的角色爲 SERVER,返回的 TokenService 爲 ClusterTokenServer,這裏使用了SPI極致,能夠經過查看 META-INF/services 目錄下的 com.alibaba.csp.sentinel.cluster.TokenService 文件,默認服務端返回 DefaultTokenService。
    代碼@2:若是沒法獲取到集羣限流Token服務,若是該限流規則配置了能夠退化爲單機限流模式,則退化爲單機限流。

代碼@3:獲取集羣限流的流程ID,該 flowId 全局惟一。

代碼@4:經過 TokenService 去申請 token,這裏是與單機限流模式最大的差異。

接下來將分別從 DefaultClusterTokenClient、DefaultTokenService 分別探究集羣限流相關的實現原理與細節,更好的指導咱們如何使用集羣限流功能。

3.2.1 DefaultClusterTokenClient 詳解

從咱們的經驗也得知,TokenClient 的主要職責就是發送請求到 TokenService 端,主要是網絡相關的細節將不在此篇文章中給出,若是有興趣,你們能夠關注個人 Netty 專欄。

首先 Sentinel 提供了 SPI 機制,故容許用戶自定義 TokenClient 的實現類,官方與 SPI 默認配置的文件以下:
Sentinel 集羣限流設計原理

關於 TokenClient 主要關注其初始化代碼,由於咱們須要關注一個很是重要的點:
DefaultClusterTokenClient#initNewConnection
Sentinel 集羣限流設計原理
在這裏插入圖片描述
在客戶端啓動的時候會建立與 TokenServer 之間的連接,即這邊須要配置服務端的 IP 與端口號,那如何配置呢?其實配置方式徹底由本身去實現Sentinel 集羣限流設計原理對應的解析器,下面根據官方的 Demo 示例以下:
Sentinel 集羣限流設計原理
在這裏插入圖片描述
這裏須要說明的其配置項由 ClusterGroupEntity 來定義,其字段的定義以下:

  • clientSet
    客戶端 Set 集合。
  • ip
    Token 服務端的 IP。
  • machinedId
    Token 服務端的機器ID。
  • port
    Token 服務端的機器端口。
    其配置示例以下:
[{"clientSet":["112.12.88.66@8729","112.12.88.67@8727"],"ip":"112.12.88.68","machineId":"112.12.88.68@8728","port":11111}]

Client 端接下來就是向服務端發送請求,與網絡相關的不在本文的討論範圍內,接下來將重點探討服務端是如何發放許可的。

3.2.2 DefaultTokenService 詳解

Token Server 端收到客戶的請求,其處理入口爲 FlowRequestProcessor,其處理方法爲:proce***equest,最終會調用 DefaultTokenService 的 requestToken 方法。
DefaultTokenService#requestToken
Sentinel 集羣限流設計原理
在這裏插入圖片描述

代碼@1:根據 ruleId 獲取指定的限流規則。
代碼@2:而後調用 ClusterFlowChecker 的 acquierClusterToken 方法,申請許可。

許可的發放流程主要由 ClusterFlowChecker 的 acquierClusterToken 方法實現。

Sentinel 集羣限流設計原理
在這裏插入圖片描述
Step1:首先判斷是否容許本次許可申請,這是由於 TokenServe 支持嵌入式,即支持在應用節點中嵌入一個 TokenServer,爲了保證許可申請的請求不對正常業務形成比較大的影響,故對申請許可這個動做進行了限流。
一旦觸發了限流,將向客戶端返回 TOO_MANY_REQUEST 狀態碼,Sentinel 支持按 namespace 進行限流,具體由 GlobalRequestLimiter 實現,該類的內部一樣基於滑動窗口進行收集,原理與 FlowSlot 類似,故這裏不加以展開,默認的限流TPS爲3W,有關於 Sentinel 相關的配置,將在後續文章專門梳理。
Sentinel 集羣限流設計原理
在這裏插入圖片描述

Step2:根據流程ID獲取指標採集器。
Sentinel 集羣限流設計原理
在這裏插入圖片描述
Step3:計算 latestQps、globalThreashold、 nextRemaining 三個闊值,三個的含義分別以下:

  • latestQps
    獲取當前正常訪問的QPS。
  • globalThreashold
    根據限流配置規則得出其總許可數量,其主要根據闊值的方式其有所不一樣,其配置闊值有兩種方式:
    1)FLOW_THRESHOLD_GLOBAL
    總數,即集羣中的許可等於限流規則中配置的 count 值。
    2)FLOW_THRESHOLD_AVG_LOCAL
    單機分攤模式,此時限流規則中配置的值只是單機的 count 值,集羣中的許可數等於 count * 集羣中客戶端的個數。
    注意:這裏還能夠經過 exceedCount 設置來運行超過其最大闊值,默認爲1表示不容許超過。
  • nextRemainging
    表示處理完本次請求後剩餘的許可數量。
    Sentinel 集羣限流設計原理
    在這裏插入圖片描述
    Step4:若是剩餘的許可數大於0,則本次申請成功,將當前的調用計入指標採集器中,而後返回給客戶便可。
    接下來全部流程步驟都是基於沒有剩餘許可數的處理邏輯。
    Sentinel 集羣限流設計原理
    在這裏插入圖片描述

Step5:當前許可數不足的狀況,而且該請求爲高優先級的處理邏輯:

  • 獲取當前等待的TPS(即1s爲維度,當前等待的請求數量)
  • 若是當前等待的TPS低於可借用將來窗口的許可闊值時,可經過,但設置其等待時間,能夠經過 maxOccupyRatio 來設置借用的最大比值。
    Sentinel 集羣限流設計原理
    在這裏插入圖片描述

Step6:若是當前許可不足,而且該請求爲普通優先級的處理邏輯,增長阻塞相關指標的統計數,並返回 BLOCKED。
TokenServer 返回申請許可以後,那 Token Client 如何處理呢?其處理代碼在 FlowRuleChecker#applyTokenResult
Sentinel 集羣限流設計原理
在這裏插入圖片描述

咱們能夠發現,若是服務端返回OK,則順利經過,返回BLOCKED,則直接返回 false,會拋出 FlowException,若是是 token 限流,若是規則運行退化爲單機限流模式,則進行單機限流。
集羣限流的基本實現原理就介紹到這裏了。

四、總結


集羣限流的基本原理接介紹到這裏了,與單機限流模式最大的區別就是集羣限流模式的須要引入 TokenService,提供許可的發放服務,該服務能夠嵌入應用節點,也能夠獨立於應用以外。這邊借用官方文檔上的兩張圖來簡單介紹一下嵌入模式與獨立模式的架構:
Sentinel 集羣限流設計原理
在這裏插入圖片描述

Sentinel 集羣限流設計原理
在這裏插入圖片描述

集羣模式使用注意,若是使用的是集羣模式限流,則以下兩個配置則失效:
Sentinel 集羣限流設計原理
在這裏插入圖片描述

最後拋出一個思考題:集羣模式應該算是高大上,但咱們項目中真的須要嗎?集羣限流模式有哪些缺點、哪些優勢,歡迎你們留言探討。

好了,親愛的讀者朋友,以上就是本文的所有內容了,原創不易,莫要白票,請你爲本文點個【在看】吧,這將是我寫做更多優質文章的最強動力。

歡迎加入個人知識星球,一塊兒交流源碼,探討架構,揭祕億級訂單的架構設計與實踐經驗,打造高質量的技術交流圈,爲廣大星友提供高質量問答服務,長按以下二維碼加入。
Sentinel 集羣限流設計原理

丁威素質三連是對我最大的鼓勵鐘意做者

相關文章
相關標籤/搜索