美文网首页
sentinel注解配置

sentinel注解配置

作者: 板栗炖牛肉 | 来源:发表于2021-08-10 10:00 被阅读0次

    前言

    • 当前在spring boot 是不spring cloud上运行sentinel
    • 环境: spring boot 2.4.9 , sentinel 2021.1
    • 主要配置运行,只讲限流方式,且不讲解控制台操作(不需要使用),不配置nacos持久化
    • 只用注解式
    • 官方

    解决方案

    • 引入sentinel
            <!-- sentinel -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
                <version>2021.1</version>
            </dependency>
    
    • 还是贴出所有pom
         <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- sentinel -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
                <version>2021.1</version>
            </dependency>
    
    • 提一下跑时出现的一个坑,引入了一个以下包,导致跑时出现异常无法启动
           <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>2.0.1.Final</version>
            </dependency>
    
    • 修改为,hibernate-validator包含validation-api,但是sentinel缺少其他配置所以无法启动
       <dependency>
                <groupId>org.hibernate.validator</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>7.0.1.Final</version>
            </dependency>
    
    • 还是贴以下外部配置,外部jar包控制台
    spring:
      cloud:
        sentinel:
          transport:
            dashboard: localhost:30010
            heartbeat-interval-ms: 1000
          enabled: true
    
    
    • 创建一个CustomBlockHandler外部控制异常捕获(只针对控制台操作),new RestBean<>(RestCodeType.BUSY_BUSINESS)这些变更为自己的异常代码
    @Configuration
    public class CustomBlockHandler implements BlockExceptionHandler {
    
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
            String msg = null;
            if (e instanceof FlowException) {
                //限流
                msg = JSON.toJSONString(new RestBean<>(RestCodeType.BUSY_BUSINESS));
            } else if (e instanceof DegradeException) {
                //BUSY_TOO_MANY_PEOPLE
                msg = JSON.toJSONString(new RestBean<>(RestCodeType.BUSY_UNREACHABLE));
            } else if (e instanceof ParamFlowException) {
                //热点参数限流
                msg = JSON.toJSONString(new RestBean<>(RestCodeType.BUSY_BUSINESS));
            } else if (e instanceof SystemBlockException) {
                //系统规则
                msg = JSON.toJSONString(new RestBean<>(RestCodeType.BUSY_UNREACHABLE));
            } else if (e instanceof AuthorityException) {
                //授权规则
                msg = JSON.toJSONString(new RestBean<>(RestCodeType.BUSY_UNREACHABLE));
            }
            response.setStatus(400);
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Type", "application/json;charset=utf-8");
            response.getWriter().write(msg);
            response.getWriter().close();
        }
    
    }
    
    
    • 创建一个持久化配置CustomSentinelConfig
    public abstract class CustomSentinelConfig {
    
        @PostConstruct
        private void config() {
            List<FlowRule> flowRules = new ArrayList<>();
    
            /**
             * 添加限流方式
             * 10次拒绝访问
             */
            FlowRule flowRule1 = new FlowRule();
            //资源名,资源名是限流规则的作用对象
            flowRule1.setResource("限流-10");
            //限流阈值
            flowRule1.setCount(10);
            //调用关系限流策略:直接、链路、关联
            flowRule1.setStrategy(0);
            //限流阈值类型,QPS 或线程数模式
            flowRule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //流控效果(直接拒绝 / 慢启动模式 / 排队等待),不支持按调用关系限流
            flowRule1.setControlBehavior(0);
    
            /**
             * 添加限流方式
             * 5次等待排队
             */
            FlowRule flowRule2 = new FlowRule();
            //资源名,资源名是限流规则的作用对象
            flowRule2.setResource("限流等待-5");
            //限流阈值
            flowRule2.setCount(5);
            //调用关系限流策略:直接、链路、关联
            flowRule2.setStrategy(0);
            //限流阈值类型,QPS 或线程数模式
            flowRule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //流控效果(直接拒绝 / 慢启动模式 / 排队等待),不支持按调用关系限流
            flowRule2.setControlBehavior(2);
            //超时时间设置
            flowRule2.setMaxQueueingTimeMs(60000);
    
            /**
             * 添加限流方式
             * 2次拒绝访问
             */
            FlowRule flowRule3 = new FlowRule();
            //资源名,资源名是限流规则的作用对象
            flowRule3.setResource("限流-2");
            //限流阈值
            flowRule3.setCount(2);
            //调用关系限流策略:直接、链路、关联
            flowRule3.setStrategy(0);
            //限流阈值类型,QPS 或线程数模式
            flowRule3.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //流控效果(直接拒绝 / 慢启动模式 / 排队等待),不支持按调用关系限流
            flowRule3.setControlBehavior(0);
    
            /**
             * 添加限流方式
             * 10次等待排队
             */
            FlowRule flowRule4 = new FlowRule();
            //资源名,资源名是限流规则的作用对象
            flowRule4.setResource("限流等待-10");
            //限流阈值
            flowRule4.setCount(10);
            //调用关系限流策略:直接、链路、关联
            flowRule4.setStrategy(0);
            //限流阈值类型,QPS 或线程数模式
            flowRule4.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //流控效果(直接拒绝 / 慢启动模式 / 排队等待),不支持按调用关系限流
            flowRule4.setControlBehavior(2);
            //超时时间设置
            flowRule4.setMaxQueueingTimeMs(60000);
    
            /**
             * 添加限流方式
             * 线程最多五个
             */
            FlowRule flowRule5 = new FlowRule();
            //资源名,资源名是限流规则的作用对象
            flowRule5.setResource("线程-5");
            //限流阈值
            flowRule5.setCount(5);
            //调用关系限流策略:直接、链路、关联
            flowRule5.setStrategy(0);
            //限流阈值类型,QPS 或线程数模式
            flowRule5.setGrade(RuleConstant.FLOW_GRADE_THREAD);
            //流控效果(直接拒绝 / 慢启动模式 / 排队等待),不支持按调用关系限流
            flowRule5.setControlBehavior(0);
            //超时时间设置
            flowRule5.setMaxQueueingTimeMs(60000);
    
    
            /**
             * 组装限流
             */
            flowRules.add(flowRule1);
            flowRules.add(flowRule2);
            flowRules.add(flowRule3);
            flowRules.add(flowRule4);
            flowRules.add(flowRule5);
            FlowRuleManager.loadRules(currentLimitRules(flowRules));
        }
    
        /**
         * 限流规则配置
         *
         * @param rules
         * @return
         */
        protected abstract List<FlowRule> currentLimitRules(List<FlowRule> rules);
    
    }
    
    • 以上是一个abstract类,继承类为SentinelConfig,这里看个人配置,我这里是为了方便配置
    @Configuration
    public class SentinelConfig extends CustomSentinelConfig {
    
        @Override
        protected List<FlowRule> currentLimitRules(List<FlowRule> rules) {
            return rules;
        }
    }
    
    • 以下开始有点特殊,创建一个测试类
    
    @RestController
    public class SentinelController {
        @SentinelResource(value = "线程-5")
        @RequestMapping(value = "/ss")
        public String ss(String id, HttpServletResponse response) throws Exception {
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "访问结果";
        }
    }
    
    • 按照官方写法应为
    @RestController
    public class SentinelController {
    
        @SentinelResource(value = "线程-5",blockHandler = "ssHandler")
        @RequestMapping(value = "/ss")
        public String ss(String id, HttpServletResponse response) throws Exception {
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "访问结果";
        }
        
        public String ssHandler(String id, HttpServletResponse response, BlockException b) throws Exception {
            return "错误代码";
        }
    
    }
    
    • 不好意思,个人代码风格有点接受不了,很恶心感觉,emmm没别的意思,注意:CustomBlockHandler只针对外部配置,内部的不生效,不要再问为什么

    • 那就把ssHandler剔掉,blockHandler = "ssHandler"也踢掉,变成了一个注释搞的

        @SentinelResource(value = "线程-5")
    
    • 当然还要加入其它配置,业务入口必须加入throws Exception,否则会报其它异常
      public String ss(String id, HttpServletResponse response) throws Exception {
    
    • 全局捕获异常加入,我这里使用文本比对的,你们可以替换为类比较
    ...
     else if (msg.contains("FlowException")) {
                logger.error("全局异常捕获,限流开始", "FlowException");
                restBean.setType(RestCodeType.BUSY_BUSINESS, e);
            } 
    ...
    
    • 基本就配置完成了,来一次测试,我这里是限制同时五个线程


      image.png
    image.png image.png image.png image.png image.png
    • 比对限流响应时间


      全局异常捕获
    自定义Handler捕获 正常结果时间
    • 置于响应时间为什么那么久,我这边请求软件高并发的问题。但是同样,全局捕获肯定比自定义要慢这是当然的,全局捕获还有其他判断。。这是当然的,以下去除休眠网页访问时间。
    网页访问时间
    image.png
    • 其它限流方式就不贴出了

    结尾

    • 有不对的地方请您指正
    • 一定要加throws Exception不然就是另一个异常

    相关文章

      网友评论

          本文标题:sentinel注解配置

          本文链接:https://www.haomeiwen.com/subject/ftdxbltx.html