ResourceWrapper
sentinel 控制的對(duì)象即為資源,調(diào)用entry方法的時(shí)候會(huì)new 一個(gè)資源對(duì)象,資源由一個(gè)全局唯一的資源名稱標(biāo)識(shí)。
Context
sentinel 的處理的上下文,包含了上下文名稱,一個(gè)調(diào)用鏈一個(gè)context,可以顯示創(chuàng)建或者在調(diào)用entry的時(shí)候隱式創(chuàng)建。
Node
持有運(yùn)行時(shí)的資源的各種統(tǒng)計(jì)數(shù)據(jù)。
- 一個(gè) resource 在同一個(gè)Context 中有且僅有一個(gè)DefaultNode 與之對(duì)應(yīng)
- 一個(gè) resource 全局有且僅有一個(gè)ClusterNode
Entry
代表一次對(duì)資源的訪問(wèn),每訪問(wèn)一個(gè)資源都會(huì)創(chuàng)建一個(gè)Entry,在context中以一個(gè)雙向鏈表存在。
必須調(diào)用exit() 方法的原因就在于這個(gè)鏈表:exit方法中會(huì)判斷上下文的當(dāng)前 entry 是不是 this,此時(shí)其他entry掉用exit會(huì)發(fā)現(xiàn)不想等,從而拋出異常。
ProcessorSlot
處理插槽,資源的各種控制都通過(guò)不同的 Slot 實(shí)現(xiàn)類去完成,包括
// com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder#build()
// 一個(gè)資源(不區(qū)分context)對(duì)應(yīng)一個(gè) chain
ProcessorSlotChain chain = new DefaultProcessorSlotChain();
// 構(gòu)建資源的調(diào)用路徑,并將這些資源的調(diào)用路徑,以樹狀結(jié)構(gòu)存儲(chǔ)起來(lái),用于根據(jù)調(diào)用路徑來(lái)限流降級(jí)
// 每個(gè)結(jié)點(diǎn)是一個(gè)DefaultNode(區(qū)分context)
chain.addLast(new NodeSelectorSlot());
// 構(gòu)建一個(gè) ClusterNode(不區(qū)分context) 用于存儲(chǔ)資源的統(tǒng)計(jì)信息以及調(diào)用者信息,跟 DefaultNode 的區(qū)別在于前者統(tǒng)計(jì)同一個(gè)資源的所有信息,而后者會(huì)區(qū)分 context 進(jìn)行統(tǒng)計(jì)
chain.addLast(new ClusterBuilderSlot());
// 通過(guò)一個(gè)try語(yǔ)句捕捉后續(xù)slot中的異常
chain.addLast(new LogSlot());
// 執(zhí)行統(tǒng)計(jì)操作,真正統(tǒng)計(jì)是在這一步,包括 線程數(shù)、pass/success request、block/exception qps、rt 等信息
chain.addLast(new StatisticSlot());
// 判斷系統(tǒng)是否過(guò)高,線程數(shù)、qps、rt、load
chain.addLast(new SystemSlot());
// 鑒權(quán)
chain.addLast(new AuthoritySlot());
// 限流
chain.addLast(new FlowSlot());
// 降級(jí)
chain.addLast(new DegradeSlot());
服務(wù)中會(huì)存在三種類型的統(tǒng)計(jì):
- 同一個(gè)資源區(qū)分 context 的
DefaultNode - 同一個(gè)資源不區(qū)分 context 的
ClusterNode· - 全局統(tǒng)計(jì)
Cluster Node, 用于系統(tǒng)負(fù)載的保護(hù)
ProcessorSlotChain
由各個(gè)處理插槽組成的鏈表,每個(gè)資源在整個(gè)服務(wù)中對(duì)應(yīng)一個(gè)處理鏈,內(nèi)容見(jiàn) ProcesserSlot
Rule
用戶定義的各種規(guī)則
RuleManager
加載并管理Rule
異步操作
前面提到必須調(diào)用exit()方法,對(duì)于資源的訪問(wèn)一般以下面的方式發(fā)起:
Entry entry = null;
try {
entry = SphU.entry(KEY);
// do something (1)
} catch (BlockException e1) {
// todo handle BlockException
} catch (Exception e2) {
// todo handle biz exception
} finally {
if (entry != null) {
entry.exit();
}
}
這個(gè)過(guò)程中會(huì)隱式創(chuàng)建一個(gè)ThreadLocal 的 Context ,假如我們想通過(guò)一個(gè)異步的操作去執(zhí)行 do something,這個(gè)過(guò)程線程會(huì)切換,導(dǎo)致exit操作不在同一個(gè)上下文。
Sentinel 上周提供了對(duì)異步的支持,增加了SphU.asyncEntry 方法創(chuàng)建一個(gè)AsyncEntry,在entry方法的finally語(yǔ)句塊中會(huì)馬上將其移出entry鏈表,后續(xù)需要將此AsyncEntry傳入到異步方法中,執(zhí)行exit 統(tǒng)計(jì)操作。