FGC频繁导致CPU 飙升定位及JVM配置优化总结

简介: FGC频繁导致CPU 飙升定位及JVM配置优化总结

本文为博主原创,未经允许不得转载:

目录:

  1. 定位消耗cpu 的服务进程和线程

  2. 定位FGC 的原因

  3. 定位jvm 参数是否导致FGC

  4. 调试最优解的 jvm 配置


  描述:项目中存在一个后台服务,该后台服务主要用来执行定时任务与kafka 中间件消息的消费。在压测环境上部署时,观察到 cpu 的使用率 异常,竟然达到了 600%, 所以记录下该问题的定位和解决过程,以帮助更多的伙伴。

1. 定位消耗cpu 的服务进程和线程

  使用top 命令查看 服务器的cpu使用情况

top

  获取 top 中cpu 占用率最高的进程的pid ,通过 top -H -P pid 获取该进程对应所有线程的使用情况

top -H -p pid

  通过上面命令得到使用cpu 最高的线程号 threadId ,将线程号通过命令转换为十六进制:

printf "%x\n" threadId

  通过以上命令获取到jvm中对应的 nid , 通过 jstack 查看该 threadId 线程的堆栈信息:

jstack -l pid| grep -10 nid

   通过以上命令判断该线程 执行任务的内容,从而推断导致cpu飙升的原因。

       项目中碰到导致cpu飙升的原因是 存在较多的 FGC 线程,从而怀疑 是 项目内部不断FGC 导致CPU飙升,从而监控项目的FGC 频率

2. 定位FGC 的原因

  通过 jstat 命令查看 FGC 的频率。

jstat  -gc   pid  3000

  发现 FGC 每隔三秒要进行9次左右的FGC垃圾回收。由于FGC 会导致STW (stop the world)现象,及服务不可用。

  需要定位 jvm 内存中的堆栈内容与线程。通过 Visualm 远程监控服务的jvm 性能,jvisualm 使用可参考这篇文章 (https://www.cnblogs.com/zjdxr-up/p/14916455.html),通过 jvisualm 查看服务当前存在的线程和堆内容。通过jvisualm 将堆内容与线程进行dump 之后,发现并未存在异常的内容。且 定时任务与kafka 都是开源的成熟框架,应该不会是导致频繁FGC 的主要原因。

  所以怀疑可能 服务的 jvm 参数配置存在问题,因为如果 jvm 参数设置不合理,当老年代的内存达到一定比例,则会进行FGC。下一步定位 jvm 的参数是否是主要原因。

3. 定位jvm 参数是否导致FGC

  由于我们的服务启动都会设置 最大堆内存和初始化堆内存等参数,所以需要调整 不同jvm 参数 时,服务内部的FGC 情况。

  以下为我们服务设置的 JVM 相关参数

-Xmn512m -Xms512m -Xmx2048m -XX:NewSize=512M -XX:MaxNewSize=512M -XX:-UseAdaptiveSizePlicy 
-XX:ParallelGCThreads=16 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:MaxTenuringThreshold=15

  为了形成做对比,采取 java -jar 的方式启动服务,不手动设置jvm相关配置,使用 JVM 默认的配置,进行观察是否有变化。

  通过 java -jar 方式启动,使用默认配置之后,再采用 top 观察cpu 使用 与 jstat 观察 FGC 频率,发现 cpu 的使用率降了下来,恢复了正常状态。

4. 调试最优解的 jvm 配置

  获取java -jar 服务启动的进程, 再使用 jinfo 命令 查看JVM 默认的配置,并修改以上jvm 的配置。我们服务器内存均为 32G,默认最大堆内存为 服务器内存的四分之一,即最大堆内存为 8G 。其余参数可根据最大堆内存进行推算出来,通常初始化内存与最大堆内存使用相同的配置。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。-Xmn 此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。年轻代大小 为 3G; 修改后的 jvm 配置参数如下:

-Xmn3072m -Xms8192m -Xmx8192m -XX:NewSize=3072M -XX:MaxNewSize=3072M -XX:-UseAdaptiveSizePlicy 
-XX:ParallelGCThreads=16 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:MaxTenuringThreshold=15

  补充:为了调试出相对比较好的jvm配置,将最大堆内存进行了多个配置对比,即从最大堆配置的值依次递增和递减 512M 之后,观察性能,发现默认配置依然最优解,所以才用默认配置作为服务启动的jvm配置

 

标签: JVM

相关文章
|
9月前
|
SQL 监控 关系型数据库
【紧急救援】MySQL CPU 100%!一套组合拳教你快速定位并解决!
凌晨三点MySQL CPU飙至100%,业务瘫痪!本文亲历30分钟应急排障全过程:从紧急止血、定位慢查询、分析锁争用,到优化SQL与索引,最终恢复服务。总结一套可复用的排查路径与预防方案,助你告别深夜救火。
|
SQL Java 关系型数据库
Dataphin功能Tips系列(53)-离线集成任务如何合理配置JVM资源
本文探讨了将MySQL数据同步至Hive时出现OOM问题的解决方案。
457 5
|
监控 Java Unix
6个Java 工具,轻松分析定位 JVM 问题 !
本文介绍了如何使用 JDK 自带工具查看和分析 JVM 的运行情况。通过编写一段测试代码(启动 10 个死循环线程,分配大量内存),结合常用工具如 `jps`、`jinfo`、`jstat`、`jstack`、`jvisualvm` 和 `jcmd` 等,详细展示了 JVM 参数配置、内存使用、线程状态及 GC 情况的监控方法。同时指出了一些常见问题,例如参数设置错误导致的内存异常,并通过实例说明了如何排查和解决。最后附上了官方文档链接,方便进一步学习。
3280 4
|
存储 设计模式 监控
快速定位并优化CPU 与 JVM 内存性能瓶颈
本文介绍了 Java 应用常见的 CPU & JVM 内存热点原因及优化思路。
1394 166
|
监控 C#
【Function App】如果一个拥有多个Function App的Plan遇见了High CPU问题? 如何方便定位是哪一个Function App引发的呢?
在Azure Function App测试中,若多个Function App共用同一App Service Plan资源,当出现High CPU问题时,由于Function App公开指标无法直接观测CPU状态,可通过启用Application Insights解决。其Live Metrics功能可过滤并查看每个Function App的CPU使用情况。具体步骤为:将所有Function App连接至同一Application Insights资源,进入Live Metrics页面按Role筛选监控数据。附有三段C#代码示例,分别展示占用CPU、Memory及普通功能的实现方法。
351 36
|
监控 Java 编译器
聊聊JVM如何优化
JVM的优化是一个复杂而细致的过程,涉及内存管理、垃圾回收、即时编译、线程调度等多个方面。通过合理配置JVM参数、选择合适的垃圾回收器、优化线程调度和使用专业的监控工具,可以大幅提升Java应用的性能和稳定性。掌握这些优化技巧,能够帮助开发者在高并发、高负载的生产环境中保持系统的高效运行。
812 13
|
存储 设计模式 监控
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
417 0
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
|
监控 关系型数据库 MySQL
如何解决 MySQL 数据库服务器 CPU 飙升的情况
大家好,我是 V 哥。当 MySQL 数据库服务器 CPU 飙升时,如何快速定位和解决问题至关重要。本文整理了一套实用的排查和优化套路,包括使用系统监控工具、分析慢查询日志、优化 SQL 查询、调整 MySQL 配置参数、优化数据库架构及检查硬件资源等步骤。通过一个电商业务系统的案例,详细展示了从问题发现到解决的全过程,帮助你有效降低 CPU 使用率,提升系统性能。关注 V 哥,掌握更多技术干货。
2198 0
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
SQL 监控 测试技术
一次压测引发的数据库CPU飙升...
一次压测过程中,当数据库的qps和tps都正常时,如果cpu利用率异常的高,应该如何排查?希望通过这篇文章,给你一些启发。