当前位置: 首页 > 图灵资讯 > 技术篇> JVM系统优化实践(17):线上GC案例(二)

JVM系统优化实践(17):线上GC案例(二)

来源:图灵教育
时间:2023-04-19 16:19:49

  GC的概念并不难理解,它的原理也不复杂,但很难很好地使用它。为什么?由于每个平台、架构、指标、操作环境都不同,甚至(新手)工程师的编码习惯也不同,随意的代码可能会给操作和维护优化带来巨大的压力。因此,除了根据实际情况充分进行压力测试外,还有大量的实际案例。然后,许多案例将陆续发布。

  在线推广需要在特定时间内向所有用户发送短信、电子邮件和其他信息,以吸引比平时多几倍的大量用户参与。通过监控系统,我们了解到CPU卡住了,更严重、更强大的问题是:重启无效!

  众所周知,CPU负载过高的常见原因无非是:

  1、同时创建大量线程并发运行;

  2、二、JVM经常执行GC。

  检查完代码后,确定线程不是由代码引起的,然后检查Fullll GC问题。使用内存分析工具MAT。先用jmap导出内存快照,再用jhat或mat插件进行分析。可在eclipse官网下载Mat插件。

  MAT使用方法:

  1、MemoryAnaler修改.ini文件

  -startup

  plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar

  --launcher.library

  plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.700.v20180518-1200

  -vmargs

  -Xmx1024m

  2、如果jmap导出的dump文件比较大(比如几个G),在使用MAT之前,一定要先为MAT设置一堆内存大小,默认为1024M。

  jmap -F -dump:live,file=dump.hprof [PID](耗时较长)

  或者

  jmap [PID](快速生成)

JVM系统优化实践(17):线上GC案例(二)_GC

  1、Leak Suspects是基于对内存泄漏的分析,试图找出一批导致内存泄漏的对象;

  2、Component是分析对象的问题。

  MAT的最终定位问题是,由于在线系统使用缓存,缓存空间的大小没有限制,也没有指定LRU算法,导致空间耗尽。

  再来,继续。

  平台版本升级后,由于CPU负载飙升,系统无法使用。

  问题定位与排查:

  1、Fulllll通过jstat发现 GC每两分钟执行一次,异常耗时

  2、JVM配置为10G年轻一代(Eden:S0:S1 = 8:1:1),10G老年

  3、Eden一分钟就被塞满了,每次Young GC后,几个G对象进入老年

  4、这说明系统在运行过程中产生了大量的对象,处理非常缓慢

  5、这显然是代码层面的问题,仅仅依靠JVM优化是没有用的

  通过分析dump文件的内存泄漏问题,使用MAT找到问题代码。由于JDK不同版本的特性,String.split()产生问题。

  现在让我们回顾一下JVM技术的一些基本内容。

  一、JVMGC的运行原理

  1、JVM的内存区域分为年轻、老年和元空间;

  2、年轻一代分为Eden区和S0区、S1;

  3、在系统运行过程中,Eden区将不断创建各种对象;

  4、当Eden区域填满时,执行Young GC,在S0和S1之间使用复制算法来回复制生存对象;

  5、在以下情况下,对象将进入老年:年龄划分达到一定的阈值,大对象,Young GC后存活对象S0/S1放不下,动态年龄判断规则;

  6、老年Full GC触发规则:老年人使用的空间大于老年人的空间阈值。Young GC前:老年人的可用空间小于以前的Young GC后进入老年对象的平均大小,Young GC后:老年空间放不下Young GC后存活对象;

  7、CMS垃圾回收器通常用于老年垃圾回收;

  8、JVM优化的核心内容是减少Fulll GC的频率和耗时;

  2.如何设置JVM参数?

  1、首先要估算每个核心接口每秒的请求次数,以及每个请求所占用的空间大小,然后估计每秒占用多少空间;

  2、估计Eden区域将填满多久,然后估计Young执行多久 GC;

  3、估计有多少对象会上升到老年,有多少空间,有多长时间触发Fulll GC;

  4、这样,年轻人和老年人的空间就可以合理分配了。

  三、JVM参数设置原则

  1、尽量让Young GC后存活的对象远小于S0/S1;

  2、尽量避免对象进入或频繁进入老年;

  3、最理想的状态是老年空间使用稳定,几乎没有Fulll GC。

  四、压力测试后合理设置JVM参数

  用jstat观察JVM的运行过程,特别要注意Eden区的增长率,Young GC频率、Young GC耗时、Young GC后有多少对象存活,老年增长率,Full GC频率、Full GC耗时

  五、Fullll频繁发生 GC的几种疾病(这只是参考,就像体温升高不一定是感冒一样)

  1、机器CPU负载过高;

  2、频繁的Full GC报警;

  3、系统响应缓慢。

  六、Fullll频繁发生 GC的几个原因

  1、系统并发过高,数据处理量过大,导致Young GC频繁,每次Young GC后存活对象过多;

  2、内存空间分配不合理;

  3、将过多的数据一次加载到内存中;

  4、系统内存泄漏;

  5、元空间加载过多;

  6、误用System.gc()(System.gc()不一定不能用,但一定要有前提条件。很多新手喜欢炫耀自己的技能,结果是给自己找麻烦)。

  7.JVM中的一些痛点

  1、JVM优化实践在工作中;

  2、如何监控GC、定位、分析和解决GC问题;

  3、串起以前学过的所有内容;

  4、考虑GC问题,将系统负载提高到10倍和100倍;

  5、将GC问题与业务相结合,深入思考,根据JVM内存运行模型总结几个可能出现的性能问题,然后真理出一套方案;

  6、结合业务,总结公司级别的JVM模板。

  八、JVM优化注意事项

  许多博客会设置一些非常罕见的JVM参数,这是完全误导性的。真正的JVM优化:根据业务选择合适的垃圾回收器(如Parnewew)、CMS、G1),并根据实际性能调整GC的参数设置。

  FAQ:

  1、jxl导出excel时,会默认调用gc方法,需要注意;

  2、jstat一般用于分析死锁情况,看看哪个线程卡住了;

  3、当多个服务竞争资源时,可以考虑增加分布式锁。如果并发量高,可以考虑拆分服务,增加吞吐量;

  4、redisson框架可以实现一般redis分布式锁;

  5、如果选择减少G1的耗时,则意味着G1的GC次数增加;

  6、Full经常发生 GC,不一定是空间太小,甚至根本不是空间问题,需要结合实际业务情况多分析多思考;

  7、实际内存消耗往往比数据本身大得多。

  如果看不懂上面的,就回去看以前的文章。

  谢谢你的大司机!咨询技术、产品、运营和管理相关问题,请注意后留言。欢迎骚扰,我很荣幸~