c++堆内存默认大小_线上内存暴涨问题定位和解决

2023年2月3日09:26:35

前因:

因为REST规范,定义资源获取接口使用GET请求,参数拼接在url上。

如果按上述定义,当参数过长,超过tomcat默认配置 max-http-header-size :8kb

会报一下错误信息:

Request header is too large

可以修改springboot配置,调整请求头大小

server:     max-http-header-size: xxx  复制代码

后果:

**如果max-http-header-size设置过大,会导致接口吞吐下降,jvm oom,内存泄漏。
**

因为tomcat 会用HeapByteBuffer 预分配请求头内存大小,在堆上分配。

c++堆内存默认大小_线上内存暴涨问题定位和解决

请求和响应都是一样的配置,每次请求处理预先分配,2倍配置值内存大小在 jvm 堆中

请求过多,导致线上内存暴涨,老年代有3GB多。使用jmap dump线上内存数据,使用 JProfiler 分析。

c++堆内存默认大小_线上内存暴涨问题定位和解决
c++堆内存默认大小_线上内存暴涨问题定位和解决

符合配置大小和源码对象

c++堆内存默认大小_线上内存暴涨问题定位和解决

数组有3GB,和老年代和eden区总和大小相近。

-XX:PretenureSizeThreshold jvm参数用来设置默认值,当数组或对象大小超过这个设定值,直接在 Old Gen 老年代分配;默认值0,当超过eden区的大小的时候,直接分配到old区。

使用 java -XX:+PrintCommandLineFlags -version

c++堆内存默认大小_线上内存暴涨问题定位和解决

发现并没有使用-XX:PretenureSizeThreshold参数,所以是

max-http-header-size设置过大,eden区分配不够,直接分配到old区,堆区内存不够,自动扩容,导致old区数据越来越多,频繁触发FullGC。

JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小 于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、 -Xmx相等以避免在每次GC后调整堆的大小。

c++堆内存默认大小_线上内存暴涨问题定位和解决
c++堆内存默认大小_线上内存暴涨问题定位和解决
c++堆内存默认大小_线上内存暴涨问题定位和解决

其中http-nio-9005-exec-线程有146个,和前面配置需要分配的20M内存请求,相乘的数据与3000MB相近。

c++堆内存默认大小_线上内存暴涨问题定位和解决

tomcat任务线程池 最大线程数200,存活时间60s

c++堆内存默认大小_线上内存暴涨问题定位和解决

因为TaskQueue 重写了offer方法,在线程池大小小于最大线程数时,任务不会放入任务队列,只会交给现有线程执行;存活时间60s,只有当线程空闲60s才会被回收,也就是**60秒内请求要小于当前线程数,**才会有空闲线程。这就导致了线程不能及时被回收。请求数下降,但是内存还是居高不下。

解决方案:

max-http-header-size修改为默认值,接口请求方式修改为POST,请求参数放置于body

  • 作者:weixin_39673947
  • 原文链接:https://blog.csdn.net/weixin_39673947/article/details/113049660
    更新时间:2023年2月3日09:26:35 ,共 1117 字。