Sentinel冷启动(预热)验证

一、冷启动含义

除了匀速器,另一种在面对RocketMQ 场景下流量突增时来保障系统稳定性的的方式是冷启动。Sentinel的Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。warm up冷启动主要用于启动需要额外开销的场景,例如建立数据库连接等。

二、验证实例

1、首先设置限流规则以及流控效果(采用warm up冷启动方式)

private static void initFlowRule() {
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(KEY);
        // 设置最大阈值为20
        // rule1.setCount(20);
        // 这里设置QPS最大的阈值1000, 便于查看变化曲线
        rule1.setCount(1000);
        // 基于QPS流控规则
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 默认不区分调用来源
        rule1.setLimitApp("default");
        // 流控效果, 采用warm up冷启动方式
        rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
        // 在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
        // warmUpPeriodSec 代表期待系统进入稳定状态的时间(即预热时长)。
        // 这里预热时间为1min, 便于在dashboard控制台实时监控查看QPS的pass和block变化曲线
        rule1.setWarmUpPeriodSec(60); // 默认值为10s
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }

2、启动一个TimerTask线程, 统计每一秒的pass, block, total这三个指标

static class TimerTask implements Runnable {
        @Override
        public void run() {
            long start = System.currentTimeMillis();
            System.out.println("begin to statistic!!!");
            long oldTotal = 0;
            long oldPass = 0;
            long oldBlock = 0;
            while (!stop) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                }
                long globalTotal = total.get();
                long oneSecondTotal = globalTotal - oldTotal;
                oldTotal = globalTotal;
                long globalPass = pass.get();
                long oneSecondPass = globalPass - oldPass;
                oldPass = globalPass;
                long globalBlock = block.get();
                long oneSecondBlock = globalBlock - oldBlock;
                oldBlock = globalBlock;
                System.out.println("currentTimeMillis:" + TimeUtil.currentTimeMillis() + ", totalSeconds:"
                        + TimeUtil.currentTimeMillis() / 1000 + ", currentSecond:"
                        + (TimeUtil.currentTimeMillis() / 1000) % 60 + ", total:" + oneSecondTotal
                        + ", pass:" + oneSecondPass + ", block:" + oneSecondBlock);
                if (seconds-- <= 0) {
                    stop = true;
                }
            }

            long cost = System.currentTimeMillis() - start;
            System.out.println("time cost: " + cost + " ms");
            System.out.println("total:" + total.get() + ", pass:" + pass.get() + ", block:" + block.get());
            try {
                TimeUnit.SECONDS.sleep(60);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.exit(0);
        }
    }

pass:是限流允许的访问数量,block:是被限流的访问数量,total是总数量。

3、同时启动三个WarmUpTask线程, 设置其休眠时间小于2s, 使系统访问资源处于一个较低的流量

// 创建3个WarmUpTask线程, 模拟一个系统处于一个低水平流量
        for (int i = 0; i < 3; i++) {
            Thread t = new Thread(new WarmUpTask());
            t.setName("sentinel-warmup-task");
            t.start();
        }
//WarmUpTask线程休眠小于2s, 通过控制休眠时间, 达到控制访问资源的流量处于一个较低的水平.
    static class WarmUpTask implements Runnable {
        @Override
        public void run() {
            while (!stop) {
                Entry entry = null;
                try {
                    entry = SphU.entry(KEY);
                    // token acquired, means pass
                    pass.addAndGet(1);
                } catch (BlockException e1) {
                    block.incrementAndGet();
                } catch (Exception e2) {
                    // biz exception
                } finally {
                    total.incrementAndGet();
                    if (entry != null) {
                        entry.exit();
                    }
                }
                Random random2 = new Random();
                try {
                    // 随机休眠时间<2s, 通过设置休眠时间(挡板业务耗时), 模拟访问资源的流量大小
                    TimeUnit.MILLISECONDS.sleep(random2.nextInt(2000));
                } catch (InterruptedException e) {
                    // ignore
                }
            }
        }
    }

4、WarmUpTask线程运行20s后,再同时启动100个线程, 设置其休眠时间小于50ms, 这样就模拟造成了访问资源的流量突增, 一是可以查看后台console观察流量变化数值, 二是查看监控台的实时监控, 能比较直观的看见warm up过程.

        // 20s开始有突增的流量进来, 访问资源
        Thread.sleep(20000);

        // 创建一个100线程, 模拟突增的流量访问被保护的资源
        for (int i = 0; i < threadCount; i++) {
            Thread t = new Thread(new RunTask());
            t.setName("sentinel-run-task");
            t.start();
        }
static class RunTask implements Runnable {
        @Override
        public void run() {
            while (!stop) {
                Entry entry = null;
                try {
                    entry = SphU.entry(KEY);
                    pass.addAndGet(1);
                } catch (BlockException e1) {
                    //以原子方式将当前值加 1。
                    block.incrementAndGet();
                } catch (Exception e2) {
                    // biz exception
                } finally {
                    total.incrementAndGet();
                    if (entry != null) {
                        entry.exit();
                    }
                }
                Random random2 = new Random();
                try {
                    // 随机休眠时间<50ms, 通过设置休眠时间, 模拟访问资源的流量大小
                    TimeUnit.MILLISECONDS.sleep(random2.nextInt(50));
                } catch (InterruptedException e) {
                    // ignore
                }
            }
        }
    }

5、控制台中打印的日志的展示效果是:

可以看到在20秒时有一个明显的流量激增,total由原来的一百多突然长到三千多pass也激增到几百了,block也长到了几千。

image.png

接着往下看

image.png

可以看到由于我们设置的阈值为1000, 所以最终的pass值是稳定在1000没有问题; 流控效果采用warm up方式, pass的值不是一下子增加到1000, 而是由300-->400-->500-->600-->700-->800-->900-->1000逐渐增加的。最终QPS流量稳定在最大阈值1000。

6、sentinel控制台展示效果图:

刚开始在qps未激增的时候:

image.png

激增之后有一个明显的激增点,也可以看到通过的QPS也就是图中红色的线,是平稳上升的:

image.png

由于阔值是1000可以看到经过60s的预热最后稳定到1000

image.png

7、总结

上面主要讲述了QPS流量控制, 采用Warm Up预热/冷启动方式控制突增流量, 通过在后台console观察打印的数据以及结合dashboard图表的形式, 能很清晰的了解到warm up冷启动方式控制突增流量, 保护资源, 维护系统的稳定性的.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343