Sentinel 動態數據源架構設計理念與改造實踐

在介紹集群限流之前需要首先掌握動態數據源的配置方式,本文將根據 Sentinel 官方提供的代碼提出整體架構思路,並最終給出實踐指導。

溫馨提示:本文主要分為動態數據源架構設計理念、從官方示例尋找改造思路、基於SpringBoot改造方案三個部分來詳細剖析 Sentienl 動態數據源的改造方案,循序漸進,不僅解決問題本身,更是反映了作者研究一個問題的思路與方法。

1、架構設計理念

在 Sentinel 中主要有如下幾個角色:管理後臺、限流熔斷規則數據源、應用程序。

1)管理後臺

管理後臺主要用於可視化配置限流規則、熔斷規則,其操作界面截圖如下:

Sentinel 動態數據源架構設計理念與改造實踐

sentinel-dashboard可視化界面

2)限流熔斷規則數據源

用於存儲限流熔斷規則的數據容器,在 Sentinel 中對應動態數據源這個概念,動態數據源包含兩層含義:

  • 數據容器
    數據容器指的就是存儲熔斷、限流等規則配置的數據庫,例如關係型數據庫、Zookeeper等等,在實際生產過程中需要選用支持持久化功能的數據庫,否則程序一重啟,配置規則就會丟失,顯然是不能接受的。
  • 動態
    動態二字主要強調的是配置規則的更改能動態及時生效,引入 Sentinel 限流 SDK 的應用程序在不需要重啟的情況下動態感知配置規則發生變化並立即生效。Sentinel 目前對 apollo、consul、etcd、nacos、redis、spring-clould-config、zookeeper 等進行了適配支持。

3)應用程序

希望通過 Sentinel 提供的限流、熔斷功能對應用程序加以保護,需要引用 Sentinel 相關的 SDK,根據採集的調用信息判斷當前是否符合限流規則。

後臺管理系統、動態數據源、應用程序的關係如圖所示:

Sentinel 動態數據源架構設計理念與改造實踐

後臺管理系統、動態數據源與應用程序關係圖

2、從官方示例尋找改造思路

從官方的文檔中可以明確獲悉 sentinel-dashboard 即官方自帶的後臺管理系統只支持將限流、熔斷等限流配置規則存儲在內存中,一旦後臺管理系統重啟,配置的熔斷規則將全部丟失,所以在生產實踐過程中需要對 sentinel-dashboard 進行一定的改造,引入動態數據源,例如 Zookeeper,對限流等配置進行持久化存儲。

有了上面的架構設計理念為我們的改造提供了方向,那如何具體改造呢?首先我們來看一下官方提供的 Demo 程序。官方提供的示例代碼如下圖所示:

Sentinel 動態數據源架構設計理念與改造實踐

sentinel-demo工程示例圖

接下來我們將以 zookeeper 動態數據源來介紹基於 zookeeper 如何構建 Sentinel 動態數據源。

2.1 限流熔斷等規則存儲

首先查閱一下 ZookeeperConfigSender,該類主要的作用是將配置寫入到 zookeeper 中,其關鍵代碼截圖如下:

Sentinel 動態數據源架構設計理念與改造實踐

ZookeeperConfigSender示例代碼

這個類的測試目的很簡單,先將限流規則持久化到 Zookeeper 中,充當的角色與 sentinel-dashboard 的角色一致,故這個類為我們改造後臺管理系統帶來很大的啟發,即可以通過 zookeeper 存儲 sentinel 限流規則,從 demo 示例可以看出限流規則在 zookeeper 中的目錄結構,路徑為/{groupId}/{dataid},該節點的 value 值存儲 json字符串,存儲所有的限流規則。

實踐指導,通常基於 zookeeper 的開發,主要是規劃好目錄結構,關於 Sentinel,我對給出一個初步的目錄規劃。

在 zookeeper 中創建一個根節點,例如 /sentienl 用來表示限流相關的根目錄。

  • groupId 通常為一個獨立的應用名稱,例如應用的 appId,例如示例中的 provider-demo。
  • dataId 通常為配置類型,例如限流規則、熔斷規則、熱點規則等類別,例如限流規則使用 /flowRule ,熔斷規則使用 /degradeRule,其 value 值使用 json 存儲,將該應用下的所有限流規則用一個 json 對象表示,其存儲格式類似於 [{},{}]。

2.2 客戶端動態感知配置

實現存儲規則的配置存儲後接下來是需要客戶端能動態感知規則的變化,從而是配置規則實時生效。

我們依然先來看一下官方示例,其核心代碼如圖所示:

Sentinel 動態數據源架構設計理念與改造實踐

ZookeeperDataSource 示例代碼

這裡儘管引入 groupId 與 dataId 的概念是方便與 nacos 進行切換,但就算不切換,基於 zookeeper 的編程,這種目錄規劃是非常有必要的。上面的示例代碼有兩個關鍵點:

  • 創建 ZookeeperDataSource,每一個 ZookeeperDataSource 負責監聽一個節點。
  • 需要調用 FlowRuleManager 的 register2Property 方法將數據源關聯的數據註冊到 FlowRuleManager 中,方便 Sentinel 內核根據數據源中存儲的限流熔斷等規則進行工作。

客戶端在啟動的時候會調用 FlowRuleManager 相關方法加載限流相關的配置,那如果配置規則發生變化後,客戶端如何動態感知呢?其關鍵就在於 ZookeeperDataSource 的實現中,其實現關鍵點如下:

Sentinel 動態數據源架構設計理念與改造實踐

ZookeeperDataSource 核心代碼

即在構建 ZookeeperDataSource 時會監聽 /groupId/dataId 節點,即存放限流配置的節點,一旦數據發生變化,就會通知到客戶端,從而調用 loadConfig 重新更新 Sentienl 客戶端的限流配置,從而實現配置實時生效。

3、Sentinel 引入Zookeeper 動態數據源實現方案

從官方的示例中我們不難發現,引入 Zookeeper 數據源主要有兩個步驟:將數據存儲在Zookeeper中以及在客戶端監聽ZK從而實時生效兩個步驟。

sentinel 官方提供了默認的後臺管理系統實現:sentinel-dashboard,但其缺點非常明顯:基於內存存儲,無法用於實際生產過程。大家可能會向後臺管理系統將配置信息存儲在內存中,那接入的客戶端如何從 sentinel-dashboard 的內存中獲取配置信息呢,這是因為 sentinel-dashboard 裡提供了簡單的機器發現,並且內置了 sentinel 客戶端之間、sentinel 客戶端與 sentinel-dashboard 之間的通訊協議,具體由 sentinel-transport 模塊實現,目前提供了基於 http 與 netty 的實現方式,故能將 sentinel-dashboard 內存中的配置信息推送到客戶端,從而使客戶端根據配置進行限流與熔斷。

接下來回答本文的重點部分,基於 sentinel-dashboard 如何引入 zookeeper 等動態數據源呢?

3.1 將配置規則存儲在Zookeeper中

首先我們可以順著 sentinel-dashboard 的提供的控制器,尋找其後臺入口,改造目標也很明確,就是將數據持久化到 zookeeper中,例如增加流控規則的後臺處理入口為:

Sentinel 動態數據源架構設計理念與改造實踐

只需要從這裡開始改造,將其配置持久化到數據庫中和 zookeeper中即可。

將數據存儲在 zookeeper 中,其關鍵是設計好各個項目如何有組織有條理的在 zookeeper 中進行組織。我給出如下設計方案:

Sentinel 動態數據源架構設計理念與改造實踐

Zookeeper目錄結構設計

這樣相關管理人員可以直接在 sentinel-dashboard 中配置限流規則,即按照應用為維度進行存儲,每一個應用再按照維度,例如限流、熔斷、熱點、集群等維度進行配置,每一分類節點的值存儲的是所有的配置,使用 [{},{}] 這種JSON格式進行存儲。

3.2 Sentinel 客戶端規則加載封裝

目前大部分項目都是基於 SpringBoot,故本文給出基於 SpringBoot 進行的客戶端加載實現思路。

Sentinel 動態數據源架構設計理念與改造實踐

客戶端改造偽代碼

其主要關鍵點如下:

  • 基於 Spring ApplicationReadyEvent 事件,實現限流規則的加載。
  • 創建 ZookeeperDataSource 創建動態數據源。
  • 並調用 Sentinel 提供的相關 API 完成限流規則的加載。

本文就介紹到這裡,Sentinel 的動態數據源改造方案是否已 Get,歡迎留言與作者互動,共同交流架構,分享源碼閱讀心得。


分享到:


相關文章: