34. Sentinel 原理-實體類

Sentinel中有很多比較重要的概念,我們要了解一個框架,首先要對框架中重要的概念實體進行分析,本文我將跟大家一起來分析一下sentinel中非常重要的幾個概念。

Resource

resource是sentinel中最重要的一個概念,sentinel通過資源來保護具體的業務代碼或其他后方服務。sentinel把復雜的邏輯給屏蔽掉了,用戶只需要為受保護的代碼或服務定義一個資源,然后定義規則就可以了,剩下的通通交給sentinel來處理了。并且資源和規則是解耦的,規則甚至可以在運行時動態修改。定義完資源后,就可以通過在程序中埋點來保護你自己的服務了,埋點的方式有兩種:

  • try-catch 方式(通過 SphU.entry(...)),當 catch 到BlockException時執行異常處理(或fallback)
  • if-else 方式(通過 SphO.entry(...)),當返回 false 時執行異常處理(或fallback)

以上這兩種方式都是通過硬編碼的形式定義資源然后進行資源埋點的,對業務代碼的侵入太大,從0.1.1版本開始,sentinel加入了注解的支持,可以通過注解來定義資源,具體的注解為:SentinelResource 。通過注解除了可以定義資源外,還可以指定 blockHandlerfallback 方法。

在sentinel中具體表示資源的類是:ResourceWrapper ,他是一個抽象的包裝類,包裝了資源的 NameEntryType。他有兩個實現類,分別是:StringResourceWrapperMethodResourceWrapper

顧名思義,StringResourceWrapper 是通過對一串字符串進行包裝,是一個通用的資源包裝類,MethodResourceWrapper 是對方法調用的包裝。

image

Slot

slot是另一個sentinel中非常重要的概念,sentinel的工作流程就是圍繞著一個個插槽所組成的插槽鏈來展開的。需要注意的是每個插槽都有自己的職責,他們各司其職完好的配合,通過一定的編排順序,來達到最終的限流降級的目的。默認的各個插槽之間的順序是固定的,因為有的插槽需要依賴其他的插槽計算出來的結果才能進行工作。

但是這并不意味著我們只能按照框架的定義來,sentinel 通過 SlotChainBuilder 作為 SPI 接口,使得 Slot Chain 具備了擴展的能力。我們可以通過實現 SlotsChainBuilder 接口加入自定義的 slot 并自定義編排各個 slot 之間的順序,從而可以給 sentinel 添加自定義的功能。

那SlotChain是在哪創建的呢?是在 CtSph.lookProcessChain() 方法中創建的,并且該方法會根據當前請求的資源先去一個靜態的HashMap中獲取,如果獲取不到才會創建,創建后會保存到HashMap中。這就意味著,同一個資源會全局共享一個SlotChain

image

Context

context上下文是sentinel中一個比較難懂的概念。源碼中是這樣描述context類的:

This class holds metadata of current invocation

就是說在context中維護著當前調用鏈的元數據,那元數據有哪些呢,從context類的源碼中可以看到有:

  • entranceNode:當前調用鏈的入口節點
  • curEntry:當前調用鏈的當前entry
  • node:與當前entry所對應的curNode
  • origin:當前調用鏈的調用源
image

每次調用 SphU.entry()SphO.entry() 都需要在一個 context 中執行,如果沒有當前執行時還沒有 context,那么框架會使用默認的 context,默認的 context 是通過 MyContextUtil.myEnter() 創建的。

那如果我想自己在調用 SphU.entry()SphO.entry() 前,自己創建一個context該怎么操作呢?那可以通過調用 ContextUtil.enter() 方法來創建。

另外context是保存在ThreadLocal中的,每次執行的時候會優先到ThreadLocal中獲取。如果context為null時才會再次去創建一個context。

那什么時候context會被置為null并從ThreadLocal中清空呢?當Entry執行exit方法時,當當前entry的parent為null時,也就說明當前entry是最上層的節點了,此時要把保存在ThreadLocal中的context也清空掉。

在NodeSelectorSlot類中有一個Map保存了DefaultNode,但是key是用的contextName,而不是resourceName,這是為什么呢?

試想一下,如果用resourceName來做map的key,那對于同一個資源resourceA來說,在context1中獲取到的defaultNodeA和在context2中獲取到的defaultNodeA是同一個,那么怎么在這兩個context中對defaultNodeA進行更改呢,修改了一個必定會對另一個產生影響。

image

而如果用contextName來作為key,那對于同一個資源resourceA來說,在context1中獲取到的是defaultNodeA1,在context2中獲取到是defaultNodeA2,那在不同的context中對同一個資源可以使用不同的DefaultNode進行分別統計和計算,最后再通過ClusterNode進行合并就可以了。

image

所以在NodeSelectorSlot這個類里面,map里面保存的是contextName和DefaultNode的映射關系,目的是為了可以在不同的context對相同的資源進行分開統計。

同一個context中對同一個resource進行多次entry()調用時,會形式一顆調用樹,這個樹是通過CtEntry之間的parent/child關系維護的。

具體的調用鏈的原理分析可以參考筆者的另一篇文章:限流降級神器-哨兵(sentinel)的資源調用鏈原理分析

Entry

entry是sentinel中用來表示是否通過限流的一個憑證,就像一個token一樣。每次執行 SphU.entry()SphO.entry() 都會返回一個 Entry 給調用者,意思就是告訴調用者,如果正確返回了 Entry 給你,那表示你可以正常訪問被sentinel保護的后方服務了,否則sentinel會拋出一個BlockException(如果是 SphO.entry() 會返回false),這就表示調用者想要訪問的服務被保護了,也就是說調用者本身被限流了。

entry中保存了本次執行 entry() 方法的一些基本信息,包括:

  • createTime:當前Entry的創建時間,主要用來后期計算rt
  • node:當前Entry所關聯的node,該node主要是記錄了當前context下該資源的統計信息
  • origin:當前Entry的調用來源,通常是調用方的應用名稱,在 ClusterBuilderSlot.entry() 方法中設置的
  • resourceWrapper:當前Entry所關聯的資源

當在一個上下文中多次調用了 SphU.entry() 方法時,就會創建一個調用樹,這個樹的節點之間是通過parent和child關系維持的。

需要注意的是:parent和child是在 CtSph 類的一個私有內部類 CtEntry 中定義的,CtEntryEntry 的一個子類。
由于context中總是保存著調用鏈樹中的當前入口,所以當當前entry執行exit退出時,需要將parent設置為當前入口。

image

Node

node中保存了資源的實時統計數據,例如:passQps,blockQps,rt等實時數據。正是有了這些統計數據后,sentinel才能進行限流、降級等一系列的操作。

node是一個接口,他有一個實現類:StatisticNode,但是StatisticNode本身也有兩個子類,一個是DefaultNode,另一個是ClusterNode,DefaultNode又有一個子類叫EntranceNode。

其中entranceNode是每個上下文的入口,該節點是直接掛在root下的,是全局唯一的,每一個context都會對應一個entranceNode。另外defaultNode是記錄當前調用的實時數據的,每個defaultNode都關聯著一個資源和clusterNode,有著相同資源的defaultNode,他們關聯著同一個clusterNode。

image

Metric

metric是sentinel中用來進行實時數據統計的度量接口,node就是通過metric來進行數據統計的。而metric本身也并沒有統計的能力,他也是通過Window來進行統計的。

具體的統計原理,可以參考筆者另一篇文章:sentinel基于滑動時間窗口的實時指標統計原理分析

Metric有一個實現類:ArrayMetric,在ArrayMetric中主要是通過一個叫WindowLeapArray的對象進行窗口統計的。

image

作者:逅弈
鏈接:http://www.lxweimin.com/p/4a19f675ef5f

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374