zoukankan      html  css  js  c++  java
  • Spring Cloud Alibaba Sentinel @SentinelResource

    https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81

    https://blog.didispace.com/spring-cloud-alibaba-sentinel-2-5/

    @SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:

    • value:资源名称,必需项(不能为空)
    • entryType:entry 类型,可选项(默认为 EntryType.OUT
    • blockHandler / blockHandlerClassblockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
    • fallback / fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
      • 返回值类型必须与原函数返回值类型一致;
      • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
      • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
    • defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:
      • 返回值类型必须与原函数返回值类型一致;
      • 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
      • defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
    • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

    package com.wsm.sentinel.controller;
    
    import com.alibaba.csp.sentinel.Entry;
    import com.alibaba.csp.sentinel.EntryType;
    import com.alibaba.csp.sentinel.SphU;
    import com.alibaba.csp.sentinel.Tracer;
    import com.alibaba.csp.sentinel.annotation.SentinelResource;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    import com.alibaba.csp.sentinel.slots.block.RuleConstant;
    import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
    import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
    import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
    import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
    import com.alibaba.csp.sentinel.slots.system.SystemRule;
    import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
    import com.wsm.sentinel.handler.HelloBlockHandler;
    import com.wsm.sentinel.pojo.User;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.PostConstruct;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    @RestController
    @Slf4j
    public class HelloController {
    
        private static final String RESOURCE_NAME="hello";
        private static final String USER_RESOURCE_NAME = "user";
        private static final String DEGRADE_RESOURCE_NAME = "degrade";
    
        //进行sentinel限流
        @RequestMapping(value = "/hello")
        public String hello() {
            Entry entry = null;
            try {
                //sentinel 针对资源进行限制
                entry = SphU.entry(RESOURCE_NAME);
                //被保护的业务逻辑
                String str = "hello world";
                log.info("======="+str+"========");
                return str;
            }catch (BlockException el){
                //资源访问阻止,被限流或被降级
                //进行相应的处理操作
                log.info("block!");
                return "被流控了!";
            }catch (Exception ex){
                //若需要配置降级,需要通过这种方式记录业务异常
                Tracer.traceEntry(ex,entry);
            }finally {
                if(entry != null){
                    entry.exit();
                }
            }
            return null;
        }
    
        /**
         * 定义规则
         *
         * spring 的初始化方法
         */
        @PostConstruct // init-method  Spring注解  Bean创建的时候会调用这个方法进行初始化
        private static void initFlowRules(){
    
    //        //流控规则
    //        List<FlowRule> rules = new ArrayList<>();
    //        //流控
    //        FlowRule rule = new FlowRule();
    //        //设置受保护的资源
    //        rule.setResource(RESOURCE_NAME);
    //        //设置流控规则 QPS
    //        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    //        //设置受保护的资源阈值  QPS每秒访问数
    //        rule.setCount(1);
    //        rules.add(rule);
    //
    //        //流控
    //        FlowRule rule2 = new FlowRule();
    //        //设置受保护的资源
    //        rule2.setResource(USER_RESOURCE_NAME);
    //        //设置流控规则 QPS
    //        rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
    //        //设置受保护的资源阈值  QPS每秒访问数
    //        rule2.setCount(1);
    //        rules.add(rule2);
    //        FlowRuleManager.loadRules(rules);
        }
    
        @PostConstruct
        public void initDegradeRules(){
    //        一秒内(请求数大于等于 5)响应时间超过某个值:RuleConstant.DEGRADE_GRADE_RT;
    //        一秒内(请求数大于等于 5)的错误比率:RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO;
    //        一分钟内的错误数量:RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT;
    
            List<DegradeRule> rules = new ArrayList<>();
            DegradeRule rule = new DegradeRule();
            rule.setResource(DEGRADE_RESOURCE_NAME);
            //异常数模式下为对应的阈值
            rule.setCount(2);
            //熔断策略,异常数策略
            rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
            // 熔断时长,单位为 s
            rule.setTimeWindow(10);
    //        rule.setMinRequestAmount(2);
    //        rule.setStatIntervalMs(60*1000*60);//时间太短不好测
            rules.add(rule);
    
    //        DegradeRule rule1 = new DegradeRule();
    //        rule1.setResource(DEGRADE_RESOURCE_NAME);
    //        //异常比例模式下为对应的阈值
    //        rule1.setCount(0.1);
    //        //熔断策略,异常比例策略
    //        rule1.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
    //        // 熔断时长,单位为 s
    //        rule1.setTimeWindow(10);
    ////        rule1.setMinRequestAmount(2);
    ////        rule1.setStatIntervalMs(60*1000*60);//时间太短不好测
    //        rules.add(rule1);
    
    //        DegradeRule rule2 = new DegradeRule();
    //        rule2.setResource(DEGRADE_RESOURCE_NAME);
    //        //慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);
    //        // set threshold RT, 10 ms
    //        rule2.setCount(10);
    //        //熔断策略,支持慢调用比例 -- DEGRADE_GRADE_RT
    //        rule2.setGrade(RuleConstant.DEGRADE_GRADE_RT);
    //        // 熔断时长,单位为 s
    //        rule2.setTimeWindow(10);
    ////        请求总数小于minRequestAmount(2);
    //        rule2.setMinRequestAmount(2);
    ////        在这个时间段内2次请求
    //        rule2.setStatIntervalMs(60*1000*60);//时间太短不好测
    ////        慢请求率: 慢请求数/总请求数> SlowRatioThreshold , 这里要设置小于1 因为慢请求数/总请求数就远不会大于1
    //        rule2.setSlowRatioThreshold(0.9);
    //        rules.add(rule2);
            DegradeRuleManager.loadRules(rules);
    
        }
    
    
        // 限流规则
        private void initFlowQpsRule() {
            List<FlowRule> rules = new ArrayList<>();
            FlowRule rule = new FlowRule(RESOURCE_NAME);
            // set limit qps to 20
            rule.setCount(20);
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            rule.setLimitApp("default");
            rules.add(rule);
            FlowRuleManager.loadRules(rules);
        }
    
        private void initDegradeRule() {
            List<DegradeRule> rules = new ArrayList<>();
            DegradeRule rule = new DegradeRule();
            rule.setResource(DEGRADE_RESOURCE_NAME);
            // set threshold RT, 10 ms
            rule.setCount(10);
            rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
            rule.setTimeWindow(10);
            rules.add(rule);
            DegradeRuleManager.loadRules(rules);
        }
    
        private void initSystemRule() {
            List<SystemRule> rules = new ArrayList<>();
            SystemRule rule = new SystemRule();
            rule.setHighestSystemLoad(10);
            rules.add(rule);
            SystemRuleManager.loadRules(rules);
        }
    
        @GetMapping("/rule_setting")
        //代码配置sentinel限流规则
        public String initFlowRule(){
            //规则集合
            List<FlowRule> rules = new ArrayList<>();
            //创建新的规则对象,"/list"就是资源名
            FlowRule rule = new FlowRule("/list");
            //直接策略
            rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
            //采用QPS限速模式
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //限制QPS为100
            rule.setCount(100);
            //流控效果设置为“预热”
            rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
            //预热时间20秒
            rule.setWarmUpPeriodSec(20);
            //来源设置为默认所有default
            rule.setLimitApp("default");
            rules.add(rule);
            //设置,FlowRuleManager是Sentinel规则管理器
            FlowRuleManager.loadRules(rules);
            return "SUCCESS";
        }
    
        /**
         * @SentinelResource  改善接口中资源定义和被流控降级后的处理方法
         * 使用方法:
         * 1.添加依赖 <artifactId>sentinel-annotation-aspectj</artifactId>
         * 2.配置 Bean - SentinelResourceAspect
         *      value 定义资源
         *      blockHandler 设置流控降级后的处理方法(默认该方法必须声明在同一个类)
         *      blockHandlerClass blockHandler不在同一个类时设置,在同一个类中时不用设置
         *      fallback 当接口出现了异常,就可以交给fallback指定的方法进行处理
         * @param id
         * @return
         */
        @RequestMapping("/user")
        @SentinelResource(value = USER_RESOURCE_NAME,
    //            fallbackClass = HelloBlockHandler.class,
    //            fallback = "fallbackForGetUser",
    //            blockHandlerClass = HelloBlockHandler.class,
                blockHandler = "blockHandlerForGetUser"
                )
        public User getUser(String id) {
            log.info("====getUser======");
            return new User("wsmen");
        }
    
        /**
         * 注意:
         * 1. 一定要是public方法
         * 2. 返回方法一定要和源方法保持一致, 包含源方法的参数
         * 3. 可以在参数最后添加BlockException, 可以区分是什么规则的处理方法
         * @param id
         * @param ex
         * @return
         */
        public User blockHandlerForGetUser(String id,BlockException ex){
            ex.printStackTrace();
            return new User("流控!!");
        }
    
    //    // 这里单独演示 blockHandlerClass 的配置.
    //    // 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 public static 函数.
    //    @SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
    //    public void test() {
    //        System.out.println("Test");
    //    }
    
        @RequestMapping("/degrade")
        @SentinelResource(value = DEGRADE_RESOURCE_NAME,entryType = EntryType.IN,
    //                        fallback = "fallbackForFb",
                            blockHandler = "blockHandlerForFb") 
        public User degrade(String id) throws InterruptedException {
            throw new RuntimeException("异常");
    
    //        TimeUnit.SECONDS.sleep(1);
    //        return new User("正常");
        }
    
        public User blockHandlerForFb(String id,BlockException ex){
            return  new User("异常处理");
        }
    
    //    public User fallbackForFb(String id,BlockException ex){
    //        return  new User("异常fallback处理");
    //    }
    
    }
  • 相关阅读:
    BZOJ 3205 [Apio2013]机器人 ——斯坦纳树
    BZOJ 3782 上学路线 ——动态规划 Lucas定理 中国剩余定理
    HDU 1423 Greatest Common Increasing Subsequence ——动态规划
    BZOJ 3309 DZY Loves Math ——莫比乌斯反演
    POJ 1038 Bugs Integrated, Inc. ——状压DP
    POJ 3693 Maximum repetition substring ——后缀数组
    POJ 2699 The Maximum Number of Strong Kings ——网络流
    POJ 2396 Budget ——有上下界的网络流
    BZOJ 4650 [Noi2016]优秀的拆分 ——后缀数组
    源码安装python
  • 原文地址:https://www.cnblogs.com/mingforyou/p/15612302.html
Copyright © 2011-2022 走看看