Sentinel基本概念


 Sentinel是阿里開源的一款高性能的限流框架。這里將對Sentinel的使用和實現進行介紹。

 這里先介紹下Sentinel中涉及到的基本概念,包括使用上或者實現上。主要是筆者在閱讀文檔和源碼時經常會接觸到的對象。

Resource

 資源是整個Sentinel最基本的一個概念。可以是一段代碼,一個http請求,一個微服務,總而言之,他是Sentinel需要保證的實體。大部分情況下,我們可以使用方法簽名,URL或者是服務名稱來作為資源的名稱。它在Sentinel中的體現是:ResourceWrapper,他有兩個子類:

  1. StringResourceWrapper 使用string來標識一個資源

  2. MethodResouceWrapper 使用一個函數簽名來標識一個資源

Node

 節點是用來存儲統計數據的基本數據單元,Node本身只是一個接口,它有多個實現:

  1. StatisticNode 唯一的直接實現類,實現了流量統計的基本方法,在StatisticSlot中使用

  2. ClusterNode 繼承自StatisticNode,對於某一個資源的全局統計

  3. DefaultNode 繼承自StatisticNode,對於某一個資源在相應上下文中的實現,保存了一個指向ClusterNode的引用。另外還保存了子節點列表,當在同一個context下多次調用SphU.entry不同資源時會創建子節點

  4. EntranceNode 繼承自DefaultNode,代表一個調用的根節點,一個Context會對應到一個EntranceNode

Context

 上下文是用來保存當前調用的元數據,存儲在ThreadLocal中,它包含了幾個信息:

  1. EntranceNode 整個調用樹的根節點,即入口

  2. Entry 當前的調用點

  3. Node 關聯到當前調用點的統計信息

  4. Origin 通常用來標識調用方,這在我們需要按照調用方來區分流控策略的時候會非常有用

 每當我們調用SphU.entry()或者 SphO.entry()獲取訪問資源許可的時候都需要當前線程處在某個context中,如果我們沒有顯式調用ContextUtil.enter(),默認會使用Default context。如果我們在一個上下文中多次調用SphU.entry()來獲取多個資源,一個調用樹就會被創建出來

NullContext

 超過系統能夠創建的最大會話數則返回NullContext,后續不對該會話做過濾校驗,直接放過。

 Entry

 每次SphU.entry()調用都會返回一個Entry,Entry保持了所有關於當前資源調用的信息:

  1. createTime 這個資源調用的創建時間

  2. currentNode SphU.entry請求進入的資源在當前上下文中的統計數據Node

  3. originNode SphU.entry請求進入的資源對於特定origin調用方的統計數據node

 Entry的實現類為CtEntry,它其中除了上述信息之外,還保存了額外的信息:

  1. parent 調用樹鏈條中上一個entry

  2. child 調用樹鏈條中的下一個entry

  3. chain 當前調用資源所使用的限流工作責任鏈,包括各個Slot

  4. context 當前調用點所屬的上下文

EntryType

 EntryType 說的是這次請求的流量類型,共有兩種類型:IN 和 OUT 。

 IN:是指進入我們系統的入口流量,比如 http 請求或者是其他的 rpc 之類的請求。

 OUT:是指我們系統調用其他第三方服務的出口流量。

 入口、出口流量只有在配置了系統規則時才有效。

 設置Type 為 IN 是為了統計整個系統的流量水平,防止系統被打垮,用以自我保護的一種方式。

 設置Type 為 OUT 一方面是為了保護第三方系統,比如我們系統依賴了一個生成訂單號的接口,而這個接口是核心服務,如果我們的服務是非核心應用的話需要對他進行限流保護;另一方面也可以保護自己的系統,假設我們的服務是核心應用,而依賴的第三方應用老是超時,那這時可以通過設置依賴的服務的 rt 來進行降級,這樣就不至於讓第三方服務把我們的系統拖垮。

Slot

 Entry 創建的時候,同時也會創建一系列功能插槽(slot chain),這些插槽有不同的職責,例如:

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

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

  3. LogSlot 用於打印日志

  4. StatisticSlot 則用於記錄、統計不同緯度的 runtime 指標監控信息;

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

  6. AuthoritySlot 則根據配置的黑白名單和調用來源信息,來做黑白名單控制;

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

  8. DegradeSlot 則通過統計信息以及預設的規則,來做熔斷降級;

  Slot只綁定在CtEntry上

ProcessorSlotChain

 功能槽處理鏈,entry進入一個槽可以添加自己的動作,之后后fire動作會entry下一個槽,exit同理

注意,實現上相同資源共享一個ProcessorSlotChain ,可以跨Context

LimitApp

 流控規則中的 limitApp 字段用於根據調用來源進行流量控制。該字段的值有以下三種選項,分別對應不同的場景:

  1. default:表示不區分調用者,來自任何調用者的請求都將進行限流統計。如果這個資源名的調用總和超過了這條規則定義的閾值,則觸發限流。

  2. {some_origin_name}:表示針對特定的調用者,只有來自這個調用者的請求才會進行流量控制。例如 NodeA 配置了一條針對調用者caller1的規則,那么當且僅當來自 caller1 對 NodeA 的請求才會觸發流量控制。

  3. other:表示針對除 {some_origin_name} 以外的其余調用方的流量進行流量控制。例如,資源NodeA配置了一條針對調用者 caller1 的限流規則,同時又配置了一條調用者為 other 的規則,那么任意來自非 caller1 對 NodeA 的調用,都不能超過 other 這條規則定義的閾值。

 同一個資源名可以配置多條規則,規則的生效順序為:{some_origin_name} > other > default

 介紹完了上面的基本概念,下面給出Sentinel的基本用法:


List<FlowRule> rules = new ArrayList<FlowRule>(); 
FlowRule rule1 = new FlowRule(); 
rule1.setResource(KEY); 
// set limit qps to 20 
rule1.setCount(20); 
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); 
rule1.setLimitApp("default"); 
rules.add(rule1);
​
Entry entry = null;
​
try { 
        entry = SphU.entry(KEY); 
        // token acquired, means pass,do biz logic 
} catch (BlockException e1) { 
        //block,handle block logic 
} catch (Exception e2) { 
        // biz exception,handle biz exception logic 
} finally { 
        if (entry != null) { 
                entry.exit(); 
        } 
}
​

 如上,為sentinel的基本用法:

 先設定好規則,在進入需要受保護的資源前,嘗試獲取token,若成功獲取token,則可以執行相關邏輯,否則拋出異常進行處理,最后釋放所獲得的token 。

file

個人公眾號:啊駝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM