前言 我们在面试时,经常会被面试官问到:线上服务频繁Full GC该如何优化? 今天这篇文章跟大家一起聊聊这个话题,希望对你会有所帮助。 1. 什么是Full GC? 2.1 实时监控:GC健康度速诊 jstat -gcutil <pid> 1000 # 每秒输出GC数据 关键指标解读: OU:老年代使用率 > 90% = 危险区 FGCT:Full GC总耗时 Xmx8g -Xms8g -Xmn3g # 新生代3G (8*3/8≈3) -XX:SurvivorRatio=8 # Eden:Survivor=8:1:1 方案4:卸载无用类 场景:热部署频繁的应用 :ZAllocationSpikeTolerance=5.0 # 容忍内存分配速率波动 -Xmx16g -Xlog:gc*:file=gc.log 效果对比: 指标 CMS ZGC Full GC次数 15次/天 0次/天 最大暂停 2.8秒 1.2毫秒 方案6:堆外内存治理 现象:堆内存正常,但Full GC频繁 根源:DirectByteBuffer的清理依赖Full GC 防御方案: //
大家好,分享一个线上GC案例,相信会对大家有所帮助。 本人曾任职于阿里,每日优鲜等互联网公司,任技术总监。 在分享案例前,先聊聊哪些场景会导致频繁full gc: 1,内存泄漏(代码有问题,对象引用没及时释放,导致对象不能及时回收) 2,死循环 3,大对象 好,现在我们开始介绍这次线上故障: 在没有任何发布的情况下,pop服务突然开始疯狂full gc,观察堆内存监控没内存泄漏,回滚到前一版本,问题仍然存在。 与此同时另外的同学去查看数据库网络IO监控,如果网络IO有明显上升,并且时间点吻合,基本可以确定是大结果集导致了full gc,赶紧找DBA快速定位大SQL(对DBA来说很简单,分分钟搞定,如果DBA不知道怎么定位
若GC速度跟不上创建对象速度,还可能产生内存溢出。 3 高并发下的内存管理技巧 对开发者,GC不可控,无法避免。但可降低GC频率,减少进程暂停时长。 如把收到请求的Request对象在业务流程中一直传递下去,而非每执行一个步骤,就创建一个和Request对象差不多的新对象 那些需频繁使用,占用内存较大的一次性对象,可考虑自行回收并重用这些对象。 收到请求后,在对象池内申请一个对象,使用完后再放回对象池,这就能复用这些对象,有效避免频繁触发GC 使用更大内存的服务器。 根本解决该问题,办法只有一个:绕开自动GC机制,自己实现内存管理。 ,防止频繁Major GC,如果晋升的对象过多大于老年代的连续内存空间也会有触发Full Gc,然后在这些处理文本的业务流程中,防止频繁的创建一次性的大对象,把文本对象做为业务流程直接传递下去,如果这些文本需要复用可以将他保存起来 ,防止频繁的创建。
序 本文主要分析一个频繁GC (Allocation Failure)及young gc时间过长的case。 再突破100,150,200,250 在8.5天的时间内,发生了9000多次gc,其中full gc为4次,平均将近8秒,大部分是young gc(allocation failure为主),平均270 Full GC (Ergonomics) 这里可以到full gc的reason是Ergonomics,是因为开启了UseAdaptiveSizePolicy,jvm自己进行自适应调整引发的full gc GC (Allocation Failure) 分析完full gc之后我们看下young gc,看log里头99%都是GC (Allocation Failure)造成的young gc。 关于-XX:+PrintTenuringDistribution有几个要点,要明确一下: 这个打印的哪个区域的对象分布(survivor) 是在gc之前打印,还是在gc之后打印(gc之后打印) 一个新生对象第一次到
介绍 业务部门的一个同事遇到个奇怪的 Full GC 问题,有个服务迁移到新的应用后,一直频繁 Full GC。 当时就想如果是 System.gc() 引起的频繁 Full GC,jstack 线程堆栈应该能看到一些信息,果不其然,确实通过线程堆栈找到了。 ? (当然该问题,也可能不是频繁的 Full GC,可能通过 jstack 定位不到问题,可以 jstat -gccause pid 1000,来查看 gc 原因。) 可能大家还有个疑问,都知道 System.gc() 会触发 Full GC,那为什么一直进行 CMS GC(通过GC日志)呢? 总结 尽量减少显示使用 System.gc() 来触发 Full GC,这会导致频繁 Full GC,非常影响应用性能。
对于Full GC较多的情况,其主要有如下两个特征: 线上多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程 通过jstat命令监控GC情况,可以看到Full GC 这里我们基本上可以确定,当前系统缓慢的原因主要是垃圾回收过于频繁,导致GC停顿时间较长。 是由于System.gc()的显示调用导致的,而第二次GC则是JVM主动发起的。 次数还是比较多,此时可能是显示的 System.gc()调用导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。 CPU过高 在前面第一点中,我们讲到,CPU过高可能是系统频繁的进行Full GC,导致系统缓慢。而我们平常也肯能遇到比较耗时的计算,导致CPU过高的情况,此时查看方式其实与上面的非常类似。
在分享此案例前,先聊聊哪些场景会导致频繁Full GC: 内存泄漏(代码有问题,对象引用没及时释放,导致对象不能及时回收) 死循环 大对象 程序执行了System.gc() 尤其是大对象, 在没有任何发布的情况下,POP(point of purchase的缩写bai,意为“卖点广告”其主要商du业用途是刺激引导zhi消费和活跃dao卖场气氛)服务(接入第三方商家的服务)突然开始疯狂Full GC -Xloggc:gc.log -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX: 先按照常规做法分析堆内存快照,与此同时另外的同学去查看数据库服务器网络IO监控,如果数据库服务器网络IO有明显上升,并且时间点吻合,基本可以确定是数据库大结果集导致了Full GC,赶紧找DBA快速定位大
有FULL GC过于频繁的,有Young GC耗时过长,CPU飙升等,这些问题带来了影响是:GC过程中程序卡顿、程序执行耗时长、进一步导致服务超时从而影响到转换功能、基础上下游调用链。 影响用户体验将以最近一次基础服务FULL GC频繁的线上案例作为引子,详细介绍排查过程、思路、方法论;1、从最近一次基础服务FULL GC频繁的线上案例说起2、排查gc思路、方法论、过程3、GC的原理介绍一 、案例:2023-1-11至12号收到了基础配置服务监控告警频繁FULL GC,结合提示信息,使用skywalking找到具体的服务监控信息,通过skywalking追踪可以看到16点之前平均半个小时FULL YGC过于频繁:即使YGC不会引起服务超时,但是YGC过于频繁也会降低服务的整体性能,对于高并发服务也是需要关注的。 其中,「FGC过于频繁」和「YGC耗时过长」,这两种情况属于比较典型的GC问题,大概率会对程序的服务质量产生影响。剩余两种情况的严重程度低一些,但是对于高并发或者高可用的程序也需要关注。
前言 前几天收到线上某机器cms-initial-remark次数超过13次报警,这台机器长时间没有过新功能上线,为啥会出现频繁cms gc告警呢,遂一起排查。 输出启动参数 登陆了问题发生的机器。 cms gc的cycle数量达到了惊人的6543次 存在4次Mix GC,并且由‘promotion failed’原因导致 存在一次perm区溢出的cms gc 存在的问题已经比较清楚了 频繁发生cms gc 存在一定程度的promotion failed(这种gc的伤害比较大,应该尽量避免) 存在意思perm溢出 那为啥会频繁的开始cms collection cycle呢,先挑选几条cms的日志 从上述日志基本可以确定这台机器的频繁gc原因是由于perm区占用率大导致的。 B机器 在分析了这台机器是由于perm占用导致的cms gc后,我又查看了另外一台机器,发现了另外一个问题。 观察了几天没有再出现频繁cms gc的问题。 题外话 system gc 该机器的频繁cms gc原因找到了,再多分析一下cms gc的另外一个原因(System.gc)。
序 本文主要分析一个频繁产生对象造成gc时间过长的case。 症状及分析 gc时间过长,平均gc pause的时间要将近4秒,有13%的gc超过10秒,太可怕了,部分gc日志如下: [PSYoungGen: 457878K->126656K(489472K)] 1746043K ->1453131K(1887744K), 12.1965757 secs] [Times: user=5.59 sys=0.52, real=12.19 secs] 154415.774: [GC 1702667K->1392499K(1883136K), 0.1665513 secs] [Times: user=0.10 sys=0.00, real=0.17 secs] 154416.838: [GC 的统计数据,对于一个大的elasticsearch平台来说,返回的数据是巨大的,将近5000条数据,返回的json纯文件都要20多M,这个再加上定时任务/health查询,导致新生对象不断产生,ygc非常频繁
借由这次生产系统频繁宕机,我们总结一下 JVM 内存模型划分、JVM 启动堆内存相关参数配置及说明、各年龄代的垃圾回收器及回收过程、生产 GC 日志解读与分析、系统运行内存预估方法、启动参数如何优化等。 从下图 GC 日志可以看出,线上系统出现频繁 ParNew GC(即年轻代的 Minor GC),平均大约每 5 分钟进行一次 Minor GC,即一天平均执行 288 次之多,太可怕了吧!!! [题外话:为什么这么频繁,系统都线上运行3年了,当初系统上线JVM启动参数应该是随便设置的,呵呵? 2.7 pinpoint 随着用户量增加、系统并发增加,系统出现了频繁 Full GC,pinpoint 监控内存使用情况如下(只能监控老年代的 Full GC,而无法监控年轻代的 Minor GC,其实 Full GC 之前 Minor GC 执行次数频率更可怕): ?
随着数据规模的不断扩大和计算复杂度的提升,Spark应用常常面临频繁Full GC的困扰。 识别问题:如何检测和分析频繁Full GC 频繁Full GC是Spark应用性能恶化的典型信号,通常表现为任务执行时间显著延长、吞吐量急剧下降,甚至出现节点失联或任务失败。 配置失当模式 表现为不合理的GC触发频率或异常停顿时间,常见于以下场景: Young区过小导致频繁Young GC,日志中短时间间隔出现大量"[GC pause (young)"记录 Heap总体过小引发频繁 调优策略与示例配置 G1GC 调优的核心目标是平衡吞吐量和停顿时间,避免频繁 Full GC。 然而,过低的暂停时间目标可能迫使G1GC更频繁地执行垃圾回收,反而增加总体GC开销。
这篇文章的内容是业务开发同学遇到的奇怪的频繁 CMS GC 问题,我们一起定位排查,最终发现跟 -XX:CMSScavengeBeforeRemark 参数相关。 问题 频繁 Full GC 业务开发同学通过监控发现线上一台机器频繁 CMS GC,下图是 CMS GC 监控图,大约从 20 点 5-15 分,每分钟 8-11 次的持续 CMS GC。 ? 疑惑 第一次触发 CMS GC 可以通过 OldGen 的使用占比到达了 OldGen 总量的 80% 来解释,但是通过监控可以看到后来 OldGen 使用占比降低到 30% 以下,为什么还一直频繁进行 也就是说一般的 Allocation Failure 引起的 YoungGC 在这种情况下,不会出现频繁 CMS GC,因此,把问题归结到 -XX:CMSScavengeBeforeRemark 参数不为过吧 触发条件满足,进而引发了频繁 CMS GC。
一个 JVM 参数引发的频繁 CMS GC 简书 涤生。 转载请注明原创出处,谢谢! 如果读完觉得有收获的话,欢迎点赞加关注。 这篇文章的内容是业务开发同学遇到的奇怪的频繁 CMS GC 问题,我们一起定位排查,最终发现跟 -XX:CMSScavengeBeforeRemark 参数相关。 问题 频繁 Full GC 业务开发同学通过监控发现线上一台机器频繁 CMS GC,下图是 CMS GC 监控图,大约从 20 点 5-15 分,每分钟 8-11 次的持续 CMS GC。 疑惑 第一次触发 CMS GC 可以通过 OldGen 的使用占比到达了 OldGen 总量的 80% 来解释,但是通过监控可以看到后来 OldGen 使用占比降低到 30% 以下,为什么还一直频繁进行 触发条件满足,进而引发了频繁 CMS GC。
深度解析:频繁 Full GC 的诊断与根治方案在 Java 应用运行过程中,Full GC(全局垃圾回收)是影响系统稳定性的 “隐形杀手”。 本文将系统梳理频繁 Full GC 的成因、诊断方法与根治策略,帮助开发者从根源上解决问题。 一、频繁 Full GC 的危害与判定标准Full GC 的核心作用是回收老年代和永久代(JDK8 后为 Metaspace)的废弃对象,但频繁触发会带来多重风险:响应延迟:Full GC 期间,大部分情况下应用线程会暂停 内存泄漏导致老年代持续增长内存泄漏是频繁 Full GC 的首要元凶。当对象不再被使用却未被回收,长期驻留老年代,会导致内存占用持续上升,最终触发频繁 Full GC。 五、案例实战:从频繁 Full GC 到稳定运行某电商平台的商品详情接口在流量峰值时频繁超时,通过以下步骤解决:现象:GC 日志显示每 3 分钟触发一次 Full GC,每次耗时 1.2 秒,老年代使用率从
一次频繁full gc引发的问题排查 一、背景 刚发布的应用,间隔8小时不到,就开始告警,告警的位置还很特殊,属于调用外组接口的位置,让人费解。 最后查明原因,是大对象造成频繁full gc,这里,记录下排查问题的过程。 skywalking的监控信息也看下,发现两台机器在搞事情,gc很频繁。 所以可能是机器有问题?换个机器试试。因为是docker实例,随手可换。 先看下内存使用情况:jstat -gcutil 8 full gc这么高,肯定是有内存泄漏。要么是大对象,要么是流没关。 五、结论 没有结论是不完整的,但是这种full gc,其实就是查找内存泄漏的位置,需要借助于工具。
对于Full GC较多的情况,其主要有如下两个特征: 线上多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程 通过jstat命令监控GC情况,可以看到Full GC 这里我们基本上可以确定,当前系统缓慢的原因主要是垃圾回收过于频繁,导致GC停顿时间较长。 是由于System.gc()的显示调用导致的,而第二次GC则是JVM主动发起的。 次数还是比较多,此时可能是显示的 System.gc()调用导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。 CPU过高 在前面第一点中,我们讲到,CPU过高可能是系统频繁的进行Full GC,导致系统缓慢。而我们平常也肯能遇到比较耗时的计算,导致CPU过高的情况,此时查看方式其实与上面的非常类似。
继续追查cpu load飙高的原因,接着去看GC日志,发现大量的Allocation Failure,然后ParNew次数在每分钟100次以上,明显异常,见下GC日志例子 2020-03-25T16:16 太过频繁,每分钟最高100次以上,整体占用cpu时间还是很可观。 拷贝到内核态 kernel space,然后在拷贝到网卡进行发送(像netty等的零拷贝针对的就是这种拷贝),加上响应体查询过程中,涉及的大量临时对象list,在高并发场景下,就导致年轻代内存占满,然后频繁 gc(后续在合适的时间会压测该接口),这里还有一个点,很多人以为ParNewGC不会stop the world,其实是会的。 频繁ParNewGC造成用户线程进入阻塞状态,让出CPU时间片,最终导致连接处理等待,接口的RT变高。
上线后没多久,就收到了频繁 GC 的告警。然后排查下来发现指标数据已经堆积了很多。
原因包括业务逻辑问题(死循环)、频繁gc以及上下文切换过多。而最常见的往往是业务逻辑(或者框架逻辑)导致的,可以使用jstack来分析对应的堆栈情况。 频繁GC问题通过使用jstat工具的-gc选项,我们可以观察GC的分代变化情况,以便确定GC是否过于频繁。 如果这些值接近或达到其最大值,则可能需要进行GC。EC/EU:这两个指标分别表示Eden区的当前容量和已使用的容量。如果这些值接近或达到其最大值,则可能需要进行GC。 如果这些值接近或达到其最大值,则可能需要进行GC。MC/MU:这两个指标分别表示元数据区的当前容量和已使用的容量。如果这些值接近或达到其最大值,则可能需要进行GC。 如果发现GC过于频繁或存在其他问题,我们可以进一步分析并采取相应的优化措施。频繁上下文切换上下文切换会消耗CPU的时间,并导致进程真正运行的时间缩短,从而成为系统性能下降的一个因素。