• sentinel中流控规则 并发线程数的实战理解


    先看下官网文档关于并发线程数的解释:链接地址

    在这里插入图片描述

    public class FlowThreadDemo {
    
        private static AtomicInteger pass = new AtomicInteger();
        private static AtomicInteger block = new AtomicInteger();
        private static AtomicInteger total = new AtomicInteger();
        private static AtomicInteger activeThread = new AtomicInteger();
    
        private static volatile boolean stop = false;
        private static final int threadCount = 100;
    
        private static int seconds = 60 + 40;
        private static volatile int methodBRunningTime = 2000;
    
        public static void main(String[] args) throws Exception {
            System.out.println(
                "MethodA will call methodB. After running for a while, methodB becomes fast, "
                    + "which make methodA also become fast ");
            tick();
            initFlowRule();
    
            for (int i = 0; i < threadCount; i++) {
                Thread entryThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (true) {
                            Entry methodA = null;
                            try {
                                //TimeUnit.MILLISECONDS.sleep(5);
                                methodA = SphU.entry("methodA");
                                activeThread.incrementAndGet();
                                Entry methodB = SphU.entry("methodB");
                                TimeUnit.MILLISECONDS.sleep(methodBRunningTime);
                                methodB.exit();
                                pass.addAndGet(1);
                            } catch (BlockException e1) {
                                block.incrementAndGet();
                            } catch (Exception e2) {
                                // biz exception
                            } finally {
                                total.incrementAndGet();
                                if (methodA != null) {
                                    methodA.exit();
                                    activeThread.decrementAndGet();
                                }
                            }
                        }
                    }
                });
                entryThread.setName("working thread");
                entryThread.start();
            }
        }
    
        private static void initFlowRule() {
            List<FlowRule> rules = new ArrayList<FlowRule>();
            FlowRule rule1 = new FlowRule();
            rule1.setResource("methodA");
            // set limit concurrent thread for 'methodA' to 20
            rule1.setCount(20);
            rule1.setGrade(RuleConstant.FLOW_GRADE_THREAD);
            rule1.setLimitApp("default");
    
            rules.add(rule1);
            FlowRuleManager.loadRules(rules);
        }
    
        private static void tick() {
            Thread timer = new Thread(new TimerTask());
            timer.setName("sentinel-timer-task");
            timer.start();
        }
    
        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(seconds + " total qps is: " + oneSecondTotal);
                    System.out.println(TimeUtil.currentTimeMillis() + ", total:" + oneSecondTotal
                        + ", pass:" + oneSecondPass
                        + ", block:" + oneSecondBlock
                        + " activeThread:" + activeThread.get());
                    if (seconds-- <= 0) {
                        stop = true;
                    }
                    if (seconds == 40) {
                        System.out.println("method B is running much faster; more requests are allowed to pass");
                        methodBRunningTime = 20;
                    }
                }
    
                long cost = System.currentTimeMillis() - start;
                System.out.println("time cost: " + cost + " ms");
                System.out.println("total:" + total.get() + ", pass:" + pass.get()
                    + ", block:" + block.get());
                System.exit(0);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122

    运行结果:
    在这里插入图片描述
    官方给出的demo的大概意思就是:

    设置流控规则为并发线程数==20
    模拟100个并发线程执行methodA调用methodB,期间模拟了methodB的方法执行耗时。
    在前60秒,methodB方法耗时2秒,所以在前60s内的每2s内会在20个线程执行一遍,所以会出现前一秒pass=20,后一秒pass=0的情况
    在后20秒,methodB方法耗时20ms,所以20线程在每一秒里执行了大概25遍(wihle循环)

    从demo打印的日志来看得出如下结论:

    并发线程数控制的是方法执行的线程数量,对于应用而言,每秒处理的数据约等于 并发线程数量*单位时间内能够处理的次数。

    带着结论自己测试一遍

    并发线程数==2
    分别测试并发100,500,1000,2000
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述并发线程数==10

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    从上述数据来看,并发线程数控制着处理处理入口流量的线程数,从给出的官方demo意图在于表述在面对大量请求时,能够很好的保护耗时操作不被大量的qps拖垮,从自身的测试看出,在处理数据rt近似平均的时候,越大的并发数能够处理更多的流量。

    在面对突然的大流量时,如果机器的性能足够好,可以适当增大线程数,增加处理量,如果机器的性能一般时,为防止被突如其来的大量线程数拖垮时,可以起到限制作用,保护应用。

  • 相关阅读:
    【历史上的今天】9 月 18 日:McAfee 创始人出生;ICANN 成立;QQ 宠物正式下线
    k8s day03
    408 | 【2017年】计算机统考真题 自用回顾知识点整理
    面了个20k的自动化测试,从腾讯出来的果然都有两把刷子···
    Cartesi 2022 年 8 月回顾
    C++ Reference: Standard C++ Library reference: C Library: cwchar: wcstoul
    k8s部署三个节点zookeeper,1主2从集群
    PC博物馆(番外01)-城会玩,初中生开发实体尺规大航海游戏
    源码编译perl5遇到的问题汇总
    2023考研常识之学硕和专硕哪个更好,有哪些不同?
  • 原文地址:https://blog.csdn.net/qq_31426247/article/details/128146932