线上环境 FGC 频繁,如何解决?

发布时间:2026/7/8 9:02:31

线上环境 FGC 频繁,如何解决? 1、问题背景我们的服务遇到线上环境 FGC 频繁时我们是如何解决的。2、遇到的问题及解决方案2.1、pinpoint 打点存在大批量300ms以上排查方向检查db是否存在慢sql定位调用链中具体接口pinpoint inspector查看是否存在fullGC应用dubbo线程池是否耗尽(默认200个线程)打点存在大批量红点排查方向确认红点出现源头判断自己调用其他的业务服务是否存在超时)重启应用2.2、应用 cpu 突然升高排查方向应用是否存在fullGC检查应用流量是否突增是否存在不合理调用(可参考监控大盘)1、阈值标准pinpoint最近5min出现大批量超过5s以上的打点应用cpu 90%以上持续3min应用内存90%以上持续3min(瞬间暴增除外)收到上游最多两个以上业务方反馈2、解决措施打印线程栈jstack l 路径文件名.bindump jvm堆 jmap dump:format 路径文件名.bin重启应用运维执行命令/jenkins下游业务服务方响应超时sentinel consumer限流如果存在恶意攻击是联系安全部门拦截如果单业务流量大针对url或dubbo进行限流升级应用机器配置(一般是加机器)2.3、内存升的很快排查方向1、排查是否存在新版本发布的影响2、查询下调用频率较高的接口是否存在内存缓存的使用guava cache 和 caffeine cache3、查询下日志确定应用是否存在大批量的异常抛出2、解决措施打印线程栈jstack l 路径文件名.bindump jvm堆 jmap dump:format 路径文件名.bin重启应用运维执行命令/jenkins下游业务服务方响应超时sentinel consumer限流如果存在恶意攻击是联系安全部门拦截如果单业务流量大针对url或dubbo进行限流升级应用机器配置(一般是加机器)2.4、数据库 cpu持续90%以上10分钟ops是否明显增高(是否爬虫等异常流量)是否存在大批量数据查询(索引/动态sql)阈值标准数据库cpu100%持续2min且没有下降趋势链接数一直增加没有下降的趋势iops打满且没有下降的趋势内存使用率80%以上持续5min解决措施定向业务限流运维kill慢sql运维kill锁进程重启应用升级配置(但是需要考虑升级时间的影响问题)2.5、连接数线性增高且长时间不下查看是否存在慢sql查看应用的数据库连接池配置查看数据库中是否存在死锁show engine innodb status;解决措施定向业务限流运维kill慢sql运维kill锁进程重启应用升级配置(但是需要考虑升级时间的影响问题)2.6、iops飙高ddl操作是否针对大表新增索引是否存在变更大表字段业务上是否存在大批量操作(写入或读取)解决措施定向业务限流运维kill慢sql运维kill锁进程重启应用/升级配置(但是需要考虑升级时间的影响问题)2.7 内存升高确认下数据库连接数是否异常(连接也占用内存)解决措施定向业务限流运维kill慢sql运维kill锁进程重启应用/升级配置(但是需要考虑升级时间的影响问题)2.8、中间件MQ 消息堆积基本不需要处理2.9canal delay延时高排查方向大批量数据操作是否存在和其他业务共用canal受其他业务影响阈值标准garafa canal delay 延迟超过用户不可接受的范围解决措施业务评估无影响情况下联系运维重置消费位点2.10、线上环境 FGC 频繁1、明确分工这个步骤应该是在事前就已经明确好的类似于一个故障处理流程规范这边需要明确出3个主要角色1总指挥负责故障处理整体指挥的人例如快速拉起线上/线下会议、通知到系统核心同学对各同学工作进行分工等等。该角色一般由主管来担任或者主管指定的另一个同学。2故障恢复小组负责故障恢复的同学该部分同学的任务就是让系统以最快的速度恢复正常。3故障定位小组负责故障定位的同学该部分同学的任务就是定位出问题的根本原因。大部分同学的回答可能会集中在故障定位中但其实另外两个角色也是非常重要的在线上出现问题时止损永远是放在第一位其次才是定位。2、故障恢复2.1、线上发布导致查看故障服务近期是否存在上线操作如果有的话优先采取回滚解决。分析该场景应该是最常见的场景就是刚上的代码存在bug。2.2、非线上发布导致1小面积故障如果故障机器只是发布在少量机器例如某机台机器、某个机房机器、某个地域的机器、某个泳道的机器等等。此时优先采取禁用服务器解决禁用前先评估禁用这批机器后是否存在服务容量问题如果是则先扩容。分析该场景一般是代码存在bug但是该场景的使用频率很低所以上线时没暴露出来只是偶尔会被触发到。也是出现概率比较大的场景。2大面积故障如果故障机器不存在共性这个概率说实话非常非常小但是如果碰到了故障恢复小组能做的事情就比较有限了。因为这个场景大概率是代码存在bug同时发布时没有被大量触发而是到现在才被大量触发需要定位才能根本解决。此时故障恢复小组能做的就是使用扩容、重启、限流等手段来尽量维持服务的运转同时给故障定位争取时间。分析之所以说该场景概率小是因为分布在大量机器上的故障通常是使用频率高的场景这部分场景一般在服务发布时就会暴露出问题而不是发布很久之后。但是这个场景也是确实存在的但是会比较少。3、故障定位故障定位主要是用于应对故障恢复中的最后一个场景也是将故障恢复和故障定位分成两个小组并行执行的主要原因。3.1、FGC 能正常回收到内存通过监控或GC日志我们能看到每次FGC后都能正常回收到内存但是内存很快又被占满导致又出现FGC从而出现FGC频繁。这个场景通常可能由于两个原因导致1Eden 区配置太小导致大量对象直接进入老年代从而导致老年代快速被占满。2业务量较大特别是在业务高峰期。而当前的服务器配置已经无法满足当前的业务量。对于这两个原因代码本身可能没有大问题优先采取扩容机器降低单台服务器压力即可解决。后续则需要重新评估当前服务器的配置是否满足当前的业务量JVM参数是否存在优化空间等等。分析该场景是由于业务量增大没有及时评估或者JVM参数配置存在问题导致的整体来说出现的概率较小。3.2、FGC 不能正常回收到内存通过监控或GC日志我们能看到每次FGC后只能回收到很小的空间甚至回收不到空间从而出现FGC频繁。对于这个场景二话不说先dump下内存使用工具看下当前的内存泄漏情况、内存分布情况等等查看是哪个对象占用了大量内存。具体工具常见的例如 Eclipse MAT如果公司内部有封装的工具就更好了。通常查看完内存占用情况大概率会看到个别对象占用了大量的内存结合其引用链定位出在代码中的位置。接着就是根据代码分析问题的严重程度如果是小概率触发的场景大部分请求其实正常则可以先禁用问题机器后续上线修复即可。如果是大概率触发的场景则查看是否存在降级开关如果有则优先降级解决如果没有则只能修改代码走紧急修复流程。总结整体的解决流程其实还是比较简单的没有太复杂的东西。大多数情况下用好扩容、禁用、重启这几个常见手段即可解决大部分问题。个人经验而言线上频繁FGC问题90%以上是由于开发同学代码存在问题导致的例如常见的存在死循环、开无界队列等等。以上的问题在dump后很容易就能定位到根本原因。而如果遇到诸如依赖的第三方jar存在bug导致的问题例如Guava、Log4j这种场景一般是在极端情况下出才会出现所以一般只会出现在少数机器禁用即可临时解决然后后续再慢慢排查。

相关新闻