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

 更新时间:2021年10月29日 11:15:43   作者:该用户快成仙了  
本篇文章介绍了我在开发过程中遇到的线上内存暴涨的问题,以及定位问题原因和解决该问题的过程及思路,通读本篇对大家的学习或工作具有一定的价值,需要的朋友可以参考下

前因:

因为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

到此这篇关于Java详解线上内存暴涨问题定位和解决方案的文章就介绍到这了,更多相关Java 内存暴涨内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot中关于static和templates的注意事项以及webjars的配置

    SpringBoot中关于static和templates的注意事项以及webjars的配置

    今天小编就为大家分享一篇关于SpringBoot中关于static和templates的注意事项以及webjars的配置,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Java中JVM常用参数配置教程(提供配置示例)

    Java中JVM常用参数配置教程(提供配置示例)

    这篇文章主要给大家介绍了关于Java中JVM常用参数配置的相关资料, jvm的参数有很多,必须知道参数分类并且记住面试常见的几个参数,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • Java 循环队列/环形队列的实现流程

    Java 循环队列/环形队列的实现流程

    循环队列又叫环形队列,是一种特殊的队列。循环队列解决了队列出队时需要将所有数据前移一位的问题。本文将带大家详细了解循环队列如何实现,需要的朋友可以参考一下
    2022-02-02
  • JAVA封装多线程实现的方式及原理

    JAVA封装多线程实现的方式及原理

    这篇文章主要介绍了Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下
    2025-03-03
  • 超详细解释Java反射

    超详细解释Java反射

    本文非常详细的讲解了java反射具体的内容以及使用,java反射在现今的使用中很频繁,希望此文可以帮大家解答疑惑,可以帮助大家理解
    2021-11-11
  • Mybatis-Plus 条件构造器示例详解

    Mybatis-Plus 条件构造器示例详解

    这篇文章主要介绍了Mybatis-Plus 条件构造器的相关资料,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • Java线程实现时间动态显示

    Java线程实现时间动态显示

    这篇文章主要为大家详细介绍了Java线程实现时间动态显示,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • SpringBoot集成本地缓存性能之王Caffeine示例详解

    SpringBoot集成本地缓存性能之王Caffeine示例详解

    这篇文章主要为大家介绍了SpringBoot集成本地缓存性能之王Caffeine的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • Java 六类运算符详解

    Java 六类运算符详解

    这篇文章主要介绍了Java 六类运算符,在 Java 语言中,运算符有算数运算符、关系运算符、逻辑运算符、赋值运算符、字符串连接运算符、条件运算符,感兴趣的朋友可以阅读一下
    2023-03-03
  • Spring 中优雅的获取泛型信息的方法

    Spring 中优雅的获取泛型信息的方法

    这篇文章主要介绍了Spring 中优雅的获取泛型信息的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03

最新评论