一次探索和修复服务器故障的经历
早上进入办公室,我平静的日常生活被一封电子邮件服务器警报、界面异常打断了。我立即专心追踪问题,直奔问题根源——Java进程的CPU使用率呈爆炸式增长,服务陷入停滞。
问题诊断
首先,我登录到服务器(CentOS7)并使用了主要工具,并在找到罪魁祸首正是Java进程,其CPU占用率高达100%,严重阻碍了后续服务的正常运行。接下来我调整了负载均衡策略,将有问题的服务器从集群中移除,以缓解压力。
接下来,我们通过jps命令发现Tomcat进程PID异常,假设为10086。进一步使用jstat-gcutil进行内存使用分析,发现了问题的关键问题:新生代使用ParNew收集器,而老年代使用CMS收集器,但是InitiatingOccupancyFraction设置为80%,这意味着一旦老年代的利用率达到80%以上,就会触发频繁的FGC(FullGarbageCollection),这显然加剧了服务的不稳定。
深入问题的根源
使用jmap-histo检查内存泄漏的迹象,导致大量的实例引起了我的注意。在查看代码时,我发现可能是由于频繁上传和下载图片导致的。然而,凭这一点并不能得出结论,因此我决定获取更详细的内存状态。
通过jmap-dump,我获取了一个缓存文件并将其导入到Eclipse的MAT工具中进行深入分析。结果暴露了一个令人烦恼的问题:名为IdleConnectionReaper的守护线程中的ArrayList内存太大,导致内存泄漏。该类负责管理上传和下载线程,但是默认的连接数非常大,导致内存消耗非常快。
问题定位及解决
深入研究了该类相关的代码和资料,发现了核心问题描述:代码为每次上传或下载操作创建一个新的OSSClient实例,由于过多的创建和销毁操作而积累了系统资源。为了解决这个问题,我修改了代码,使用单例模式来管理OSSClient,减少了资源浪费。经在线核实,问题得到缓解,服务稳定。
经验总结
这次经历让我深刻体会到在处理大规模需求时,我们必须注意内存消耗,合理使用合并技术,降低系统创建和销毁对象的总体成本。此外,CMS收集器的CPU占用率高、无法处理浮动垃圾、内存碎片等缺点也需要我们关注。通过调整UseCMSCompactAtFullCollection和CMSFullGCsBeforeCompaction参数,可以优化FGC策略,提高内存使用效率,保证服务稳定运行。
上一篇:java内存溢出dump文件命令
下一篇:Java占用内存一直升高