生产告警JVM内存使用率超过80%告警问题排查

背景

  • 我们的产品旨在为金融客户提供全面的解决方案服务,包括资金管理、交易处理等。我们的团队拥有丰富的行业经验和技术实力,能够根据客户的需求定制个性化的解决方案,并提供快速高效的实施和售后服务。 为了确保客户在使用我们的产品时能够获得最佳的体验和服务,公司提供了完善的监控服务。该监控平台可以实时监测产品的运行状态、性能指标,并及时发现和解决问题,保障客户的业务连续性和数据安全。

问题现象

  • 客户反馈在生产过程中出现了"内存使用率过高"的告警。经过检查,我们发现是JVM内存使用率超过了80%。

问题排查过程

  • Why: 首先怀疑是JVM内存配置有问题,因此让客户检查了JVM内存的配置。之前也出现过客户年轻代配置过小,导致很多对象都跑到老年代里面的情况。 Answer: 查看客户配置内存为-Xms:2048M -Xmx:4096 -Xmn:1512m,年轻代和老年代的比例符合1:2的要求,因此排除了这个原因。

  • Why: 接下来只能按照传统的方案导出dump文件进行分析,提供了客户两个命令:

    bash 复制代码
    # 导出dump文件
    jmap -dump:format=b,file=/home/admin/logs/heap.hprof 6214
    bash 复制代码
    # 执行一次full gc后导出dump文件
    jmap -dump:format=live,b,file=/home/admin/logs/heap.hprof 6214

    Answer: 导出两个文件后,发现第一个文件有2G大,但是第二个文件只有400M。因为环境限制就只能让客户把第二个小一点的文件拿下来分析。做这一步主要是用来判断服务是否发生内存泄漏,即存在对象不能释放。文件拿下分析之后发现并没有存在特殊的对象。

  • Why: 通过jprofiler分析了该文件并未找到有内存泄漏后,只能通过jstat去查看内存增长的过程中有没有异常。

    bash 复制代码
    # 间隔5秒钟打印20次服务垃圾回收情况
    jstat -gc 1212 5000 20

    Answer: 通过上述命令,因为监控的原因所以年轻代end区一直有对象创建,然后等到end区满了之后就触发了一次 Minor GC ,存活的对象晋升到了Servivor区;持续这个过程等到一次Minor GC时 Servivor区也满了时,能观察到Old区内存使用量有增长;然后直到Old区内存使用率超过80%仍然未触发full gc释放内存。

  • Why: 此时引申出一个问题,什么情况下会触发full gc? Answer: 通过以下命令主动触发一次full gc后,发现内存果然明显降低了,老年代内存被释放掉了。

    bash 复制代码
    		# 调用java.lang.System.gc()
    		jcmd [pid] GC.run

    因为gc机制跟垃圾收集器有关系,所以需要查看服务使用到的垃圾收集器。命令如下:

    bash 复制代码
    jmap -heap 29871

    通过上述命令看到我们项目使用的正式Java8默认是垃圾收集器,Parallel Scavenge垃圾收集器管理的新生代,ParOldGen表示由Parallel Old管理的老年代。然后就开始搜索Parallel Old相关的配置,网上文章较少,只能从实体书入手,经过阅读《Java虚拟器》后了解到该垃圾收集器并没有限制内存使用率达到多少就必须做full gc,只有CMS垃圾收集器才有这个限制。

问题分析

  • 经过上述排查过程,可以明显看出是监控项设置不合理所导致的问题。建议客户将对应限制调高或关闭以解决这个问题。另外,我们也可以考虑使用其他垃圾收集器来优化性能。

问题总结

  • 经过一整天的排查,我们终于找到了问题所在。然而,这次排查让我意识到了自己在JVM相关知识方面的不足。虽然之前也曾经多次排查过JVM相关的问题,但是一直没有形成完整的知识体系,导致每次都需要重新学习和查找资料。因此,我决定要梳理出一个完整的知识树,以便更好地解决今后工作中遇到的各种问题。
相关推荐
云烟成雨TD10 分钟前
Agent Scope Java 2.x 系列【11】中间件(Middleware):核心设计
java·人工智能·agent
心之伊始13 分钟前
Spring AI Chat Memory 实战:用 JDBC 给 Java Agent 加会话记忆
java·spring boot·agent·spring ai·chat memory
凡人叶枫16 分钟前
Effective C++ 条款40:明智而审慎地使用多重继承
java·数据库·c++·嵌入式开发·effective c++
放弃 治疗19 分钟前
宝塔面板安装 JDK 完整教程|Java 环境配置详解
java·开发语言
至此流年莫相忘31 分钟前
Spring 依赖注入三剑客:@Autowired、@Resource 与 @RequiredArgsConstructor 深度对比与实战指南
java·数据库·spring
码云骑士42 分钟前
23-Django-ORM的N+1问题-select_related与prefetch_related详解
后端·python·django
零陵上将军_xdr42 分钟前
为什么DCL单例要加volatile?——CPU乱序执行与内存屏障
java·linux
shushangyun_1 小时前
批发商城系统源码多少钱?2026最新报价一览
java·开发语言·人工智能·spring·spring cloud
cfm_29141 小时前
JVM深度详解:Class常量池、运行时常量池、字符串常量池、包装类对象池
java·jvm
JAVA面经实录9171 小时前
高频算法面试题
java·计算机网络·算法·面试