Sentinel核心源碼解析
Sentinel是分布式系統的防御系統。以流量為切入點,通過動態設置的流量控制、服務熔斷等手段達到
保護系統的目的,通過服務降級增強服務被拒后用戶的體驗。
一、Sentinel工作原理
1 架構圖解析
若要讀懂Sentinel源碼,則必須要搞明白官方給出的Sentinel的架構圖。
微服務框架核心源碼深度解析<<大廠學院完結>>

Sentinel的核心骨架是ProcessorSlotChain。其將不同的 Slot 按照順序串在一起(責任鏈模式),從而將不同的功能組合在一起(限流、降級、系統保護)。系統會為每個資源創建一套SlotChain。
2 SPI機制
Sentinel槽鏈中各Slot的執行順序是固定好的。但並不是絕對不能改變的。Sentinel將ProcessorSlot 作為 SPI 接口進行擴展,使得 SlotChain 具備了擴展能力。用戶可以自定義Slot並編排Slot 間的順序。

3 Slot簡介
NodeSelectorSlot
負責收集資源的路徑,並將這些資源的調用路徑,以樹狀結構存儲起來,用於根據調用路徑來限流降。
ClusterBuilderSlot
用於存儲資源的統計信息以及調用者信息,例如該資源的 RT, QPS, thread count,Block count,Exception count 等等,這些信息將用作為多維度限流,降級的依據。簡單來說,就是用於構建ClusterNode。
StatisticSlot
用於記錄、統計不同緯度的 runtime 指標監控信息。
ParamFlowSlot
對應熱點流控。
FlowSlot
用於根據預設的限流規則以及前面 slot 統計的狀態,來進行流量控制。對應流控規則。
AuthoritySlot
根據配置的黑白名單和調用來源信息,來做黑白名單控制。對應授權規則。
DegradeSlot
通過統計信息以及預設的規則,來做熔斷降級。對應降級規則。
SystemSlot
通過系統的狀態,例如 load1 等,來控制總的入口流量。對應系統規則。
4 Context簡介
Context是對資源操作的上下文,每個資源操作必須屬於一個Context。如果代碼中沒有指定Context,則會創建一個name為sentinel_default_context的默認Context。一個Context生命周期中可以包含多個資源操作。Context生命周期中的最后一個資源在exit()時會清理該Conetxt,這也就意味着這個Context生命周期結束了。
5 Context代碼
// 創建一個來自於appA訪問的Context, // entranceOne為Context的name ContextUtil.enter("entranceOne", "appA"); // Entry就是一個資源操作對象 Entry resource1 = null; Entry resource2 = null; try { // 獲取資源resource1的entry resource1 = SphU.entry("resource1"); // 代碼能走到這里,說明當前對資源resource1的請求通過了流控 // 對資源resource1的相關業務處理。。。 // 獲取資源resource2的entry resource2 = SphU.entry("resource2"); // 代碼能走到這里,說明當前對資源resource2的請求通過了流控 // 對資源resource2的相關業務處理。。。 } catch (BlockException e) { // 代碼能走到這里,說明請求被限流, // 這里執行降級處理 } finally { if (resource1 != null) { resource1.exit(); } if (resource2 != null) { resource2.exit(); } } // 釋放Context ContextUtil.exit(); // --------------------------------------------------------
// 創建另一個來自於appA訪問的Context, // entranceTwo為Context的name ContextUtil.enter("entranceTwo", "appA"); // Entry就是一個資源操作對象 Entry resource3 = null; try { // 獲取資源resource2的entry resource2 = SphU.entry("resource2"); // 代碼能走到這里,說明當前對資源resource2的請求通過了流控 // 對資源resource2的相關業務處理。。。 // 獲取資源resource3的entry resource3 = SphU.entry("resource3"); // 代碼能走到這里,說明當前對資源resource3的請求通過了流控 // 對資源resource3的相關業務處理。。。 } catch (BlockException e) { // 代碼能走到這里,說明請求被限流, // 這里執行降級處理 } finally { if (resource2 != null) { resource2.exit(); } if (resource3 != null) { resource3.exit(); } } // 釋放Context ContextUtil.exit();
6 Node間的

Node:用於完成數據統計的接口
StatisticNode:統計節點,是Node接口的實現類,用於完成數據統計
EntranceNode:入口節點,一個Context會有一個入口節點,用於統計當前
Context的總體流量數據
DefaultNode:默認節點,用於統計一個資源在當前Context中的流量數據
ClusterNode:集群節點,用於統計一個資源在所有Context中的總體流量