作積極的人,越努力越幸運!node
首先一個服務有三個服務提供者,但這三臺集羣的硬件配置不同,如圖所示:
在這裏插入圖片描述緩存
爲了充分利用硬件的資源,諸如 Dubbo 都提供了基於權重的負載均衡機制,例如能夠將8C16G的機器設置的權重是4C8G的兩倍,這樣充分利用硬件資源,假如如今須要引入 Sentinel 的限流機制,例如爲一個 Dubbo 服務設置限流規則,這樣因爲三臺集羣分擔的流量不均勻,會致使沒法重複利用高配機器的資源。
假設通過壓測,機器配置爲C48G最高能承受的TPS爲 1500,而機器配置爲8C16G能承受的TPS爲2800,那若是採起單機限流,其闊值只能設置爲1500,由於若是超過1500,會將4C8G的機器壓垮。網絡
解決這種辦法的方式就是針對整個集羣進行限流,即爲整個集羣設置一個闊值,例如設置限流TPS爲6000。多線程
限流的一個基本做用就是按照限流規則生成訪問許可(Token),而後根據當前實時的調用信息進行判斷是否能夠得到許可而決定是否放行。架構
集羣與單機限流在實時調用信息收集方面應該差異不大,均可以基於滑動窗口進行統計信息的收集。app
集羣與單機限流的最主要區別在與許可的生成,單機模式的許可直接在本地生成,但集羣限流必須有一個統一的 Token 發放機制,以此來協調當前集羣內多機調用,從而基於當前「調用總數」進行限流。負載均衡
在探究集羣限流實現原理以前先來回顧一下單機限流的執行流程圖。
在這裏插入圖片描述ide
結合流程咱們能夠看出集羣限流的幾個關鍵點 ClusterBuilderSlot、FlowSlot。ui
在對一個資源進行流控規則判斷時,首先將進入到 NodeSelectorSlot,而後就會進入到 ClusterBuilderSlot,爲了與單機限流模式,介紹 ClusterBuilderSlot 時與 NodeSelectorSlot 進行一個對比。spa
NodeSelectorSlot 的核心實現截圖以下所示:
在這裏插入圖片描述
舒適提示:從該系列以前的文章也能得知,一個 資源對應的一個 NodeSelectorSlot 實例,即多線程訪問一個資源時,都會調用同一個 NodeSelectorSlot 實例。
NodeSelectorSlot 的關鍵點以下:
ClusterBuilderSlot 的關鍵點以下:
在這裏插入圖片描述
FlowSlow FlowSlot 的核心處理邏輯主要是調用 FlowRuleChecker 的 canPassCheck 方法,正如上面看到的同樣,根據配置規則,若是是集羣模式,則調用的是其 passClusterCheck 方法,接下來咱們將重點探討該方法。
FlowRuleChecker#passClusterCheck
代碼@1:獲取一個 TokenService 服務類。這裏實現關鍵點:
代碼@3:獲取集羣限流的流程ID,該 flowId 全局惟一。
代碼@4:經過 TokenService 去申請 token,這裏是與單機限流模式最大的差異。
接下來將分別從 DefaultClusterTokenClient、DefaultTokenService 分別探究集羣限流相關的實現原理與細節,更好的指導咱們如何使用集羣限流功能。
從咱們的經驗也得知,TokenClient 的主要職責就是發送請求到 TokenService 端,主要是網絡相關的細節將不在此篇文章中給出,若是有興趣,你們能夠關注個人 Netty 專欄。
首先 Sentinel 提供了 SPI 機制,故容許用戶自定義 TokenClient 的實現類,官方與 SPI 默認配置的文件以下:
關於 TokenClient 主要關注其初始化代碼,由於咱們須要關注一個很是重要的點:
DefaultClusterTokenClient#initNewConnection
在這裏插入圖片描述
在客戶端啓動的時候會建立與 TokenServer 之間的連接,即這邊須要配置服務端的 IP 與端口號,那如何配置呢?其實配置方式徹底由本身去實現對應的解析器,下面根據官方的 Demo 示例以下:
在這裏插入圖片描述
這裏須要說明的其配置項由 ClusterGroupEntity 來定義,其字段的定義以下:
[{"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 端接下來就是向服務端發送請求,與網絡相關的不在本文的討論範圍內,接下來將重點探討服務端是如何發放許可的。
Token Server 端收到客戶的請求,其處理入口爲 FlowRequestProcessor,其處理方法爲:proce***equest,最終會調用 DefaultTokenService 的 requestToken 方法。
DefaultTokenService#requestToken
在這裏插入圖片描述
代碼@1:根據 ruleId 獲取指定的限流規則。
代碼@2:而後調用 ClusterFlowChecker 的 acquierClusterToken 方法,申請許可。
許可的發放流程主要由 ClusterFlowChecker 的 acquierClusterToken 方法實現。
在這裏插入圖片描述
Step1:首先判斷是否容許本次許可申請,這是由於 TokenServe 支持嵌入式,即支持在應用節點中嵌入一個 TokenServer,爲了保證許可申請的請求不對正常業務形成比較大的影響,故對申請許可這個動做進行了限流。
一旦觸發了限流,將向客戶端返回 TOO_MANY_REQUEST 狀態碼,Sentinel 支持按 namespace 進行限流,具體由 GlobalRequestLimiter 實現,該類的內部一樣基於滑動窗口進行收集,原理與 FlowSlot 類似,故這裏不加以展開,默認的限流TPS爲3W,有關於 Sentinel 相關的配置,將在後續文章專門梳理。
在這裏插入圖片描述
Step2:根據流程ID獲取指標採集器。
在這裏插入圖片描述
Step3:計算 latestQps、globalThreashold、 nextRemaining 三個闊值,三個的含義分別以下:
Step5:當前許可數不足的狀況,而且該請求爲高優先級的處理邏輯:
Step6:若是當前許可不足,而且該請求爲普通優先級的處理邏輯,增長阻塞相關指標的統計數,並返回 BLOCKED。
TokenServer 返回申請許可以後,那 Token Client 如何處理呢?其處理代碼在 FlowRuleChecker#applyTokenResult
在這裏插入圖片描述
咱們能夠發現,若是服務端返回OK,則順利經過,返回BLOCKED,則直接返回 false,會拋出 FlowException,若是是 token 限流,若是規則運行退化爲單機限流模式,則進行單機限流。
集羣限流的基本實現原理就介紹到這裏了。
集羣限流的基本原理接介紹到這裏了,與單機限流模式最大的區別就是集羣限流模式的須要引入 TokenService,提供許可的發放服務,該服務能夠嵌入應用節點,也能夠獨立於應用以外。這邊借用官方文檔上的兩張圖來簡單介紹一下嵌入模式與獨立模式的架構:
在這裏插入圖片描述
在這裏插入圖片描述
集羣模式使用注意,若是使用的是集羣模式限流,則以下兩個配置則失效:
在這裏插入圖片描述
最後拋出一個思考題:集羣模式應該算是高大上,但咱們項目中真的須要嗎?集羣限流模式有哪些缺點、哪些優勢,歡迎你們留言探討。
好了,親愛的讀者朋友,以上就是本文的所有內容了,原創不易,莫要白票,請你爲本文點個【在看】吧,這將是我寫做更多優質文章的最強動力。
歡迎加入個人知識星球,一塊兒交流源碼,探討架構,揭祕億級訂單的架構設計與實踐經驗,打造高質量的技術交流圈,爲廣大星友提供高質量問答服務,長按以下二維碼加入。
丁威素質三連是對我最大的鼓勵鐘意做者