背景
使用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没有退出。
2条答案
按热度按时间wrrgggsh1#
关于异步两次进入preHandler可以参考这个解决方案:
https://stackoverflow.com/questions/26995395/spring-mvc-interceptorhandler-called-twice-with-deferredresult
tv6aics12#
#2810 @sczyh30@brotherlu-xcq 使用栈来替换之前的引用计数
preHandler
入栈一个preEvent
postHandler
中入栈postEvent
在
afterCompletion
对事件进行闭合处理 ,一个postEvent
和他之前连续最远的一个preEvent
进行匹配闭合,