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](快速生成)
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、实际内存消耗往往比数据本身大得多。
如果看不懂上面的,就回去看以前的文章。
谢谢你的大司机!咨询技术、产品、运营和管理相关问题,请注意后留言。欢迎骚扰,我很荣幸~