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处理");
    //    }
    
    }
  • 相关阅读:
    requirejs 加载其它js
    springmvc 国际化
    企业QQ客服的添加
    js验证身份证号码
    JQUERY获取当前页面的URL信息
    lnmp、lamp、lnmpa一键安装包(Updated: 2015-10-25)
    php生成代金券码
    JS控制文本框textarea输入字数限制的方法
    ps 换图片的背景颜色
    读取数据库配置文件
  • 原文地址:https://www.cnblogs.com/mingforyou/p/15612302.html
Copyright © 2011-2022 走看看