Spring Cloud Alibaba Sentinel 主要原理和核心類介紹

大星說爬蟲發表於2023-12-29

Context

Context 代表呼叫鏈路上下文,貫穿一次呼叫鏈路中的所有 Entry。Context 維持著入口節點(entranceNode)、本次呼叫鏈路的 curNode、呼叫來源(origin)等資訊。Context 名稱即為呼叫鏈路入口名稱。


Context 維持的方式:透過 ThreadLocal 傳遞,只有在入口 enter 的時候生效。由於 Context 是透過 ThreadLocal 傳遞的,因此對於非同步呼叫鏈路,執行緒切換的時候會丟掉 Context,因此需要手動透過 ContextUtil.runOnContext(context, f) 來變換 context。


Entry

每一次資源呼叫都會建立一個 Entry。Entry 包含了資源名、curNode(當前統計節點)、originNode(來源統計節點)等資訊


Node

Sentinel 裡面的各種種類的統計節點:


StatisticNode:最為基礎的統計節點,包含秒級和分鐘級兩個滑動視窗結構。

DefaultNode:鏈路節點,用於統計呼叫鏈路上某個資源的資料,維持樹狀結構。

ClusterNode:簇點,用於統計每個資源全域性的資料(不區分呼叫鏈路),以及存放該資源的按來源區分的呼叫資料(型別為 StatisticNode)。特別地,Constants.ENTRY_NODE 節點用於統計全域性的入口資源資料。

EntranceNode:入口節點,特殊的鏈路節點,對應某個 Context 入口的所有呼叫資料。Constants.ROOT 節點也是入口節點。

構建的時機:

EntranceNode 在 ContextUtil.enter(xxx) 的時候就建立了,然後設定到 Context 裡面。

NodeSelectorSlot:根據 context 建立 DefaultNode,然後設定到 Context 裡面。

ClusterBuilderSlot:首先根據 resourceName 建立 ClusterNode,並且 set clusterNode to defaultNode;然後再根據 origin 建立來源節點(型別為 StatisticNode),並且 set originNode to curEntry。

幾種 Node 的維度(數目):


ClusterNode 的維度是 resource

DefaultNode 的維度是 resource * context,存在每個 NodeSelectorSlot 的 map 裡面

EntranceNode 的維度是 context,存在 ContextUtil 類的 contextNameNodeMap 裡面

來源節點(型別為 StatisticNode)的維度是 resource * origin,存在每個 ClusterNode 的 originCountMap 裡面

Sentinel核心結構





在 Sentinel 裡面,所有的資源都對應一個資源名稱以及一個 Entry。Entry 可以透過對主流框架的適配自動建立,也可以透過註解的方式或呼叫 API 顯式建立;每一個 Entry 建立的時候,同時也會建立一系列功能插槽(slot chain)。這些插槽有不同的職責


NodeSelectorSlot 負責收集資源的路徑,並將這些資源的呼叫路徑,以樹狀結構儲存起來,用於根據呼叫路徑來限流降級;

ClusterBuilderSlot 則用於儲存資源的統計資訊以及呼叫者資訊,例如該資源的 RT, QPS, thread count 等等,這些資訊將用作為多維度限流,降級的依據;

StatisticSlot 則用於記錄、統計不同緯度的 runtime 指標監控資訊;

FlowSlot 則用於根據預設的限流規則以及前面 slot 統計的狀態,來進行流量控制;

AuthoritySlot 則根據配置的黑白名單和呼叫來源資訊,來做黑白名單控制;

DegradeSlot 則透過統計資訊以及預設的規則,來做熔斷降級;

SystemSlot 則透過系統的狀態,例如 load1 等,來控制總的入口流量;

slot chain其實可以分為兩個部分:統計資料構建部分(statistic)和判斷部分(rule checking)


Sentinel 將 ProcessorSlot 作為 SPI 介面進行擴充套件(1.7.2 版本以前 SlotChainBuilder 作為 SPI),使得 Slot Chain 具備了擴充套件的能力。您可以自行加入自定義的 slot 並編排 slot 間的順序,從而可以給 Sentinel 新增自定義的功能。




SPI 擴充套件

Sentinel 提供多樣化的 SPI 介面用於提供擴充套件的能力。開發者可以在用同一個 sentinel-core 的基礎上自行擴充套件介面實現,從而可以方便地根據業務需求給 Sentinel 新增自定義的邏輯。目前 Sentinel 提供如下的擴充套件點:


初始化過程擴充套件:提供 InitFunc SPI介面,可以新增自定義的一些初始化邏輯,如動態規則源註冊等。

Slot/Slot Chain 擴充套件:用於給 Sentinel 功能鏈新增自定義的功能並自由編排。

指標統計擴充套件(StatisticSlot Callback):用於擴充套件 StatisticSlot 指標統計相關的邏輯。

Transport 擴充套件:提供 CommandHandler、CommandCenter 等介面,用於對心跳傳送、監控 API Server 進行擴充套件。

叢集流控擴充套件:可以方便地定製 token client/server 自定義實現

日誌擴充套件:用於自定義 record log Logger,可用於對接 slf4j 等標準日誌實現。

NodeSelectorSlot

這個 slot 主要負責收集資源的路徑,並將這些資源的呼叫路徑,以樹狀結構儲存起來,用於根據呼叫路徑來限流降級。


ContextUtil.enter("entrance1", "appA");

 Entry nodeA = SphU.entry("nodeA");

 if (nodeA != null) {

    nodeA.exit();

 }

 ContextUtil.exit();

1.

2.

3.

4.

5.

6.

上述程式碼透過 ContextUtil.enter() 建立了一個名為 entrance1 的上下文,同時指定呼叫發起者為 appA;接著透過 SphU.entry()請求一個 token,如果該方法順利執行沒有拋 BlockException,表明 token 請求成功。


以上程式碼將在記憶體中生成以下結構:


machine-root

                 /     

                /

         EntranceNode1

              /

             /   

      DefaultNode(nodeA)

1.

2.

3.

4.

5.

6.

7.

示例2


ContextUtil.enter("entrance1", "appA");

  Entry nodeA = SphU.entry("nodeA");

  if (nodeA != null) {

    nodeA.exit();

  }

  ContextUtil.exit();


  ContextUtil.enter("entrance2", "appA");

  nodeA = SphU.entry("nodeA");

  if (nodeA != null) {

    nodeA.exit();

  }

  ContextUtil.exit();

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

以上程式碼生成如下結構


machine-root

                   /         \

                  /           \

          EntranceNode1   EntranceNode2

                /               \

               /                 \

       DefaultNode(nodeA)   DefaultNode(nodeA)

1.

2.

3.

4.

5.

6.

7.

上面的結構可以透過呼叫 curl 來顯示:


EntranceNode: machine-root(t:0 pq:1 bq:0 tq:1 rt:0 prq:1 1mp:0 1mb:0 1mt:0)

-EntranceNode1: Entrance1(t:0 pq:1 bq:0 tq:1 rt:0 prq:1 1mp:0 1mb:0 1mt:0)

--nodeA(t:0 pq:1 bq:0 tq:1 rt:0 prq:1 1mp:0 1mb:0 1mt:0)

-EntranceNode2: Entrance1(t:0 pq:1 bq:0 tq:1 rt:0 prq:1 1mp:0 1mb:0 1mt:0)

--nodeA(t:0 pq:1 bq:0 tq:1 rt:0 prq:1 1mp:0 1mb:0 1mt:0)


t:threadNum  pq:passQps  bq:blockedQps  tq:totalQps  rt:averageRt  prq: passRequestQps 1mp:1m-passed 1mb:1m-blocked 1mt:1m-total

1.

2.

3.

4.

5.

6.

7.

localhost:8719是我們引入Transport 模組(sentinel-transport-simple-http)後,對Sentinel控制檯暴露的端點資料介面。後續我們在Sentinel控制檯接入的時候再說。


ClusterBuilderSlot

此插槽用於構建資源的 ClusterNode 以及呼叫來源節點。ClusterNode 保持資源執行統計資訊(響應時間、QPS、block 數目、執行緒數、異常數等)以及原始呼叫者統計資訊列表。來源呼叫者的名字由 ContextUtil.enter(contextName,origin) 中的 origin 標記。可透過如下命令檢視某個資源不同呼叫者的訪問情況:curl :


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

1.

2.

3.

4.

StatisticSlot

StatisticSlot 是 Sentinel 的核心功能插槽之一,用於統計實時的呼叫資料。


clusterNode:資源標識的 ClusterNode 的 runtime 統計

origin:根據來自不同呼叫者的統計資訊

defaultnode: 根據上下文條目名稱和資源 ID 的 runtime 統計

入口的統計

Sentinel 底層採用高效能的滑動視窗資料結構 LeapArray 來統計實時的秒級指標資料,可以很好地支撐寫多於讀的高併發場景。




FlowSlot

這個 slot 主要根據預設的資源的統計資訊,按照固定的次序,依次生效。如果一個資源對應兩條或者多條流控規則,則會根據如下次序依次檢驗,直到全部透過或者有一個規則生效為止:


指定應用生效的規則,即針對呼叫方限流的;

呼叫方為 other 的規則;

呼叫方為 default 的規則。

DegradeSlot

這個 slot 主要針對資源的平均響應時間(RT)以及異常比率,來決定資源是否在接下來的時間被自動熔斷掉。


SystemSlot

這個 slot 會根據對於當前系統的整體情況,對入口資源的呼叫進行動態調配。其原理是讓入口的流量和當前系統的預計容量達到一個動態平衡。


注意系統規則只對入口流量起作用(呼叫型別為 EntryType.IN),對出口流量無效。可透過 SphU.entry(res, entryType) 指定呼叫型別,如果不指定,預設是EntryType.OUT。


注:本文大部分內容摘自官網,可做了解,為後續的學習打下理論基礎。



來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70030722/viewspace-3002109/,如需轉載,請註明出處,否則將追究法律責任。

相關文章