异常处理多次,统一异常处理多次

关于spring 核心线程池满了 当并发的时候 遇到线程拒绝,统一异常处理会处理两次

先贴代码


@RequestMapping(value = "/testVisitNum", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_VALUE})
    @ApiOperation(value = "测试访问人数过多,是否会报错两次", response = BaseVo.class)
    @ApiOperationSupport(order = 3)
    public Callable<ResponseEntity<JSONObject>> testVisitNum(HttpServletRequest request) {
        //System.out.println(getCurrentUserId(request));
        return ()->{
            Thread.sleep(3000);
            return success();
        };
    }

配置文件中

是否允许核心线程超时。这样可以动态增加和缩小线程池

spring.task.execution.pool.allow-core-thread-timeout=true

核心线程池大小 默认 8

spring.task.execution.pool.core-size=8

线程空闲等待时间 默认 60s

spring.task.execution.pool.keep-alive=60s

线程池最大数 根据任务定制

spring.task.execution.pool.max-size=8

线程池 队列容量大小

spring.task.execution.pool.queue-capacity=0

线程池关闭时等待所有任务完成

spring.task.execution.shutdown.await-termination=true

执行线程关闭前最大等待时间,确保最后一定关闭

spring.task.execution.shutdown.await-termination-period=1s

线程名称前缀

spring.task.execution.thread-name-prefix=hexin-

统一异常处理


@ExceptionHandler
    public ResponseEntity<JSONObject> exp2(Exception ex) {
        JSONObject result = new JSONObject();
        if (ex instanceof TaskRejectedException) {
            ex.printStackTrace();
            result.put("code", NumberUtils.CODE_99);
            result.put("msg", "访问人数过多,请稍后再试");
            log.error("访问人数过多,请稍后再试"+ex.hashCode());
            //TODO 测试 这里可能会调用多次
            System.out.println("实际返回值1:"+result.toJSONString());
            return new ResponseEntity<>(result, HttpStatus.OK);
        }

控制台打印

访问人数过多,请稍后再试2039621435
访问人数过多,请稍后再试2039621435

hashcode是同一个

jemter 测试

img

img

img

导致第九个结果 反馈给客户但是 两个json对象 求解~

已经解决


@ExceptionHandler
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)     //加了这样返回参数 状态码 解决这个问题
    public ResponseEntity<JSONObject> exp2(Exception ex) {
        JSONObject result = new JSONObject();
        // 根据不同错误输出不同的消息
        ex.printStackTrace();
        result.put("code", NumberUtils.CODE_99);
        result.put("msg", "访问人数过多,请稍后再试");
        log.error("访问人数过多,请稍后再试"+ex.hashCode());
        //TODO 测试 这里可能会调用多次
        System.out.println("实际返回值1:"+result.toJSONString());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }

debug了一下,然后结合百度的情况,先说原因,tomcat的拒绝策略并不是直接拒绝,临死前还挣扎了一次,将任务加入到等待队列,
第二次如果还是没有线程处理的话,这个就真的拒绝了,
先是百度了一下能不能去配置拒绝策略,发现并没有啥好的方式,然后退而求其次,既然是执行两次,那我控制下异常处理逻辑,只写入一次异常信息即可
加入限制前

img


img

加入限制

img


img

img


然后再写一个springmvc的拦截器去清除Threadlocal就行了

线上这需要你多测试测试看有没有问题