一、概述
在 Sentinel 裡面,所有的資源都對應一個資源名稱(
resourceName
),每次資源調用都會建立一個
Entry
對象。Entry 可以通過對主流架構的适配自動建立,也可以通過注解的方式或調用
SphU
API 顯式建立。Entry 建立的時候,同時也會建立一系列功能插槽(slot chain),這些插槽有不同的職責,例如:
-
負責收集資源的路徑,并将這些資源的調用路徑,以樹狀結構存儲起來,用于根據調用路徑來限流降級;NodeSelectorSlot
-
則用于存儲資源的統計資訊以及調用者資訊,例如該資源的 RT, QPS, thread count 等等,這些資訊将用作為多元度限流,降級的依據;ClusterBuilderSlot
-
則用于記錄用于記錄塊異常,為故障排除提供具體的日志LogSlot
-
則用于記錄、統計不同緯度的 runtime 名額監控資訊;StatisticSlot
-
則用于根據預設的限流規則以及前面 slot 統計的狀态,來進行流量控制;FlowSlot
-
則根據配置的黑白名單和調用來源資訊,來做黑白名單控制;AuthoritySlot
-
則通過統計資訊以及預設的規則,來做熔斷降級;DegradeSlot
-
則通過系統的狀态,例如 load1 等,來控制總的入口流量;SystemSlot
下面是關系結構圖

二、LogSlot分析
1.LogSlot介紹
官方文檔是這樣描述LogSlot的:用于記錄塊異常,為故障排除提供具體的日志
2.源碼解讀
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode obj, int count, boolean prioritized, Object... args)
throws Throwable {
try {
fireEntry(context, resourceWrapper, obj, count, prioritized, args);
} catch (BlockException e) {
EagleEyeLogUtil.log(resourceWrapper.getName(), e.getClass().getSimpleName(), e.getRuleLimitApp(),
context.getOrigin(), count);
throw e;
} catch (Throwable e) {
RecordLog.warn("Unexpected entry exception", e);
}
}
@Override
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
try {
fireExit(context, resourceWrapper, count, args);
} catch (Throwable e) {
RecordLog.warn("Unexpected entry exit exception", e);
}
}
1.在entry階段這個slot沒有什麼業務邏輯,主要就是攔截了業務異常和Throwable級别的錯誤
2.如果是com.alibaba.csp.sentinel.slots.block.BlockException的異常,則将異常資訊用LogSlot專用的EagleEyeLogUtil記錄。
3.在exit階段,出現的日志是沒有記錄在EagleEyeLogUtil裡面的,因為沒有關于com.alibaba.csp.sentinel.slots.block.BlockException的異常的捕獲和攔截,直接為一個Throwable級别的catch。
作為
sentinel
執行序号第三的
slot
,和之前的
NodeSelectorSlot
,
ClusterBuilderSlot
最大的不同是,這個時候已經初始化好了必要的
DefaultSlot
和
ClusterSlot
,功能基本完備,處于
sentinle
的業務處理階段,由于責任鍊的調用模式,這裡攔截的資訊多為
BlockException
,我們可以了解為已識别的業務(sentinel的能力域邏輯)異常。是以使用了一個簡單粗暴的方式,直接
catch
住了下面所有
slot
的異常傳回。
多個相同的
resource
(name),對應着不同的
context
(name),那麼我們就可以快速統計出某個資源的總統計資訊。對應着多個(歸屬于同一個resource的)
DefaultNode
對應同一個
ClusterNode
。
三、StatisticSlot分析
1.StatisticSlot介紹
官方文檔是這樣描述StatisticSlot的:用于存儲資源的統計資訊以及調用者資訊,例如該資源的 RT, QPS, thread count 等等,這些資訊将用作為多元度限流,降級的依據,指的就是ClusterNode;
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args) throws Throwable {
if (clusterNode == null) {
synchronized (lock) {
if (clusterNode == null) {//1
// Create the cluster node.
clusterNode = new ClusterNode(resourceWrapper.getName(), resourceWrapper.getResourceType());
HashMap<ResourceWrapper, ClusterNode> newMap = new HashMap<>(Math.max(clusterNodeMap.size(), 16));
newMap.putAll(clusterNodeMap);
newMap.put(node.getId(), clusterNode);//2
clusterNodeMap = newMap;
}
}
}
node.setClusterNode(clusterNode);
/*
* if context origin is set, we should get or create a new {@link Node} of
* the specific origin.
*/
if (!"".equals(context.getOrigin())) {//3
Node originNode = node.getClusterNode().getOrCreateOriginNode(context.getOrigin());
context.getCurEntry().setOriginNode(originNode);
}
fireEntry(context, resourceWrapper, node, count, prioritized, args);
}
1.判斷
clusterNode
是否需要建立,需要就根據
rocourceName
建立一個
2.将
clusterNode
插入
clusterNodeMap
3.如果指定了
origin
還會創造來源次元的
node
,作為
origin
級别的統計
項目的
resource
共享了相同的
ProcessorSlotChain
,無論在關聯了哪個上下圍,資訊都被收集在
resource
對應的
ClusterNode
中,
clusterNodeMap
則存儲了所有
resource
的統計資訊。
四、小結
本期我們講述了Slot的子類
LogSlot
StatisticSlot
的基本實作原理。
現在建立我們的知識樹
執行個體化DefaultNode和ClusterNode,建立結構樹
建立上下文時,首先會在
NodeSelectorSlot
中判斷是否有
DefaultNode
如果沒有則新增一個基于
resource
的
DefaultNode
,然後執行下一個
slot
下一個
slot
是
ClusterBuilderSlot
ClusterBuilderSlot
會判斷是否有對應的
ClusterNode
,如果沒有則新增一個基于resource的
ClusterNode
并繼續下一個流程(
slot
)。
總結來說,這個兩個
slot
奠定了一個基于
resource
進行全局控制的基調。
進行資訊收集
LogSlot
在
DefaultNode
ClusterNode
初始化後,作為業務執行個體子產品的分界點,收集全局異常并處理。
StatisticSlot
作為全局統計的執行個體,依托于
ClusterNode
,将全局的
RT
,
QPS
thread
count
等等資訊存放在
clusterNodeMap
裡面。