Spring boot tomcat因为maxHttpHeaderSize配置导致启动请求一会OOM

背景

项目上线后,发现过段时间就会请求失败OOM。经过排除,哪怕请求一个空的接口都会OOM,请求分配内存失败。

调试过程

先附上人家的调试过程:https://www.jianshu.com/p/28fdd66b976f
其实这个OOM如果直觉比较准的话(因为请求时好时坏,且整个服务没挂掉)直接从OOM的堆栈日志结合源码也能找到原因

问题原因

最后发现有次我在网上搜的spring boot配置文件上传,然后无脑从网上复制了一个配置maxHttpHeaderSize设了100M。

经过查看源码,是因为请求来了后,会先创建Http的Processor,然后将这个Processor缓存起来复用。
Processor中会直接根据maxHttpHeaderSize来申请http的inputBuffer和outputbuffer。
那么就导致了创建了几个Processor后内存就直接满了。后续的请求要分配新内存时就没有内存使用而出现OOM。

根据需要去掉maxHttpHeaderSize配置,或者不要写太大就行了。

具体源码可以查看RecycledProcessors及相关调用的位置。

public Http11Processor(AbstractHttp11Protocol<?> protocol, Adapter adapter) {
        super(adapter);
        this.protocol = protocol;

        httpParser = new HttpParser(protocol.getRelaxedPathChars(),
                protocol.getRelaxedQueryChars());

        inputBuffer = new Http11InputBuffer(request, protocol.getMaxHttpHeaderSize(),
                protocol.getRejectIllegalHeader(), httpParser);
        request.setInputBuffer(inputBuffer);
		//直接分配了内存
        outputBuffer = new Http11OutputBuffer(response, protocol.getMaxHttpHeaderSize());
        response.setOutputBuffer(outputBuffer);
        …………
protected Http11OutputBuffer(Response response, int headerBufferSize) {
        this.response = response;
        //直接分配了内存
        headerBuffer = ByteBuffer.allocate(headerBufferSize);

你可能感兴趣的:(java)