阿裡Sentinel 基本概念主要包括下圖内容:
總體說明
從定義和運作兩種态勢,可以分為定義态:
- rule,規則,每個規則定義都關聯一個資源名稱,一個資源可以定義多個rule
- ruleManager ,規則管理
- slot,承載規則的卡槽
- Chain,多個slot組成的鍊,在老版本 Chain是hard code寫死的,1.8.1使用order 來定義,便于加入自定義slot
運作态:
- Entry :入口,入口會指定資源名稱
- Chain及slot: 執行鍊
- Context: 上下文,貫穿整個執行過程
- Node: 保留各種資料,如一定時間内的qps
- Metric:各種名額,儲存在node上,注意node還有非metric資料
- Resource: 被Entry保護的資源,可以通俗了解為所有rule通過後要執行的代碼
Resource
可以了解為Entry(後面會講)擷取成功要要執行的方法或者代碼 ,一般和Entry綁定在一起,如:
try (Entry entry = SphU.entry("HelloWorld")) {
// 被保護的邏輯
System.out.println("hello world");
} catch (BlockException ex) {
// 處理被流控的邏輯
System.out.println("blocked!");
}
或者annotation寫法:
@SentinelResource("HelloWorld")
public void helloWorld() {
// 資源中的邏輯
System.out.println("hello world");
}
以上代碼中的"HelloWorld" 被稱為資源名稱,用于關聯下面提到的slot及chain,也可以了解為通過resource name進行規則關聯。
目前隻有String和method兩種resource,對應的類定義資訊如下:
28 * @author qinan.qn
29 */
30: public class MethodResourceWrapper extends ResourceWrapper {
31
32 private final transient Method method;
25 * @author jialiang.linjl
26 */
27: public class StringResourceWrapper extends ResourceWrapper {
28
29 public StringResourceWrapper(String name, EntryType e) {
Entry
以下為Entry的官方說法:
每一次資源調用都會建立一個 Entry。Entry 包含了資源名、curNode(目前統計節點)、originNode(來源統計節點)等資訊。
CtEntry 為普通的 Entry,在調用 SphU.entry(xxx) 的時候建立。特性:Linked entry within current context(内部維護着 parent 和 child)
需要注意的一點:CtEntry 構造函數中會做調用鍊的變換,即将目前 Entry 接到傳入 Context 的調用鍊路上(setUpEntryFor)。
資源調用結束時需要 entry.exit()。exit 操作會過一遍 slot chain exit,恢複調用棧,exit context 然後清空 entry 中的 context 防止重複調用。
通俗來說,Entry就是進入sentinel的一系列資料(如CPU、QPS)擷取及規則判斷,如果這些規則判斷都通過了,就執行資源函數或者代碼。
Entry的執行過程就對應則一個或者多個規則集合體,有兩個實作類:
SphU.entry() 擷取失敗傳回異常
SphO.entry() 傳回true或者false
這兩個類的最終實作都是通過類CtSph實作的,可以參考如下代碼
public static boolean entry(String name, EntryType trafficType, int batchCount, Object... args) {
try {
Env.sph.entry(name, trafficType, batchCount, args);
} catch (BlockException e) {
return false;
} catch (Throwable e) {
RecordLog.warn("SphO fatal error", e);
return true;
}
return true;
}
public class Env {
public static final Sph sph = new CtSph();
static {
// If init fails, the process will exit.
InitExecutor.doInit();
}
}
chain及slot
沒有Entry在執行過程會去尋找對應的Chain
ProcessorSlot<Object> lookProcessChain(ResourceWrapper resourceWrapper) {
ProcessorSlotChain chain = chainMap.get(resourceWrapper);
if (chain == null) {
synchronized (LOCK) {
chain = chainMap.get(resourceWrapper);
if (chain == null) {
// Entry size limit.
if (chainMap.size() >= Constants.MAX_SLOT_CHAIN_SIZE) {
return null;
}
chain = SlotChainProvider.newSlotChain();
Map<ResourceWrapper, ProcessorSlotChain> newMap = new HashMap<ResourceWrapper, ProcessorSlotChain>(
chainMap.size() + 1);
newMap.putAll(chainMap);
newMap.put(resourceWrapper, chain);
chainMap = newMap;
}
}
}
return chain;
}
然後執行Chain上的slot(資料擷取或者檢測類),預設chain 的build 類是com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder
可以參考sentinel-demo-slot-chain-spi 進行修改
sentinel 自帶的主要slot如下
- NodeSelectorSlot 負責收集資源的路徑,并将這些資源的調用路徑,以樹狀結構存儲起來,用于根據調用路徑來限流降級;
- ClusterBuilderSlot 則用于存儲資源的統計資訊以及調用者資訊,例如該資源的 RT, QPS, thread count等等,這些資訊将用作為多元度限流,降級的依據;
- StatisticSlot 則用于記錄、統計不同緯度的 runtime 名額監控資訊
- FlowSlot 則用于根據預設的限流規則以及前面 slot 統計的狀态,來進行流量控制;
- AuthoritySlot則根據配置的黑白名單和調用來源資訊,來做黑白名單控制;
- DegradeSlot 則通過統計資訊以及預設的規則,來做熔斷降級
- SystemSlot 則通過系統的狀态,例如 load1 等,來控制總的入口流量;
Rule
Chain是内部執行,外部不能直接定義,外部定義是通過rules模式來實作的,可以參考sentinel-demo-basic 下的這四個子目錄下的代碼
這四個目錄對應四中規則:
- DegradeRule
- AuthorityRule
- FlowRule
- SystemRule
一個資源可以有以上4種規則中的多種進行合并判斷。
Context
context中維護着目前調用鍊的中繼資料
SphU.entry() 或 SphO.entry() 都需要在一個 context 中執行,如果沒有目前執行時還沒有 context,那麼架構會使用預設的 context,預設的 context 是通過 MyContextUtil.myEnter() 建立的
Node
Node 中儲存了資源的實時統計資料,例如:passQps,blockQps,rt等實時資料。正是有了這些統計資料後, Sentinel 才能進行限流、降級等一系列的操作。
Metric
Metric 是 Sentinel 中用來進行實時資料統計的度量接口,node就是通過metric來進行資料統計的。而metric本身也并沒有統計的能力,他也是通過Window來進行統計的。