我一时兴起对测试环境的服务在进行压测的时候发现瞬时并发量居然不到三十就挂了.
我通过jstack导出内存线程发现很多请求线程在处理,因为是并发压测这很正常啊,没发现有死锁的情况.
然后我通过jstat -gc指令查看时发现jvm各区域的内存都满了,并且在不停的执行Full GC
我使用过jmap指令将内存快照导出,然后用MAT工具打开
可以看到内存被两种对象类型吃满,我去看一下Tree
通过潜堆和深堆的大小判断很明显最大的其实是byte,
展开org.apache.coyote.http11.Http11OutputBuffer对象可以验证:
java.nio.HeapByteBuffer中的数据就是上边的byte
但是这些对象都是数据tomcat里的呀,网上查了一下没有结果.
我展开看开一下对象下的引用
通过类名看到是headerBuffer,还有output字眼,猜测这应该就是响应头的缓冲区,
去看一下byte的内容
确定了这就是请求返回的头信息并且不包含消息体,剩下的都是000也就是空内容.
就是请求返回头的数据缓冲区过大导致.而且属于tomcat.
但项目用的是SpringBoot内置的Tomat,按理不会有这种问题.
当时没解决,线上环境是增大内存以保证服务正常,好在我们的系统瞬时并发并不高.
直到最近我在搭建项目监控平台时改项目配置的时候看到这项配置
server:
port: 30001
max-http-header-size: 10000000
http-header-size?10000000?
这个名字和数值怎么和我之前看到的byte名字和大小一致,都是header=10M
看了一下git提交记录,这是我入职之前的人提交的而且没人认识,commit写的是用于加快XXX的速度.
我点配置进去看了一下默认是0,也就是不配是可以的.于是我就重新做了一下压测.
确定了删除这行配置项目并发已经恢复正常,不会出现内存溢出问题.