天天看點

《一起學sentinel》四、Slot的子類及實作之LogSlot和StatisticSlot

一、概述

在 Sentinel 裡面,所有的資源都對應一個資源名稱(

resourceName

),每次資源調用都會建立一個

Entry

對象。Entry 可以通過對主流架構的适配自動建立,也可以通過注解的方式或調用

SphU

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

  • NodeSelectorSlot

    負責收集資源的路徑,并将這些資源的調用路徑,以樹狀結構存儲起來,用于根據調用路徑來限流降級;
  • ClusterBuilderSlot

    則用于存儲資源的統計資訊以及調用者資訊,例如該資源的 RT, QPS, thread count 等等,這些資訊将用作為多元度限流,降級的依據;
  • LogSlot

    則用于記錄用于記錄塊異常,為故障排除提供具體的日志
  • StatisticSlot

    則用于記錄、統計不同緯度的 runtime 名額監控資訊;
  • FlowSlot

    則用于根據預設的限流規則以及前面 slot 統計的狀态,來進行流量控制;
  • AuthoritySlot

    則根據配置的黑白名單和調用來源資訊,來做黑白名單控制;
  • DegradeSlot

    則通過統計資訊以及預設的規則,來做熔斷降級;
  • SystemSlot

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

下面是關系結構圖

《一起學sentinel》四、Slot的子類及實作之LogSlot和StatisticSlot

二、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

裡面。