Java 内存暴涨 Java详解线上内存暴涨问题定位和解决方案

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Java 内存暴涨 Java详解线上内存暴涨问题定位和解决方案

该用户快成仙了   2021-10-29 我要评论
想了解Java详解线上内存暴涨问题定位和解决方案的相关内容吗,该用户快成仙了在本文为您仔细讲解Java 内存暴涨的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Java,内存暴涨,Java,内存无限增长,下面大家一起来学习吧。

前因:

因为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 预分配请求头内存大小,在堆上分配。

线上内存暴涨问题定位和解决

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

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

线上内存暴涨问题定位和解决

线上内存暴涨问题定位和解决

符合配置大小和源码对象

线上内存暴涨问题定位和解决

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


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

使用 java -XX:+PrintCommandLineFlags -version

线上内存暴涨问题定位和解决

发现并没有使用
-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后调整堆的大小。

线上内存暴涨问题定位和解决

线上内存暴涨问题定位和解决

线上内存暴涨问题定位和解决

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

线上内存暴涨问题定位和解决

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

线上内存暴涨问题定位和解决

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

解决方案:

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

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们