这个Full GC问题是去年双12压测的时候触发的,中间排查的过程和踩的坑给大家借鉴一下。

线上问题

双12之前压测的时候起了很小的量,直接触发了Full GC,吓尿了,因为马上双12大促预热就要开始了,这搞不好妥妥的3.25啦。

赶紧拉群,把相关同学拉在一起排查问题。

第一时间查看GC日志:

可以看到原因是超过了Metadata GC的阈值,触发了Full GC,Metaspace从243M 回收到231M,基本没怎么回收掉,所以稍微再来点量,很容易再次触发Metaspace 的回收。

知识储备

GC问题排查需要很多储备知识,最主要是JVM相关的,之前文章已经讲过一些了,这里主要讲Matespace是什么?后面讲怎么做的GC问题的排查。

这里有二个知识点:

  • Matespace(元空间)是什么?在JVM中扮演什么角色,也就是存放什么的?

  • Full GC跟Matespace 大小设置有什么关系?

Matespace叫做元空间,从JDK 8开始,永久代(PermGen)的概念被废弃掉了,取而代之的是一个称为Metaspace的存储空间。

Metaspace用来存放:Class文件在JVM 里的运行时数据结构;以及存Klass相关的其他的内容,比如Method,ConstantPool等。

Metaspace使用的是本地内存,而不是堆内存,也就是说在默认情况下Metaspace的大小只与本地内存大小有关。但是很容易有个误区是Matespace可以随便用,不管使用多少,只要不超本地内存就不会触发GC,这是错误的。

Matespace的设置方式是:-XX: MetaspaceSize=**M, 这个JVM参数的作用是让Matespace 达到MetaspaceSize时触发Full GC, 如果不设置Matespace, 默认值很小,也就 20M左右(不同系统会有一点差别),如果程序Load Class比较多,很容易触发Full GC。这里要明白的是Class信息和加载Class 的ClassLoader 都存放在Metaspace,我们知道一个类是由这个类的类加载器加上全限定名(由包名&类名组成)确定唯一性的。

所以大家可以检查一下自己应用JVM Metaspace 设置的大小,如果没设置可以通过 -XX:+PrintFlagsInitial 查看一下默认值。

(之前文章发过GC日志的详细讲解以及JVM 参数的配置说明,如果有疑问的同学可以去看看历史文章。)

问题排查

刚开始看到 Full GC频繁,查看日志是由于Metaspace 空间不够造成的,第一反应是调整Metaspace 大小,把MetaspaceSize 从256M提高到了512M。但是发现Metaspace引发的Full GC还是没有消除。

立即dump了二台机器的日志,第一次分析GC 日志文件,没发现异常,这里有个注意的地方,大家dump文件时机很重要,有时候dump 的GC 日志没问题是因为刚好 Full GC完成之后dump的,内存回收的干干净净,有些内存缓慢增加的问题一定要在Full GC前dump。

期间我们还发现缓存相关的对象占用内存较高,但是经过分析,缓存对象生命周期本身就比较长,所以常驻在堆上,没有问题,继续看。

排查发现Metaspace内存占用是随着双12新接口压测流量的增长而增长,所以可以确定是新接口代码引入。

分析GC dump日志发现可疑点,同一个ClassCloader 加载了接近3000个,如下图所示,前面我们说过,ClassCloader 信息在Metaspace 区域。

破案了,fastjson使用不当引入了ASM Serializer的坑。

故障定位&修复

FastJson之所以快,原因就是使用asm字节码增强替代了反射。所以肯定是代码中应用了fastjson的ASM处理数据时造成的频繁加载同一个类,基本问题清楚了,那就是撸代码了,很快就定位了问题代码。

因为保密原因,不方便放原始代码,安琪拉撸了个类似逻辑的代码:

for(Item item -> arrays) {SerializeConfig serializeConfig = new SerializeConfig();serializeConfig.put(Custom.class, new CustomSerializer());jsonString = JSON.toJSONString(item, serializeConfig);
}

这段代码是自定义了一个序列化实现类CustomSerializer,在进行序列化时进行了一个类似AOP的切面处理,对所有Custom类型的字段进行统一自定义序列化(使用CustomSerializer)。

实现原理上是对需要序列化的Class使用asm动态生成了代理类,在这里就是Item类,使用SerializeConfig配置动态生成字节码代理类: com.alibaba.fastjson.serializer.ASMSerializer_1_Item,但是每次new SerializeConfig对象(内存地址不一样),FastJson会当作每次代理的目标是不一样的,导致每次会使用一个新的类加载器ASMClassLoader,所以Metaspace很快就满了,触发了频繁Full GC。

如果希望深入研究可以看下FastJson源码:

com.alibaba.fastjson.serializer.SerializeConfig#createASMSerializer

问题修复:

注册ObjectSerializer,让ObjectSerializer 成为全局唯一的,相当于是单例的。

SerializeConfig.getGlobalInstance().put(Character.class, new CharacterSerializer());

SerializeConfig 改成单例的后,每次序列化不用重复加载。

类似问题排查 & 调优

  1. 如果dump 日志发现很多classloader 名称前缀相同,排查是否有这种动态代理技术的使用,可能在不断生成代理对象。

  2. 发现内存缓慢增长,GC回收不掉,dump GC日志,查看是否有类被重复加载;

  3. Metaspace调优,比如我们现在生产环境 Metaspace 基本会设置256M 或者512M,可以根据应用的类型和机器内存配置来决定,因素:1. 是否会加载比较多的类,2. 机器内存允许, 可以适当调大Metaspace。

以上就是双12压测GC问题完整的排查方法论、详细过程和解决方案。

有道无术,术可成;有术无道,止于术

欢迎大家关注Java之道公众号

好文章,我在看❤️

双12压测引出的线上Full GC排查相关推荐

  1. 线上应用故障排查之二:高内存占用

    为什么80%的码农都做不了架构师?>>>    搞Java开发的,经常会碰到下面两种异常: 1.java.lang.OutOfMemoryError: PermGen space 2 ...

  2. Alibaba Cloud Toolkit 中SLS插件助力线上服务问题排查

    简介:Alibaba Cloud Toolkit 是一款非常优秀的插件,新增SLS日志服务的功能,针对软件开发者日常工作中常见的问题排查场景,将日志服务平台的功能集成到ide当中,省去了不同窗口之间来 ...

  3. Java线上应用故障排查之二:高内存占用

    前一篇介绍了线上应用故障排查之一:高CPU占用,这篇主要分析高内存占用故障的排查. 搞Java开发的,经常会碰到下面两种异常: 1.java.lang.OutOfMemoryError: PermGe ...

  4. Java线上应用故障排查之一:高内存占用

    Java线上应用故障排查之一:高内存占用 转载地址:http://www.blogjava.net/hankchen 搞Java开发的,经常会碰到下面两种异常: 1.java.lang.OutOfMe ...

  5. 线上基础问题排查常用手册

    线上基础问题排查常用手册 问题分类 业务问题 日志排查 代码逻辑排查 配置排查 性能问题 接口问题 JVM问题 Redis问题 MySQL问题 系统问题 实施手段 日志排查 阿里云 参考: https ...

  6. 2021阿里云弹性计算年度峰会将于12月21日开启线上直播,五大看点不容错过

    从2009年阿里云成立开始,到2010年推出首个弹性计算产品ECS,到2017年虚拟化架构零损耗的神龙架构横空出世,再到2021年发布计算巢生态战略,帮助合作伙伴云化升级:十二年,阿里云初心未改,一直 ...

  7. 宝洁网测、OT 线上测评

    宝洁OT包含四部分,下面为大家讲解: 1.成功驱动力测评 成功驱动力测评即性格测试一共64题,会在各个你不经意的问题中测试你的领导.团队协作能力.诚信,堪称刷人利器... 成功驱动力评估,不限时: 宝 ...

  8. 服务压测发现怪异现象,一顿排查,揪出“TIME_WAIT”这个内鬼

    点击关注公众号,Java干货及时送达 最近有同事在用 ab 进行服务压测,到 QPS 瓶颈后怀疑是起压机的问题,来跟我借测试机,于是我就趁机分析了一波起压机可能成为压测瓶颈的可能,除了网络 I/O.机 ...

  9. 服务压测发现怪异现象,一顿排查,揪出“TIME_WAIT”这个内鬼~

    点击关注公众号,回复"2T"获取2TB学习资源! 互联网架构师后台回复 2T 有特别礼包 上一篇:深夜看了张一鸣的微博,让我越想越后怕 来源:https://zhenbianshu ...

最新文章

  1. python3socket非阻塞_利用Python中SocketServer 实现客户端与服务器间非阻塞通信
  2. 在centos上搭建svn服务器
  3. C语言BFS算法的实现(附完整源码)
  4. Caffe: Faster-RCNN Python版本配置 (Windows)
  5. Redis和Memcache区别,优缺点对比
  6. C#面向对象设计模式第二讲:Singleton Pattern单件模式(创建型模式)
  7. Win7旗舰版系统网页显示不全怎么办
  8. LoadRunner性能测试-Std. Deviation标准差
  9. STL之multiset简介
  10. 孙玄吴守星:全方位剖析边缘计算架构设计以及应用实践
  11. 宽带连接工具[bat]
  12. 数据模型的概念,数据模型的作用和数据模型的三个要素
  13. excel中单元格的回车替换成其他字符
  14. 洛蒂(Lottie)
  15. 佐治亚理工计算机考研,美国佐治亚理工大学研究生专业排名多少?
  16. HTML期末作业-基于HTML+CSS+JavaScript制作学生信息管理系统模板
  17. Vue.js 内置指令
  18. 基于以太坊的区块链浏览器搭建
  19. meb备份mysql,MySQL企业版备份工具MEB
  20. 通信工程师考试简介(直播回放)

热门文章

  1. 网易易盾的“外挂对抗战”,游戏出海之路如何走得更安全?
  2. c语言加法结合性,C语言 运算符 的结合性 怎么理解?求举例子详细解答!!
  3. 我们变成了最小的,当我们发现不了最弱小的时候
  4. HelloWorld讲解
  5. (软件工程复习核心重点)第三章需求分析-第五节:验证软件需求
  6. event_base_loop
  7. 使用 GDB 恢复堆栈信息
  8. c++ winpcap开发(8)
  9. Error installing bundler:bundler requires Ruby version >= 2.3.0.
  10. python模块之 paramiko(转载)