Alibaba Sentinel限流功能

前言

上周經(jīng)歷了合作方未按照約定在客戶端進行緩存忆家,以高QPS調(diào)用我這邊某個接口的問題携添,當時帶來的影響是接口RT變高袍睡,當時如果QPS繼續(xù)增加,將會導(dǎo)致整個應(yīng)用級別的服務(wù)不可用艺玲。那么有沒有辦法括蝠,來限制系統(tǒng)的某個服務(wù)被調(diào)用的QPS,以保護系統(tǒng)不會過載呢饭聚?Alibaba Sentinel就是這樣的一個產(chǎn)品忌警。本文只介紹限流的功能,Sentinel本身是極其強大的秒梳,支持流量控制法绵、熔斷降級、系統(tǒng)負載保護酪碘,詳見官方文檔朋譬。https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

Sentinel如何使用

引入maven依賴

<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
        </dependency>
  1. 若希望在代碼塊級別限流,使用SphU#entry和Entry#exit將代碼塊包住即可兴垦,這跟很多打點的工具是一樣的徙赢。
Entry entry = SphU.entry(resourceName);
businessCode();
entry.exit();

初始化流控規(guī)則配置見下,流控規(guī)則里面的resourceName和Entry初始化的時候一致即可。(Sentinel也支持控制臺的方式來配置限流規(guī)則)

private static void initFlowQpsRule() {
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(resourceName);
        // set limit qps to 20
        rule1.setCount(20);
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setLimitApp("default");
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }

這種在代碼塊級別硬編碼的方式并不是我們的主要場景探越,更多的時候狡赐,我們希望在某個服務(wù),或者某個接口級別進行限流钦幔,Sentinel支持注解的方式來配置限流枕屉。

@GetMapping("/hello")
    @SentinelResource("resourceName")
    public String hello() {
        return "Hello";
    }

只需要一個注解,即可添加限流功能节槐。

Sentinel執(zhí)行過程

使用注解來引入限流搀庶,其實就是使用了一個aop切面自動幫你初始化一個Entry,執(zhí)行完畢之后exit铜异。
詳見SentinelResourceAspect

@Around("sentinelResourceAnnotationPointcut()")
    public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
        Method originMethod = resolveMethod(pjp);

        SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class);
        if (annotation == null) {
            // Should not go through here.
            throw new IllegalStateException("Wrong state for SentinelResource annotation");
        }
        String resourceName = getResourceName(annotation.value(), originMethod);
        EntryType entryType = annotation.entryType();
        int resourceType = annotation.resourceType();
        Entry entry = null;
        try {
            entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
            Object result = pjp.proceed();
            return result;
        } catch (BlockException ex) {
            return handleBlockException(pjp, annotation, ex);
        }finally {
            if (entry != null) {
                entry.exit(1, pjp.getArgs());
            }
        }

整個限流的核心就在SphU#entry方法哥倔,如果被限流攔截,就拋出異常BlockException揍庄,不再執(zhí)行業(yè)務(wù)代碼咆蒿。
如果讓我們自己實現(xiàn)一套針對服務(wù)的限流邏輯,會有兩個關(guān)鍵點需要考慮,一個點是沃测,請求進來了缭黔,需要去檢查當前服務(wù)qps,判斷是否需要進行攔截蒂破;另一個點是統(tǒng)計當前服務(wù)的QPS馏谨,每處理一個請求,去更新當前服務(wù)QPS值附迷。
SphU#entry方法主要就是做這兩個事情惧互。Sentinel對每一個限流的Resouce維護了一個基于滑動窗口的計數(shù)器rollingCounterInSecond。

public class StatisticNode implements Node {
    private transient volatile Metric rollingCounterInSecond;
}

請求進來之后喇伯,先進行canPassCheck喊儡,判斷是否攔截,判斷的邏輯
curCount 為當前qps,通過滑動窗口計數(shù)器rollingCounterInSecond計算得出
acquireCount 為請求個數(shù)稻据,這個數(shù)寫死的是1
this.count為限流配置
如果curCount+1>this.count則返回false艾猜,進行攔截,然后拋出FlowException捻悯。
否則通過匆赃,去更新計數(shù)器rollingCounterInSecond

public boolean canPass(Node node, int acquireCount, boolean prioritized) {
        int curCount = this.avgUsedTokens(node);
        if ((double)(curCount + acquireCount) > this.count) {
            if (prioritized && this.grade == 1) {
                long currentTime = TimeUtil.currentTimeMillis();
                long waitInMs = node.tryOccupyNext(currentTime, acquireCount, this.count);
                if (waitInMs < (long)OccupyTimeoutProperty.getOccupyTimeout()) {
                    node.addWaitingRequest(currentTime + waitInMs, acquireCount);
                    node.addOccupiedPass(acquireCount);
                    this.sleep(waitInMs);
                    throw new PriorityWaitException(waitInMs);
                }
            }

            return false;
        } else {
            return true;
        }
    }

總結(jié)

Sentinel限流的本質(zhì)是為每個resource(限流單元)維護一個基于滑動窗口的計數(shù)器,當請求進來今缚,先檢查計數(shù)器炸庞,校驗是否需要攔截,通過后荚斯,更新這個計數(shù)器。限流功能可以保證我們的接口在一個可控的負載范圍內(nèi)查牌。不至于因為某一個接口的過載導(dǎo)致整個應(yīng)用級別的不可用事期。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市纸颜,隨后出現(xiàn)的幾起案子兽泣,更是在濱河造成了極大的恐慌,老刑警劉巖胁孙,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唠倦,死亡現(xiàn)場離奇詭異,居然都是意外死亡涮较,警方通過查閱死者的電腦和手機稠鼻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狂票,“玉大人候齿,你說我怎么就攤上這事。” “怎么了慌盯?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵周霉,是天一觀的道長。 經(jīng)常有香客問我亚皂,道長俱箱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任灭必,我火速辦了婚禮狞谱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厂财。我一直安慰自己芋簿,他們只是感情好,可當我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布璃饱。 她就那樣靜靜地躺著与斤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荚恶。 梳的紋絲不亂的頭發(fā)上撩穿,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天,我揣著相機與錄音谒撼,去河邊找鬼食寡。 笑死,一個胖子當著我的面吹牛廓潜,可吹牛的內(nèi)容都是我干的抵皱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼辩蛋,長吁一口氣:“原來是場噩夢啊……” “哼呻畸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悼院,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤伤为,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后据途,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绞愚,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年颖医,在試婚紗的時候發(fā)現(xiàn)自己被綠了位衩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡便脊,死狀恐怖蚂四,靈堂內(nèi)的尸體忽然破棺而出光戈,到底是詐尸還是另有隱情,我是刑警寧澤遂赠,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布久妆,位于F島的核電站,受9級特大地震影響跷睦,放射性物質(zhì)發(fā)生泄漏筷弦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一抑诸、第九天 我趴在偏房一處隱蔽的房頂上張望烂琴。 院中可真熱鬧,春花似錦蜕乡、人聲如沸奸绷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽号醉。三九已至,卻和暖如春辛块,著一層夾襖步出監(jiān)牢的瞬間畔派,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工润绵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留线椰,地道東北人。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓尘盼,卻偏偏與公主長得像憨愉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子卿捎,可洞房花燭夜當晚...
    茶點故事閱讀 45,446評論 2 359

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