阿里云

一个springmvc使用不当引发的血案

2018-08-09  本文已影响171人  黄云斌huangyunbin

先说结论:是@FrameworkController的坑

一个同事和我反馈他们的health-check接口都很慢,在容器(2核)只有1000qps不到,这让我很想不通,health-check接口是没有任何逻辑的,直接返回一个ok而已
而且重点是这个health-check接口是公司的框架提供的,应该是没问题的啊
@FrameworkController
public class HealthCheckController {

    @RequestMapping(value = "/_health_check", method = RequestMethod.GET)
    public ResponseEntity<String> healthCheck() {
        return new ResponseEntity<String>("ok", HttpStatus.OK);
    }
}
然后我自己压测看了下,确实和他说的那样,1000qps左右。用jprofile看了下
image.png
cpu大部分都是在AccessController.doPrivileged这个方法上,这是个native方法
image.png
看到调用链发现,springmvc做接口匹配的时候,会构造ProduceMediaTypeExpression,这个对象的log居然不是静态字段,每次都会创建。
image.png
getFactory 会拿ClassLoader
image.png
拿ClassLoader会做权限检查
image.png
看起来一切事情都非常明白了,就是ProduceMediaTypeExpression比较傻逼,log这个字段居然都是不是静态字段。

但是health-check这种非常明确的接口,不应该做各种复杂的springmvc匹配逻辑啊。再次压测也注意到有匹配失败的


image.png
这个就有点想不通了,health-check是非常容易匹配的啊,然后我远程debug一下。发现是@FrameworkController的坑
image.png
@FrameworkController是放在FrameworkControllerHandlerMapping的,这个maping的放在最后的。
开始要去RequestMappingHandlerMapping匹配,匹配逻辑是先从urlmap中看有不有,health_check不在urlmap中,然后就挨个尝试复杂匹配。都匹配不到才到FrameworkControllerHandlerMapping。
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<Match> matches = new ArrayList<Match>();
        List<T> directPathMatches = this.urlMap.get(lookupPath);
        if (directPathMatches != null) {
            addMatchingMappings(directPathMatches, matches, request);
        }
        if (matches.isEmpty()) {
            // No choice but to go through all mappings...
            addMatchingMappings(this.handlerMethods.keySet(), matches, request);
        }

        if (!matches.isEmpty()) {
            ......
        }
        else {
            return handleNoMatch(handlerMethods.keySet(), lookupPath, request);
        }
    }

所以,最根本的原因还是@FrameworkController的坑。
ps:同事使用的springmvc的4.0.5,我看了下springmvc5是没有这个问题的。
然后让同事写用@Controller再写了_health_check,qps就上去了。

最后的问题就是:AccessController.doPrivileged这个方法为什么这么吃cpu呢?
上一篇下一篇

猜你喜欢

热点阅读