Sentinel之Slots插槽源碼分析降級規(guī)則(六)

一炮捧、引子

除了流量控制以外贫奠,對調(diào)用鏈路中不穩(wěn)定的資源進(jìn)行熔斷降級也是保障高可用的重要措施之一他膳。由于調(diào)用關(guān)系的復(fù)雜性响逢,如果調(diào)用鏈路中的某個資源不穩(wěn)定,最終會導(dǎo)致請求發(fā)生堆積棕孙。Sentinel 熔斷降級會在調(diào)用鏈路中某個資源出現(xiàn)不穩(wěn)定狀態(tài)時(例如調(diào)用超時或異常比例升高)舔亭,對這個資源的調(diào)用進(jìn)行限制,讓請求快速失敗蟀俊,避免影響到其它的資源而導(dǎo)致級聯(lián)錯誤钦铺。當(dāng)資源被降級后,在接下來的降級時間窗口之內(nèi)欧漱,對該資源的調(diào)用都自動熔斷(默認(rèn)行為是拋出 DegradeException)职抡。

二、降級策略

我們通常用以下幾種方式來衡量資源是否處于穩(wěn)定的狀態(tài):

  • 平均響應(yīng)時間 (DEGRADE_GRADE_RT):當(dāng)資源的平均響應(yīng)時間超過閾值(DegradeRule 中的 count误甚,以 ms 為單位)之后,資源進(jìn)入準(zhǔn)降級狀態(tài)谱净。接下來如果持續(xù)進(jìn)入 5 個請求窑邦,它們的 RT 都持續(xù)超過這個閾值,那么在接下的時間窗口(DegradeRule 中的 timeWindow壕探,以 s 為單位)之內(nèi)冈钦,對這個方法的調(diào)用都會自動地返回(拋出 DegradeException)。
  • 異常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):當(dāng)資源的每秒異忱钋耄總數(shù)占通過量的比值超過閾值(DegradeRule 中的 count)之后,資源進(jìn)入降級狀態(tài)导盅,即在接下的時間窗口(DegradeRule 中的 timeWindow较幌,以 s 為單位)之內(nèi),對這個方法的調(diào)用都會自動地返回白翻。異常比率的閾值范圍是 [0.0, 1.0]乍炉,代表 0% - 100%绢片。
  • 異常數(shù) (DEGRADE_GRADE_EXCEPTION_COUNT):當(dāng)資源近 1 分鐘的異常數(shù)目超過閾值之后會進(jìn)行熔斷。

注意:異常降級僅針對業(yè)務(wù)異常岛琼,對 Sentinel 限流降級本身的異常(BlockException)不生效底循。為了統(tǒng)計(jì)異常比例或異常數(shù),需要通過 Tracer.trace(ex) 記錄業(yè)務(wù)異常槐瑞。示例:

Entry entry = null;
try {
  entry = SphU.entry(key, EntryType.IN, key);

  // Write your biz code here.
  // <<BIZ CODE>>
} catch (Throwable t) {
  if (!BlockException.isBlockException(t)) {
    //這里會統(tǒng)計(jì)異常數(shù)
    Tracer.trace(t);
  }
} finally {
  if (entry != null) {
    entry.exit();
  }
}

開源整合模塊熙涤,如 Sentinel Dubbo Adapter, Sentinel Web Servlet Filter 或 @SentinelResource 注解會自動統(tǒng)計(jì)業(yè)務(wù)異常,無需手動調(diào)用困檩。

三祠挫、源碼分析

3.1 DegradeSlot

public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, Object... args)
        throws Throwable {
       //規(guī)則檢查
        DegradeRuleManager.checkDegrade(resourceWrapper, context, node, count);
        fireEntry(context, resourceWrapper, node, count, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        fireExit(context, resourceWrapper, count, args);
    }
}

進(jìn)入DegradeRuleManager中,可以發(fā)現(xiàn)與前面的限流規(guī)則一樣窗看,這個是用于管理降級的類茸歧。
我們重點(diǎn)看下checkDegrade方法。

3.2 DegradeRuleManager

    public static void checkDegrade(ResourceWrapper resource, Context context, DefaultNode node, int count)
        throws BlockException {
        if (degradeRules == null) {
            return;
        }

        List<DegradeRule> rules = degradeRules.get(resource.getName());
        if (rules == null) {
            return;
        }

        for (DegradeRule rule : rules) {
            if (!rule.passCheck(context, node, count)) {
                throw new DegradeException(rule.getLimitApp());
            }
        }
    }
  1. degradeRule是對應(yīng)資源的額降級規(guī)則显沈,是一個map软瞎。
  2. 獲取到對應(yīng)資源的降級規(guī)則。
  3. 調(diào)用Degrade的passCheck檢測是否需要降級拉讯。
  4. 若降級了則拋出DegradeException異常涤浇。

3.3 DegradeRule

降級規(guī)則的參數(shù)

  • count: RT臨界值或者異常數(shù)、異常比列
  • timeWindow:降級的時間間隔魔慷,單位秒
  • grade:閾值類型RT只锭、異常數(shù)、異常比例

下面看下passCheck方法:

 @Override
    public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) {
        if (cut) {
            return false;
        }

        ClusterNode clusterNode = ClusterBuilderSlot.getClusterNode(this.getResource());
        if (clusterNode == null) {
            return true;
        }

        if (grade == RuleConstant.DEGRADE_GRADE_RT) {
            double rt = clusterNode.avgRt();
            if (rt < this.count) {
                passCount.set(0);
                return true;
            }

            // Sentinel will degrade the service only if count exceeds.
            if (passCount.incrementAndGet() < RT_MAX_EXCEED_N) {
                return true;
            }
        } else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
            double exception = clusterNode.exceptionQps();
            double success = clusterNode.successQps();
            long total = clusterNode.totalQps();
            // if total qps less than RT_MAX_EXCEED_N, pass.
            if (total < RT_MAX_EXCEED_N) {
                return true;
            }

            double realSuccess = success - exception;
            if (realSuccess <= 0 && exception < RT_MAX_EXCEED_N) {
                return true;
            }

            if (exception / success < count) {
                return true;
            }
        } else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
            double exception = clusterNode.totalException();
            if (exception < count) {
                return true;
            }
        }

        synchronized (lock) {
            if (!cut) {
                // Automatically degrade.
                cut = true;
                ResetTask resetTask = new ResetTask(this);
                pool.schedule(resetTask, timeWindow, TimeUnit.SECONDS);
            }

            return false;
        }
    }

關(guān)鍵參數(shù):

  1. cut:資源是否已經(jīng)降級標(biāo)志院尔,為true表示已經(jīng)降級了蜻展。
  2. passCount:若達(dá)到降級條件后,連續(xù)復(fù)合降級條件的次數(shù)邀摆,默認(rèn)為RT_MAX_EXCEED_N(5)次纵顾。

過程大致如下:

  1. 如果已經(jīng)降級了(cut為ture),則阻塞栋盹;否則獲取clusterNode施逾。
  2. 降級規(guī)則為RuleConstant.DEGRADE_GRADE_RT,先獲取資源的平均RT例获;若RT小于設(shè)置的閾值count汉额,則請求通過并設(shè)置passCount為0,否在判斷passCount是否小于5榨汤,若小于則請求通過蠕搜;否則請求阻塞。
  3. 降級規(guī)則為RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO異常比例時件余,先獲取資源的exception數(shù)讥脐,success數(shù)遭居,total數(shù)。若total數(shù)小于5請求通過旬渠;exception是小于5請求通過俱萍;異常比列exception/total小于設(shè)置的閾值則請求通過;否則請求阻塞告丢。
  4. 降級規(guī)則為RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT異常數(shù)時枪蘑,若異常數(shù)小于設(shè)置的閾值時則請求通過;否則請求阻塞岖免。
  5. 若上述有規(guī)則不滿足岳颇,則說明該資源需要降級;降級時需要先設(shè)置cut為true颅湘,并啟動一個定時任務(wù)來設(shè)置降級時間窗口后降級的重置话侧。該任務(wù)如下:
    private static final class ResetTask implements Runnable {

        private DegradeRule rule;

        ResetTask(DegradeRule rule) {
            this.rule = rule;
        }

        @Override
        public void run() {
            //設(shè)置passCount為0
            rule.getPassCount().set(0);
            //設(shè)置cut為false
            rule.setCut(false);
        }
    }

四、我的總結(jié)

  1. 介紹了Sentinel的j降級規(guī)則以及降級原理闯参。
  2. 降級有三種策略瞻鹏,rt,異常數(shù)鹿寨,異常比例新博;目前dashboard控制臺能夠設(shè)置應(yīng)該就只有rt和異常比例了。
  3. 通過設(shè)置passCount來避免出現(xiàn)偶爾一個請求異常的情況脚草,提高降級的準(zhǔn)確性赫悄。
  4. 生產(chǎn)環(huán)境下建議使用設(shè)置rt策略來控制降級。

以上內(nèi)容馏慨,若有不當(dāng)之處埂淮,請指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末写隶,一起剝皮案震驚了整個濱河市同诫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌樟澜,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叮盘,死亡現(xiàn)場離奇詭異秩贰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)柔吼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門毒费,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人愈魏,你說我怎么就攤上這事觅玻∠爰剩” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵溪厘,是天一觀的道長胡本。 經(jīng)常有香客問我,道長畸悬,這世上最難降的妖魔是什么侧甫? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮蹋宦,結(jié)果婚禮上披粟,老公的妹妹穿的比我還像新娘。我一直安慰自己冷冗,他們只是感情好守屉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蒿辙,像睡著了一般拇泛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上须板,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天碰镜,我揣著相機(jī)與錄音,去河邊找鬼习瑰。 笑死绪颖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的甜奄。 我是一名探鬼主播柠横,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼课兄!你這毒婦竟也來了牍氛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤烟阐,失蹤者是張志新(化名)和其女友劉穎搬俊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜒茄,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唉擂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了檀葛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玩祟。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖屿聋,靈堂內(nèi)的尸體忽然破棺而出空扎,到底是詐尸還是另有隱情藏鹊,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布转锈,位于F島的核電站盘寡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏黑忱。R本人自食惡果不足惜宴抚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望甫煞。 院中可真熱鬧菇曲,春花似錦、人聲如沸抚吠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽楷力。三九已至喊式,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間萧朝,已是汗流浹背岔留。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留检柬,地道東北人献联。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像何址,于是被迫代替她去往敵國和親里逆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容