Sentinel勻速模式(削峰填谷)

一、什么是削峰填谷:

某瞬時來了大流量的請求, 而如果此時要處理所有請求,很可能會導(dǎo)致系統(tǒng)負(fù)載過高,影響穩(wěn)定性。但其實可能后面幾秒之內(nèi)都沒有消息投遞,若直接把多余的消息丟掉則沒有充分利用系統(tǒng)處理消息的能力。Sentinel的Rate Limiter模式能在某一段時間間隔內(nèi)以勻速方式處理這樣的請求, 充分利用系統(tǒng)的處理能力, 也就是削峰填谷, 保證資源的穩(wěn)定性.
Sentinel會以固定的間隔時間讓請求通過, 訪問資源。當(dāng)請求到來的時候,如果當(dāng)前請求距離上個通過的請求通過的時間間隔不小于預(yù)設(shè)值,則讓當(dāng)前請求通過;否則,計算當(dāng)前請求的預(yù)期通過時間,如果該請求的預(yù)期通過時間小于規(guī)則預(yù)設(shè)的 timeout 時間,則該請求會等待直到預(yù)設(shè)時間到來通過;反之,則馬上拋出阻塞異常。
使用Sentinel的這種策略, 簡單點說, 就是使用一個時間段(比如20s的時間)處理某一瞬時產(chǎn)生的大量請求, 起到一個削峰填谷的作用, 從而充分利用系統(tǒng)的處理能力, 下圖能很形象的展示這種場景: X軸代表時間, Y軸代表系統(tǒng)處理的請求.

image.png

二、驗證

模擬1000個請求同時并發(fā)的訪問資源, 這1000個請求, 如果設(shè)置QPS閾值為100, 按照默認(rèn)sentinel默認(rèn)的RuleConstant.CONTROL_BEHAVIOR_DEFAULT拒絕策略, 那么剩余的900個請求會被立即直接拒絕掉, 拋出BlockException.

image.png
image.png
image.png

同樣是模擬1000個請求同時并發(fā)訪問資源, 同樣設(shè)置QPS閾值100, 但是拒絕策略修改為Rate Limiter勻速RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER方式, 還需要設(shè)置setMaxQueueingTimeMs(20 * 1000)表示每一請求最長等待時間, 這里等待時間大一點, 以保證讓所有請求都能正常通過。
假設(shè)這里設(shè)置的排隊等待時間過小的話, 導(dǎo)致排隊等待的請求超時而拋出異常BlockException, 最終結(jié)果可能是這1000個并發(fā)請求中只有幾個請求或幾十個才能正常通過, 所以使用這種模式得根據(jù)訪問資源的耗時時間決定排隊等待時間。
按照目前這種設(shè)置, QPS閾值為100的話, 每一個請求相當(dāng)于是以勻速10ms左右通過。

@GetMapping("/paceFlow")
    public void paceFlow() throws InterruptedException{
        System.out.println("pace behavior");
        countDown = new CountDownLatch(1);
        // queuing隊列方式, 勻速處理流量
        initPaceFlowRule();
        // 直接并發(fā)同時啟動1000個線程, 模擬1000個并發(fā)請求資源
        simulatePulseFlow();
        countDown.await();

        System.out.println("done");
        System.out.println("total pass:" + pass.get() + ", total block:" + block.get());

        System.out.println();
    }

勻速模式的規(guī)則

private static void initPaceFlowRule() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(KEY);
        rule1.setCount(count);
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setLimitApp("default");
        /*
         * CONTROL_BEHAVIOR_RATE_LIMITER means requests more than threshold will be queueing in the queue, until the
         * queueing time is more than {@link FlowRule#maxQueueingTimeMs}, the requests will be rejected.
         */
        rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
        // 這里設(shè)置的等待處理時間較大, 讓系統(tǒng)能平穩(wěn)的處理所有的請求
        rule1.setMaxQueueingTimeMs(20 * 1000);// 表示每一個請求的最長等待時間20s
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }

并發(fā)啟動1000線程模擬請求

private static void simulatePulseFlow() {
        for (int i = 0; i < requestQps; i++) {
            Thread thread = new Thread(new Runnable() {

                @Override
                public void run() {
                    long startTime = TimeUtil.currentTimeMillis();
                    Entry entry = null;
                    try {
                        entry = SphU.entry(KEY);
                        pass.incrementAndGet();
                    } catch (BlockException e1) {
                        System.out.println("===>BlockException");
                        block.incrementAndGet();
                    } catch (Exception e2) {
                        // biz exception
                    } finally {
                        if (entry != null) {
                            entry.exit();
                            // pass.incrementAndGet();
                            long cost = TimeUtil.currentTimeMillis() - startTime;
                            System.out.println(TimeUtil.currentTimeMillis() + " one request pass, cost " + cost
                                    + " ms");
                        }
                    }

                    try {
                        TimeUnit.MILLISECONDS.sleep(5);
                    } catch (InterruptedException e1) {
                        // ignore
                    }

                    if (done.incrementAndGet() >= requestQps) {
                        countDown.countDown();
                    }
                }
            }, "Thread " + i);
            thread.start();
        }
    }

啟動后控制臺打?。?/p>

image.png

可以看到pass:1000,block:0,可以看到在闊值設(shè)定為100,勻速模式下仍可以全部通過,實現(xiàn)了削峰填谷。
sentinel控制臺展示效果圖:

image.png

可以看到由于闊值是100,而模擬請求是1000,通過的qps就是100,勻速通過直到全部pass。
還可以在控制臺看到代碼所限定的流控規(guī)則:

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容