zoukankan      html  css  js  c++  java
  • sentinel基本规则的api操作

    sentinel基本规则的api操作

    sentinel的功能作用: 限流

    sentinel和hystrix的区别是怎么样的:

    image-20210131160032389

    sentinel有哪些规则呢:

    流量控制,熔断降级,热点参数限流,系统自适应限流,黑白名单控制,网关流控,集群流控

    流量控制

    流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

    pom.xml

            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-core</artifactId>
                <version>${sentinel.version}</version>
            </dependency>
    
    

    代码:

    public class Demo {
    
        private static final String resourceName = "helloResource";
    
        public static void main(String[] args) {
            initFlowRules();
            sphoMethod();
        }
    
        /**
         * sphu的方式
         * 抛出异常的方式定义资源
         */
        public static void sphuMethod(){
            while (true){
                //如果违反了规则就抛出异常
                try (Entry entry = SphU.entry(resourceName)){
                    System.out.println(new Date().toString() + ": hello world");
                } catch (BlockException e) {
                    System.out.println("blocked!");
                }
    
            }
        }
    
    
        /**
         * spho的方式
         * 返回布尔值方式定义资源
         */
    
        public static void sphoMethod(){
            while (true){
                if(SphO.entry(resourceName)){
                    try {
                        System.out.println(new Date().toString() + ": hello world");
                    }finally {
                        SphO.exit();
                    }
                }else{
                    System.out.println("blocked!");
                }
            }
        }
    
    
        //这个规则代表只允许每秒qps为10的请求通过resourceName这个资源
        public static void initFlowRules(){
            //定义规则
            FlowRule flowRule = new FlowRule();
            flowRule.setResource(resourceName);
            flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            flowRule.setCount(10);
            FlowRuleManager.loadRules(Collections.singletonList(flowRule));
    
        }
    }
    

    首先解析一下我们配置的规则是什么:只允许每秒qps为10的请求通过resourceName这个资源

    运行一下main方法:

    image-20210131175310163

    ​ 这样我们就可以知道:限流的直接表现是在执行 Entry nodeA = SphU.entry(resourceName) 的时候抛出 FlowException 异常。FlowExceptionBlockException 的子类,我们可以捕捉 BlockException 来自定义被限流之后的处理逻辑。

    我们先看上面的initFlowRules方法里面定义的规则含义,即FlowRule的Api含义:

    一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:

    • resource:资源名,即限流规则的作用对象

    • count: 限流阈值

    • grade: 限流阈值类型(QPS 或并发线程数)

    • limitApp: 流控针对的调用来源,若为 default 则不区分调用来源

    • strategy: 调用关系限流策略

    • controlBehavior: 流量控制效果(直接拒绝、Warm Up、匀速排队)

    具体代码请看: com.onion.apiDemo.flowRule.Demo这个demo。github地址会放到文章结尾

    熔断降级

    Sentinel 提供以下几种熔断策略:

    • 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
    • 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
    • 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

    配置如下:

            List<DegradeRule> rules = new ArrayList<>();
            DegradeRule rule = new DegradeRule(KEY)
                    .setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
                    // Set ratio threshold to 50%.
                    .setCount(0.5d)
                    .setStatIntervalMs(30000)
                    .setMinRequestAmount(50)
                    // Retry timeout (in second)
                    .setTimeWindow(10);
            rules.add(rule);
            DegradeRuleManager.loadRules(rules);
    

    执行代码如下:

                   try {
                            entry = SphU.entry(KEY);
                            sleep(ThreadLocalRandom.current().nextInt(5, 10));
                            pass.addAndGet(1);
                            // Error probability is 45%
                            if (ThreadLocalRandom.current().nextInt(0, 100) > 55) {
                                // biz code raise an exception.
                                throw new RuntimeException("oops");
                            }
                        } catch (BlockException e) { //熔断降级的时候会抛出BlockException
                            block.addAndGet(1);
                            sleep(ThreadLocalRandom.current().nextInt(5, 10));
                        } catch (Throwable t) {
                            bizException.incrementAndGet();
                            Tracer.traceEntry(t, entry); //注意:为了统计异常比例或异常数,需要通过 Tracer.trace(ex) 记录业务异常
                        } finally {
                            total.addAndGet(1);
                            if (entry != null) {
                                entry.exit();
                            }
                        }
                    }
    

    熔断降级规则(DegradeRule)包含下面几个重要的属性:

    Field 说明 默认值
    resource 资源名,即规则的作用对象
    grade 熔断策略,支持慢调用比例/异常比例/异常数策略 慢调用比例
    count 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值
    timeWindow 熔断时长,单位为 s
    minRequestAmount 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) 5
    statIntervalMs 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) 1000 ms
    slowRatioThreshold 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

    注意:这里count的比例是: 异常比例/总数的。比如设置了count等于0.5。总请求是100,异常请求个数为:60,正常请求个数为:40,那么就会触发熔断降级了。

    熔断降级运行:

    ​ 也是通过SphU.entry(KEY)来进行。如果SphU.entry(KEY)熔断降级的话。会抛出BlockException异常。

    注意:异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效,为了统计异常比例或异常数,需要通过 Tracer.trace(ex) 记录业务异常,慢调用不需要

    熔断器支持事件监听

    ​ 即是Sentinel 支持注册自定义的事件监听器监听熔断器状态变换事件(state change event),代码如下:

            EventObserverRegistry.getInstance().addStateChangeObserver("logging",
                    (prevState, newState, rule, snapshotValue) -> {
                                    // 变换至 OPEN state 时会携带触发时的值
                        if (newState == State.OPEN) {
                            System.err.println(String.format("%s -> OPEN at %d, snapshotValue=%.2f", prevState.name(),
                                    TimeUtil.currentTimeMillis(), snapshotValue));
                        } else {
                            System.err.println(String.format("%s -> %s at %d", prevState.name(), newState.name(),
                                    TimeUtil.currentTimeMillis()));
                        }
                    });
    

    具体代码请看: com.onion.apiDemo.degradeRule.ExceptionRatioCircuitBreakerDemo 这个demo。github地址会放到文章结尾

    ​ 这个demo主要功能就是:8个线程跑一段代码。该代码有百分之55的机会抛出异常并且还会统计该段代码的总的运行数量,通过的数量,异常的数量,block(熔断降级)的数量。 并且有个线程每隔一秒就打印这些指标出来。

    热点参数限流

    何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

    • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
    • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

    ​ 热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

    image-20210202105045945

    规则配置如下:

    需要额外加入这个依赖:

            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-parameter-flow-control</artifactId>
                <version>${sentinel.version}</version>
            </dependency>
    

    代码:

        public static void initParamFlowRule(){
            ParamFlowRule paramFlowRule = new ParamFlowRule();
            paramFlowRule.setResource(RESOURCE_KEY);
            //	限流阈值,全局的
            paramFlowRule.setCount(5);
            paramFlowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置
            paramFlowRule.setParamIdx(0);
    
            ParamFlowItem paramFlowItem = new ParamFlowItem()
                    .setObject(String.valueOf(PARAM_B)) //设置热点参数的数值
                    .setClassType(int.class.getName()) //设置热点参数的类型
                    .setCount(10);//单独参数的阈值
            paramFlowRule.setParamFlowItemList(Collections.singletonList(paramFlowItem));
            ParamFlowRuleManager.loadRules(Collections.singletonList(paramFlowRule));
        }
    

    热点参数规则(ParamFlowRule)类似于流量控制规则(FlowRule):

    ParamFlowItem其实就是设置单独参数的阈值,ParamFlowRule是设置全局的阈值

    运行部分的代码:

    T param = generateParam();
    try {
        entry = SphU.entry(resourceName, EntryType.IN, 1, param,param);
        // Add pass for parameter.
        passFor(param);
    } catch (BlockException e) {
        // block.incrementAndGet();
        blockFor(param);
    } catch (Exception ex) {
        // biz exception
        ex.printStackTrace();
    } finally {
        // total.incrementAndGet();
        if (entry != null) {
            entry.exit(1, param);
        }
    }
    

    ​ Entry entry(String name, EntryType type, int count, Object... args) 参数解析:

    • entryType: 资源调用的流量类型,是入口流量(EntryType.IN)还是出口流量(EntryType.OUT),注意系统规则只对 IN 生效
    • count: 表示每次调用计数为多少,通常传1。
    • args:传入的参数

    注意:若 entry 的时候传入了热点参数,那么 exit 的时候也一定要带上对应的参数(exit(count, args)),否则可能会有统计错误。

    具体代码请看: com.onion.apiDemo.ParamFlowRule.ParamFlowRuleDemo 这个demo。github地址会放到文章结尾

    系统自适应限流

    ​ Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

    系统规则支持以下的模式:

    • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5
    • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
    • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
    • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
    • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

    系统自适应限流得代码如下:

        List<SystemRule> rules = new ArrayList<SystemRule>();
        SystemRule rule = new SystemRule();
        // max load is 3
        rule.setHighestSystemLoad(3.0);
        // max cpu usage is 60%
        rule.setHighestCpuUsage(0.6);
        // max avg rt of all request is 10 ms
        rule.setAvgRt(10);
        // max total qps is 20
        rule.setQps(20);
        // max parallel working thread is 10
        rule.setMaxThread(10);
    
        rules.add(rule);
        SystemRuleManager.loadRules(Collections.singletonList(rule));
    

    具体代码请看: com.onion.apiDemo.systemRule.SystemGuardDemo 这个demo。github地址会放到文章结尾

    黑白名单控制

    ​ 很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问控制(黑白名单控制)的功能。来源访问控制根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。

    调用方信息通过 ContextUtil.enter(resourceName, origin) 方法中的 origin 参数传入。

    规则配置

    来源访问控制规则(AuthorityRule)非常简单,主要有以下配置项:

    • resource:资源名,即限流规则的作用对象。
    • limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB
    • strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。

    代码显示:

    public class AuthorityRuleDemo {
    
        public static String KEY = "AuthorityRuleKey";
    
        public static void main(String[] args) {
            System.out.println("---------------------白名单打印---------------------");
            initWhiteRule();
            test(KEY,"appA");
            test(KEY,"appB");
            test(KEY,"appC");
    
            System.out.println("---------------------黑名单打印---------------------");
            initBlackRule();
            test(KEY,"appA");
            test(KEY,"appB");
            test(KEY,"appC");
        }
        
    
        public static void test(String resource,String appName){
            ContextUtil.enter(resource,appName);
            Entry entry = null;
            try {
                 entry = SphU.entry(KEY);
                System.out.println("pass:" + appName);
            }catch (BlockException e){
                System.out.println("block:" + appName);
            }finally {
                if(entry!=null){
                    entry.exit();
                }
                ContextUtil.exit();
            }
            
        }
       
        /**
         * 初始化白名单规则
         */
        public  static void initWhiteRule(){
            AuthorityRule authorityRule = new AuthorityRule();
            authorityRule.setResource(KEY);
            authorityRule.setStrategy(RuleConstant.AUTHORITY_WHITE);  //设置白名单类型
            authorityRule.setLimitApp("appA,appB,appE");
            AuthorityRuleManager.loadRules(Collections.singletonList(authorityRule));
        }
    
        /**
         * 初始化黑名单规则
         */
        public  static void initBlackRule(){
            AuthorityRule authorityRule = new AuthorityRule();
            authorityRule.setResource(KEY);
            authorityRule.setStrategy(RuleConstant.AUTHORITY_BLACK);  //设置白名单类型
            authorityRule.setLimitApp("appA,appB,appE");
            AuthorityRuleManager.loadRules(Collections.singletonList(authorityRule));
        }
    
    
    
    }
    

    具体代码请看:com.onion.apiDemo.authorityRule.AuthorityRuleDemo这个demo。github地址会放到文章结尾

    github地址https://gitee.com/gzgyc/dubbo-demo.git

    一些比集群流控的文章:

    https://blog.csdn.net/weixin_42073629/article/details/106450575

    https://www.jianshu.com/p/67d02420e814

    https://blog.csdn.net/wangzhanzheng/article/details/86477559

    生产环境落地的文章:

    https://mp.weixin.qq.com/s/AjHCUmygTr78yo9yMxMEyg

  • 相关阅读:
    JSON 体验JSON (二)json格式化日期
    让D2006的控件面板回到D7的样式
    突破网站限制 复制网页内容
    欢迎光临
    加密Access数据库
    取得程序中一些特殊文件夹的位置
    连接带密码的Access数据库
    我被强暴,老公这样回答是人么?(转~非黄)
    【WinCE版凯立德】2012春季版地图下载
    刚刚拍到的日环食金星凌日
  • 原文地址:https://www.cnblogs.com/dabenxiang/p/14376946.html
Copyright © 2011-2022 走看看