Sentinel icon indicating copy to clipboard operation
Sentinel copied to clipboard

SpringMVC异步情况下System的Thread限流计数有问题

Open polarrwl opened this issue 2 years ago • 2 comments

背景

使用SpringMVC进行Sentinel限流,配置了System的Thread最大数限流规则。

当使用SpringMVC @Callable 异步模式后,SystemRule的当前线程数会不停的放大,一直递增不扣减,请求次数超过最大线程数就会出现BlockingException,后面所有请求都会是这个错,无法恢复。

业务代码:

@ResponseBody
@GetMapping("/async")
public Callable<String> async() throws Exception {
    Callable<String> callable = () -> {
        TimeUnit.MILLISECONDS.sleep(50); //
        return "hello world";
    };
    return callable;
}

问题分析

通过打断点分析发现是因为SpringMVC异步情况下preHandle会进来两次,Sentinel的AbstractSentinelInterceptor拦截器会两次计数,导致Entry没有退出。

polarrwl avatar May 16 '22 02:05 polarrwl

关于异步两次进入preHandler可以参考这个解决方案: https://stackoverflow.com/questions/26995395/spring-mvc-interceptorhandler-called-twice-with-deferredresult

polarrwl avatar May 16 '22 03:05 polarrwl

#2810 @sczyh30 @brotherlu-xcq 使用栈来替换之前的引用计数 preHandler 入栈一个 preEvent postHandler 中入栈 postEventafterCompletion 对事件进行闭合处理 ,一个postEvent 和他之前连续最远的一个 preEvent 进行匹配闭合,

liufeiyu1002 avatar Aug 03 '22 13:08 liufeiyu1002