gateway sentinel 熔断 不起作用_Sentinel 的一些概念与核心类介绍
了解 Sentinel 的一些概念
- 資源:資源是 Sentinel 的關(guān)鍵概念。資源,可以是一個(gè)方法、一段代碼、由應(yīng)用提供的接口,或者由應(yīng)用調(diào)用其它應(yīng)用的接口。
- 規(guī)則:圍繞資源的實(shí)時(shí)狀態(tài)設(shè)定的規(guī)則,包括流量控制規(guī)則、熔斷降級(jí)規(guī)則以及系統(tǒng)保護(hù)規(guī)則、自定義規(guī)則。
- 降級(jí):在流量劇增的情況下,為保證系統(tǒng)能夠正常運(yùn)行,根據(jù)資源的實(shí)時(shí)狀態(tài)、訪問流量以及系統(tǒng)負(fù)載有策略的拒絕掉一部分流量。
Sentinel 資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)相關(guān)的類
Sentinel 中指標(biāo)數(shù)據(jù)統(tǒng)計(jì)以資源為維度。資源使用 ResourceWrapper 對(duì)象表示,我們把 ResourceWrapper 對(duì)象稱為資源 ID。如果一個(gè)資源描述的是一個(gè)接口,那么資源名稱通常就是接口的 url,例如“GET:/v1/demo”。
ResourceWrapper
public abstract class ResourceWrapper { protected final String name; protected final EntryType entryType; protected final int resourceType; public ResourceWrapper(String name, EntryType entryType, int resourceType) { this.name = name; this.entryType = entryType; this.resourceType = resourceType; }}復(fù)制ResourceWrapper 有三個(gè)字段:
- name 為資源名稱,例如:“GET:/v1/demo”。
- entryType 為流量類型,即流入流量還是流出流量,通俗點(diǎn)說就是發(fā)起請(qǐng)求還是接收請(qǐng)求。
- resourceType 表示資源的類型,例如 Dubbo RPC、Web MVC 或者 API Gateway 網(wǎng)關(guān)。
EntryType 是一個(gè)枚舉類型:
public enum EntryType { IN("IN"), OUT("OUT");}復(fù)制可以把 IN 和 OUT 簡單理解為接收處理請(qǐng)求與發(fā)送請(qǐng)求。當(dāng)接收到別的服務(wù)或者前端發(fā)來的請(qǐng)求,那么 entryType 為 IN;當(dāng)向其他服務(wù)發(fā)起請(qǐng)求時(shí),那么 entryType 就為 OUT。例如,在消費(fèi)端向服務(wù)提供者發(fā)送請(qǐng)求,當(dāng)請(qǐng)求失敗率達(dá)到多少時(shí)觸發(fā)熔斷降級(jí),那么服務(wù)消費(fèi)端為實(shí)現(xiàn)熔斷降級(jí)就需要統(tǒng)計(jì)資源的 OUT 類型流量。
Sentinel 目前支持的資源類型有以下幾種:
public final class ResourceTypeConstants { public static final int COMMON = 0; public static final int COMMON_WEB = 1; public static final int COMMON_RPC = 2; public static final int COMMON_API_GATEWAY = 3; public static final int COMMON_DB_SQL = 4;}復(fù)制- COMMON:默認(rèn)
- COMMON_WEB:Web 應(yīng)用的接口
- COMMON_RPC:Dubbo 框架的 RPC 接口
- COMMON_API_GATEWAY:用于 API Gateway 網(wǎng)關(guān)
- COMMON_DB_SQL:數(shù)據(jù)庫 SQL 操作
Node
Node 用于持有實(shí)時(shí)統(tǒng)計(jì)的指標(biāo)數(shù)據(jù),Node 接口定義了一個(gè) Node 類所需要提供的各項(xiàng)指標(biāo)數(shù)據(jù)統(tǒng)計(jì)的相關(guān)功能,為外部屏蔽滑動(dòng)窗口的存在。提供記錄請(qǐng)求被拒絕、請(qǐng)求被放行、請(qǐng)求處理異常、請(qǐng)求處理成功的方法,以及獲取當(dāng)前時(shí)間窗口統(tǒng)計(jì)的請(qǐng)求總數(shù)、平均耗時(shí)等方法。Node 接口源碼如下。
public interface Node extends OccupySupport, DebugSupport { long totalRequest(); // 獲取總的請(qǐng)求數(shù) long totalPass(); // 獲取通過的請(qǐng)求總數(shù) long totalSuccess(); // 獲取成功的請(qǐng)求總數(shù) long blockRequest(); // 獲取被 Sentinel 拒絕的請(qǐng)求總數(shù) long totalException(); // 獲取異常總數(shù) double passQps(); // 通過 QPS double blockQps(); // 拒絕 QPS double totalQps(); // 總 qps double successQps(); // 成功 qps double maxSuccessQps(); // 最大成功總數(shù) QPS(例如秒級(jí)滑動(dòng)窗口的數(shù)組大小默認(rèn)配置為 2,則取數(shù)組中最大) double exceptionQps(); // 異常 QPS double avgRt(); // 平均耗時(shí) double minRt(); // 最小耗時(shí) int curThreadNum(); // 當(dāng)前并發(fā)占用的線程數(shù) double previousBlockQps(); // 前一個(gè)時(shí)間窗口的被拒絕 qps double previousPassQps(); // 前一個(gè)時(shí)間窗口的通過 qps Map metrics(); List rawMetricsInMin(Predicate timePredicate); void addPassRequest(int count); // 添加通過請(qǐng)求數(shù) void addRtAndSuccess(long rt, int success); // 添加成功請(qǐng)求數(shù),并且添加處理成功的耗時(shí) void increaseBlockQps(int count); // 添加被拒絕的請(qǐng)求數(shù) void increaseExceptionQps(int count); // 添加異常請(qǐng)求數(shù) void increaseThreadNum(); // 自增占用線程 void decreaseThreadNum(); // 自減占用線程 void reset(); // 重置滑動(dòng)窗口}復(fù)制它的幾個(gè)實(shí)現(xiàn)類:DefaultNode、ClusterNode、EntranceNode、StatisticNode 的關(guān)系如下圖所示。
StatisticNode
Statistic 即統(tǒng)計(jì)的意思,StatisticNode 是 Node 接口的實(shí)現(xiàn)類,是實(shí)現(xiàn)實(shí)時(shí)指標(biāo)數(shù)據(jù)統(tǒng)計(jì) Node。
public class StatisticNode implements Node { // 秒級(jí)滑動(dòng)窗口,2 個(gè)時(shí)間窗口大小為 500 毫秒的 Bucket private transient volatile Metric rollingCounterInSecond = new ArrayMetric(2,1000); // 分鐘級(jí)滑動(dòng)窗口,60 個(gè) Bucket 數(shù)組,每個(gè) Bucket 統(tǒng)計(jì)的時(shí)間窗口大小為 1 秒 private transient Metric rollingCounterInMinute = new ArrayMetric(60, 60 * 1000, false); // 統(tǒng)計(jì)并發(fā)使用的線程數(shù) private LongAdder curThreadNum = new LongAdder();}復(fù)制如代碼所示,一個(gè) StatisticNode 包含一個(gè)秒級(jí)和一個(gè)分鐘級(jí)的滑動(dòng)窗口,以及并行線程數(shù)計(jì)數(shù)器。秒級(jí)滑動(dòng)窗口用于統(tǒng)計(jì)實(shí)時(shí)的 QPS,分鐘級(jí)的滑動(dòng)窗口用于保存最近一分鐘內(nèi)的歷史指標(biāo)數(shù)據(jù),并行線程計(jì)數(shù)器用于統(tǒng)計(jì)當(dāng)前并行占用的線程數(shù)。
StatisticNode 的分鐘級(jí)和秒級(jí)滑動(dòng)窗口統(tǒng)計(jì)的指標(biāo)數(shù)據(jù)分別有不同的用處。例如,StatisticNode 記錄請(qǐng)求成功和請(qǐng)求執(zhí)行耗時(shí)的方法中調(diào)用了兩個(gè)滑動(dòng)窗口的對(duì)應(yīng)指標(biāo)項(xiàng)的記錄方法,代碼如下:
@Override public void addRtAndSuccess(long rt, int successCount) { // 秒級(jí)滑動(dòng)窗口 rollingCounterInSecond.addSuccess(successCount); rollingCounterInSecond.addRT(rt); // 分鐘級(jí)滑動(dòng)窗口 rollingCounterInMinute.addSuccess(successCount); rollingCounterInMinute.addRT(rt); }復(fù)制獲取前一秒被 Sentinel 拒絕的請(qǐng)求總數(shù)從分鐘級(jí)滑動(dòng)窗口獲取,代碼如下:
@Overridepublic double previousBlockQps() { return this.rollingCounterInMinute.previousWindowBlock();}復(fù)制而獲取當(dāng)前一秒內(nèi)已經(jīng)被 Sentinel 拒絕的請(qǐng)求總數(shù)則從秒級(jí)滑動(dòng)窗口獲取,代碼如下:
@Overridepublic double blockQps() { return rollingCounterInSecond.block() / rollingCounterInSecond.getWindowIntervalInSec();}復(fù)制獲取最小耗時(shí)也是從秒級(jí)的滑動(dòng)窗口取的,代碼如下:
@Override public double minRt() { // 秒級(jí)滑動(dòng)窗口 return rollingCounterInSecond.minRt(); }復(fù)制由于方法比較多,這里就不詳細(xì)介紹每個(gè)方法的實(shí)現(xiàn)了。
StatisticNode 還負(fù)責(zé)統(tǒng)計(jì)并行占用的線程數(shù),用于實(shí)現(xiàn)信號(hào)量隔離,按資源所能并發(fā)占用的最大線程數(shù)實(shí)現(xiàn)限流。當(dāng)接收到一個(gè)請(qǐng)求就將 curThreadNum 自增 1,當(dāng)處理完請(qǐng)求時(shí)就將 curThreadNum 自減一,如果同時(shí)處理 10 個(gè)請(qǐng)求,那么 curThreadNum 的值就為 10。
假設(shè)我們配置 tomcat 處理請(qǐng)求的線程池大小為 200,通過控制并發(fā)線程數(shù)實(shí)現(xiàn)信號(hào)量隔離的好處就是不讓一個(gè)接口同時(shí)使用完這 200 個(gè)線程,避免因?yàn)橐粋€(gè)接口響應(yīng)慢將 200 個(gè)線程都阻塞導(dǎo)致應(yīng)用無法處理其他請(qǐng)求的問題,這也是實(shí)現(xiàn)信號(hào)量隔離的目的。
DefaultNode
DefaultNode 是實(shí)現(xiàn)以資源為維度的指標(biāo)數(shù)據(jù)統(tǒng)計(jì)的 Node,是將資源 ID 和 StatisticNode 映射到一起的 Node。
public class DefaultNode extends StatisticNode { private ResourceWrapper id; private volatile Set childList = new HashSet<>(); private ClusterNode clusterNode; public DefaultNode(ResourceWrapper id, ClusterNode clusterNode) { this.id = id; this.clusterNode = clusterNode; }}復(fù)制如代碼所示,DefaultNode 是 StatisticNode 的子類,構(gòu)造方法要求傳入資源 ID,表示該 Node 用于統(tǒng)計(jì)哪個(gè)資源的實(shí)時(shí)指標(biāo)數(shù)據(jù),指標(biāo)數(shù)據(jù)統(tǒng)計(jì)則由父類 StatisticNode 完成。
DefaultNode 字段說明:
- id:資源 ID,ResourceWrapper 對(duì)象。
- childList:childList 是一個(gè) Node(DefaultNode)集合,用于存放子節(jié)點(diǎn)。
- clusterNode:clusterNode 字段是一個(gè) ClusterNode,ClusterNode 也是 StatisticNode 的子類。
我們回顧下 Sentinel 的基本使用:
ContextUtil.enter("上下文名稱,例如:sentinel_spring_web_context");Entry entry = null;try { entry = SphU.entry("資源名稱,例如:/rpc/openfein/demo", EntryType.IN (或者 EntryType.OUT)); // 執(zhí)行業(yè)務(wù)方法 return doBusiness();} catch (Exception e) { if (!(e instanceof BlockException)) { Tracer.trace(e); } throw e;} finally { if (entry != null) { entry.exit(1); } ContextUtil.exit();}復(fù)制如上代碼所示,doBusiness 業(yè)務(wù)方法被 Sentinel 保護(hù),當(dāng) doBusiness 方法被多層保護(hù)時(shí),就可能對(duì)同一個(gè)資源創(chuàng)建多個(gè) DefaultNode。一個(gè)資源理論上可能有多個(gè) DefaultNode,是否有多個(gè) DefaultNode 取決于是否存在多個(gè) Context,即當(dāng)前調(diào)用鏈路上是否多次調(diào)用 ContextUtil#enter 方法,是否每次調(diào)用 ContextUtil#enter 方法都會(huì)創(chuàng)建一個(gè) Context。
特別加上“理論上”,是因?yàn)樵谝粋€(gè)線程中,調(diào)用多次 ContextUtil#enter 方法,只有第一次調(diào)用會(huì)創(chuàng)建 Context,ContextUtil 使用 ThreadLocal 存儲(chǔ) Context,所以后續(xù)的調(diào)用都會(huì)使用之前創(chuàng)建的 Context,而 DefaultNode 是在 NodeSelectorSlot 中創(chuàng)建的,使用 Map 緩存,key 為 Context#name,所以在使用同一個(gè) Context 的情況下,只會(huì)為一個(gè)資源創(chuàng)建一個(gè) DefaultNode。這部分內(nèi)容在介紹 NodeSelectorSlot 時(shí)再作詳細(xì)介紹。
ClusterNode
Sentinel 使用 ClusterNode 統(tǒng)計(jì)每個(gè)資源全局的指標(biāo)數(shù)據(jù),以及統(tǒng)計(jì)該資源按調(diào)用來源區(qū)分的指標(biāo)數(shù)據(jù)。全局?jǐn)?shù)據(jù)指的是不區(qū)分調(diào)用鏈路,一個(gè)資源 ID 只對(duì)應(yīng)一個(gè) ClusterNode。
public class ClusterNode extends StatisticNode { // 資源名稱 private final String name; // 資源類型 private final int resourceType; // 來源指標(biāo)數(shù)據(jù)統(tǒng)計(jì) private Map originCountMap = new HashMap<>(); // 控制并發(fā)修改 originCountMap 用的鎖 private final ReentrantLock lock = new ReentrantLock(); public ClusterNode(String name, int resourceType) { this.name = name; this.resourceType = resourceType; }} 復(fù)制ClusterNode 字段說明:
- name:資源名稱。很奇怪,這里沒有使用 ResourceWrapper,是版本歷史問題,還是因?yàn)?ClusterNode 不需要判斷流量類型。
- resourceType:資源類型。
- originCountMap:維護(hù)每個(gè)調(diào)用來源的指標(biāo)數(shù)據(jù)統(tǒng)計(jì)數(shù)據(jù)(StatisticNode),其用途是什么,在使用到時(shí)再做分析。
EntranceNode
EntranceNode 是一個(gè)特殊的 Node,它繼承 DefaultNode,用于維護(hù)一顆樹,從根節(jié)點(diǎn)到每個(gè)葉子節(jié)點(diǎn)都是不同請(qǐng)求的調(diào)用鏈路,所經(jīng)過的每個(gè)節(jié)點(diǎn)都對(duì)應(yīng)著調(diào)用鏈路上被 Sentinel 保護(hù)的資源,一個(gè)請(qǐng)求調(diào)用鏈路上的節(jié)點(diǎn)順序正是資源被訪問的順序。
public class EntranceNode extends DefaultNode { public EntranceNode(ResourceWrapper id, ClusterNode clusterNode) { super(id, clusterNode); }}復(fù)制在一個(gè) Web MVC 應(yīng)用中,每個(gè)接口就是一個(gè)資源,Sentinel 通過 Spring MVC 攔截器攔截每個(gè)接口的入口,統(tǒng)一創(chuàng)建名為“sentinel_spring_web_context”的 Context,名稱相同的 Context 都使用同一個(gè) EntranceNode。一個(gè) Web 應(yīng)用可能有多個(gè)接口,而 childList 就用于存儲(chǔ)每個(gè)接口對(duì)應(yīng)的 DefaultNode。
如果想統(tǒng)計(jì)一個(gè)應(yīng)用的所有接口(不一定是所有,沒有被調(diào)用過的接口不會(huì)創(chuàng)建對(duì)應(yīng)的 DefaultNode)總的 QPS,只需要調(diào)用 EntranceNode 的 totalQps 就能獲取到。EntranceNode 的 totalQps 方法代碼如下:
@Override public double totalQps() { double r = 0; // 遍歷 childList for (Node node : getChildList()) { r += node.totalQps(); } return r; }復(fù)制EntranceNode、DefaultNode、ClusterNode 與滑動(dòng)窗口的關(guān)系如下圖所示:
Sentinel 中的 Context 與 Entry
理解 Context 與 Entry 也是理解 Sentinel 整個(gè)工作流程的關(guān)鍵,其中 Entry 還會(huì)涉及到“調(diào)用樹”這一概念。
Context
Context 代表調(diào)用鏈路上下文,貫穿一次調(diào)用鏈路中的所有 Entry。Context 維持著入口節(jié)點(diǎn)(entranceNode)、本次調(diào)用鏈路的 curNode、調(diào)用來源(origin)等信息。Context 名稱即為調(diào)用鏈路入口名稱。
Context 通過 ThreadLocal 傳遞,只在調(diào)用鏈路的入口處創(chuàng)建。
假設(shè)服務(wù)B提供一個(gè)查詢天氣預(yù)報(bào)的接口給服務(wù)A調(diào)用,服務(wù)B實(shí)現(xiàn)查詢天氣預(yù)報(bào)的接口是調(diào)用第三方服務(wù)C實(shí)現(xiàn)的,服務(wù)B是一個(gè) MVC 應(yīng)用,同時(shí)服務(wù)B調(diào)用服務(wù) C 接口使用 OpenFeign 實(shí)現(xiàn) RPC 調(diào)用。那么,服務(wù) B 即使用了 Sentinel 的 MVC 適配模塊,也使用了 Sentinel 的 OpenFeign 適配模塊。
當(dāng)服務(wù) B 接收到服務(wù) A 請(qǐng)求時(shí),會(huì)創(chuàng)建一個(gè)名為“sentinel_spring_web_context”的 Context,服務(wù) B 在向服務(wù) C 發(fā)起接口調(diào)用時(shí)由于當(dāng)前線程已經(jīng)存在一個(gè) Context,所以還是用“sentinel_spring_web_context”這個(gè) Context,代表是同一個(gè)調(diào)用鏈路入口。
舉個(gè)不恰當(dāng)?shù)睦?#xff1a;
- 路徑一:A.a()-> 調(diào)用 -> B.b()-> 調(diào)用 C.c(),A.a() 為該調(diào)用鏈路的入口,入口名稱為“a_context”。
- 路徑二:D.d()-> 調(diào)用 -> B.b()-> 調(diào)用 C.c(),D.d() 為該調(diào)用鏈路的入口,入口名稱為“d_context”。
那么,每次調(diào)用 A.a() 方法都會(huì)創(chuàng)建名為“a_context”的 Context,每次調(diào)用 B.b() 方法都會(huì)創(chuàng)建名為“b_context”的 Context。如果 A.a() 同時(shí)有 20 個(gè)請(qǐng)求,那么就會(huì)創(chuàng)建 20 個(gè)名為“a_context”的 Context,Context 代表了這 20 個(gè)請(qǐng)求每個(gè)請(qǐng)求的調(diào)用鏈路上下文,而路徑一就是這 20 個(gè)請(qǐng)求相同的調(diào)用鏈路。
Context 的字段定義如下:
public class Context { private final String name; private DefaultNode entranceNode; private Entry curEntry; private String origin = ""; // 我們不討論異步的情況 // private final boolean async;}復(fù)制- name:Context 的名稱。
- entranceNode:當(dāng)前調(diào)用樹的入口節(jié)點(diǎn),類型為 EntranceNode。同一個(gè)入口的資源,每個(gè)資源對(duì)應(yīng)一個(gè) DefaultNode,entranceNode#childList 用于存儲(chǔ)這些資源的 DefaultNode。
- curEntry:當(dāng)前 Entry(CtEntry)。
- origin:調(diào)用來源的名稱,即服務(wù)消費(fèi)者的名稱或者服務(wù)消費(fèi)者的來源 IP,取決于服務(wù)消費(fèi)者是否使用 Sentinel,由 Sentinel 適配層傳遞過來。例如:服務(wù)提供者是 Spring MVC 應(yīng)用,且服務(wù)提供者使用 Sentinel 的 Web MVC 適配,那么 Sentinel 會(huì)嘗試從請(qǐng)求頭獲取"S-user",如果服務(wù)消費(fèi)者有在請(qǐng)求頭傳遞這個(gè)參數(shù),那么就能夠獲取到。
Entry(CtEntry)
在調(diào)用 Context#getCurNode 方法獲取調(diào)用鏈路上當(dāng)前訪問到的資源的 DefaultNode 時(shí),實(shí)際是從 Context#curEntry 獲取的,Entry 維護(hù)了當(dāng)前資源的 DefaultNode,以及調(diào)用來源的 StatisticNode。Entry 抽象類字段的定義如下。
public abstract class Entry implements AutoCloseable { private static final Object[] OBJECTS0 = new Object[0]; private long createTime; // 當(dāng)前節(jié)點(diǎn)(DefaultNode) private Node curNode; // 來源節(jié)點(diǎn) private Node originNode; private Throwable error; // 資源 protected ResourceWrapper resourceWrapper;}復(fù)制CtEntry 是 Entry 的直接子類,后面分析源碼時(shí),我們所說 Entry 皆指 CtEntry。CtEntry 中聲明的字段信息如下代碼所示。
class CtEntry extends Entry { // 當(dāng)前 Entry 指向的父 Entry protected Entry parent = null; // 父 Entry 指向當(dāng)前 Entry protected Entry child = null; // 當(dāng)前資源的 ProcessorSlotChain protected ProcessorSlot chain; // 當(dāng)前上下文 protected Context context;}復(fù)制CtEntry 用于維護(hù)父子 Entry,每一次調(diào)用 SphU#entry 方法都會(huì)創(chuàng)建一個(gè) CtEntry。如果服務(wù) B 在處理一個(gè)請(qǐng)求的路徑上會(huì)多次調(diào)用 SphU#entry,那么這些 CtEntry 會(huì)構(gòu)成一個(gè)雙向鏈表。在每次創(chuàng)建 CtEntry,都會(huì)將 Context.curEntry 設(shè)置為這個(gè)新的 CtEntry,雙向鏈表的作用就是在調(diào)用 CtEntry#exit 方法時(shí),能夠?qū)?Context.curEntry 還原為上一個(gè)資源的 CtEntry。
例如,在服務(wù) B 接收到服務(wù) A 的請(qǐng)求時(shí),會(huì)調(diào)用 SphU#entry 方法創(chuàng)建一個(gè) CtEntry,我們?nèi)€(gè)代號(hào) ctEntry1,此時(shí)的 ctEntry1 的父節(jié)點(diǎn)(parent)為空。當(dāng)服務(wù) B 向服務(wù) C 發(fā)起調(diào)用時(shí),OpenFeign 適配器調(diào)用 SphU#entry 的方法會(huì)創(chuàng)建一個(gè) CtEntry,我們?nèi)€(gè)代號(hào) ctEntry2,此時(shí) ctEntry2 的父節(jié)點(diǎn)(parent)就是 ctEntry1,ctEntry1 的子節(jié)點(diǎn)(child)就是 ctEntry2,如下圖所示。
ROOT 與調(diào)用樹
Constants 常量類用于聲明全局靜態(tài)常量,Constants 有一個(gè) ROOT 靜態(tài)字段,類型為 EntranceNode。
在調(diào)用 ContextUtil#enter 方法時(shí),如果還沒有為當(dāng)前入口創(chuàng)建 EntranceNode,則會(huì)為當(dāng)前入口創(chuàng)建 EntranceNode,將其賦值給 Context.entranceNode,同時(shí)也會(huì)將這個(gè) EntranceNode 添加到 Constants.ROOT 的子節(jié)點(diǎn)(childList)。資源對(duì)應(yīng)的 DefaultNode 則是在 NodeSelectorSlot 中創(chuàng)建,并賦值給 Context.curEntry.curNode。
Constants.ROOT、Context.entranceNode 與 Entry.curNode 三者關(guān)系如下圖所示。
Sentinel 中的 ProcessorSlot
ProcessorSlot 直譯就是處理器插槽,是 Sentinel 實(shí)現(xiàn)限流降級(jí)、熔斷降級(jí)、系統(tǒng)自適應(yīng)降級(jí)等功能的切入點(diǎn)。Sentinel 提供的 ProcessorSlot 可以分為兩類,一類是輔助完成資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)的切入點(diǎn),一類是實(shí)現(xiàn)降級(jí)功能的切入點(diǎn)。
輔助資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)的 ProcessorSlot:
- NodeSelectorSlot:為當(dāng)前資源創(chuàng)建 DefaultNode,并且將 DefaultNode 賦值給 Context.curEntry.curNode(見倒數(shù)第二張圖);如果當(dāng)前調(diào)用鏈路上只出現(xiàn)過一次 SphU#entry 的情況,將該 DefaultNode 添加到的 Context.entranceNode 的子節(jié)點(diǎn)(如倒數(shù)第一張圖所示,名為 sentinel_spring_web_context 的 EntranceNode),否則添加到 Context.curEntry.parent 的子節(jié)點(diǎn)(childList)。有點(diǎn)抽象,我們?cè)诜治?NodeSelectorSlot 源碼時(shí)再詳細(xì)介紹。
- ClusterBuilderSlot:如果當(dāng)前資源未創(chuàng)建 ClusterNode,則為資源創(chuàng)建 ClusterNode;將 ClusterNode 賦值給當(dāng)前資源的 DefaultNode.clusterNode;如果調(diào)用來源(origin)不為空,則為調(diào)用來源創(chuàng)建 StatisticNode,用于實(shí)現(xiàn)按調(diào)用來源統(tǒng)計(jì)資源的指標(biāo)數(shù)據(jù),ClusterNode 持有每個(gè)調(diào)用來源的 StatisticNode。
- StatisticSlot:這是 Sentinel 最為重要的類之一,用于實(shí)現(xiàn)指標(biāo)數(shù)據(jù)統(tǒng)計(jì)。先是調(diào)用后續(xù)的 ProcessorSlot#entry 判斷是否放行請(qǐng)求,再根據(jù)判斷結(jié)果進(jìn)行相應(yīng)的指標(biāo)數(shù)據(jù)統(tǒng)計(jì)操作。
實(shí)現(xiàn)降級(jí)功能的 ProcessorSlot:
- AuthoritySlot:實(shí)現(xiàn)黑白名單降級(jí)
- SystemSlot:實(shí)現(xiàn)系統(tǒng)自適應(yīng)降級(jí)
- FlowSlot:實(shí)現(xiàn)限流降級(jí)
- DegradeSlot:實(shí)現(xiàn)熔斷降級(jí)
關(guān)于每個(gè) ProcessorSlot 實(shí)現(xiàn)的功能,將在后續(xù)文章詳細(xì)分析。
總結(jié)
以上是生活随笔為你收集整理的gateway sentinel 熔断 不起作用_Sentinel 的一些概念与核心类介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: maven springboot 除去指
- 下一篇: opencv计算brox光流_字节跳动计