项目实战典型案例20——内存长期占用导致系统慢

简介: 项目实战典型案例20——内存长期占用导致系统慢

内存长期占用导致系统慢

一:背景介绍

本篇博客是对生产环境出现内存长期占用系统慢的分析以及总结。目的是将经历转变为自己的经验。通过博客的方式分享给大家,大家一起共同进步和提高。

出现的问题

目前又出现了爬取加载慢的情况,核心服务的内存占用很高的情况。



二:思路&方案

服务内存占用过高的原因:

1.服务启动时分配的堆内存过小(与Xms和Xmx有关,-Xms 为JVM启动时申请的初始Heap值,-Xmx 为JVM运行时可申请的最大Heap值)
2.具有大量大对象被创建,并且没有及时被GC回收或者由于具有引用GC无法回收(代码中存在不合理的地方,需要进行代码调优)

3.当GC之后,虽然会清理堆内的对象看,但是并不会释放内存,没有把曾经申请到的内存归还给操作系统(与垃圾回收器和垃圾回收器的回收机制有关)

下面是对于这三个原因的解决方案

1.服务启动时分配的堆内存过小

我们可以通过在启动jar文件的时候进行Xms和Xmx的配置

如:nohup java -Xms3072m -Xmx4096m -jar a.jar&


-Xms
为JVM启动时申请的初始Heap值,默认为操作系统物理内存的1/64但小于1G。默认当空余堆内存大于70%时,JVM会减小heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRation来指定这个比列。

-Xmx 为JVM运行时可申请的最大Heap值,默认值为物理内存的1/4但小于1G,默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRation来指定这个比列。


nohup 不挂断的运行

& 指后台运行

2. 具有大量大对象被创建,并且没有及时被GC回收或者由于具有引用GC无法回收

这类问题是由于代码存在不合理的情况,需要进行代码调优。我们可以分析dump文件找到内存占用的原因。
首先生成系统快照dump文件:

执行命令:

jmap -dump:[live,]format=b,file=<filename> <pid>

通过-dump选项,把java堆中的对象dump到本地文件,pid为进程号

然后通过内存分析工具进行分析:如MATjvisual

示例: 使用jvisual分析dump文件,这个是jdk1.8自带的分析工具


启动jvisual载入下载下来的.hprof文件,之后就可以进行内存分析了。



3.当GC之后,虽然会清理堆内的对象看,但是并不会释放内存,没有把曾经申请到的内存归还给操作系统

这个主要与垃圾回收器垃圾回收器的回收机制有关

首先jvm明确目前使用的是哪一种垃圾回收器

cmd中输入以下命令:

java -XX:+PrintCommandLineFlags -version


虚拟机运行在Server模式下的默认值,打开此开关后,使用ParallelSeavenge+ParallelOld的收集器组合进行内存回收。

JDK1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)


目前已有的结论是full gc操作之后物理内存没有下降的原因与垃圾回收器回收的物理内存归还机制有关。

目前了解到1.CMS垃圾回收器,在内存开辟后,会随着System.gc()执行次数逐渐增多和回收频率逐渐拉长,从继续开辟内存到慢慢归还物理内存给操作系统,直到出现一次全部归还,就会在每次调用System.gc()都归还所有剩余的物理内存给操作系统;G1恰恰相反,G1是在JVM每次回收垃圾后,主动归还物理内存给操作系统,不做任何保留,大大降低了内存占用。

2.咱们目前使用的垃圾回收器的是ParallelSeavenge+ParallelOld

3.可以通过修改配置的方式更换垃圾回收器,如更换为G1

下一步的计划是了解ParallelSeavenge+ParallelOld物理内存归还机制.

选择更适合系统的垃圾回收器。

四:总结

由于出现内存长期占用导致系统慢这个问题是很早之前出现,现在进行复现比较困难。所以采取的是对于可能出现情况的一个分析,并没有深入的分析原因。

通过这次的分析,对于有与代码质量的原因造成的内存飙升问题,一方面可以通过代码质量进行解决,另一方面也可以通过压力测试的方式进行测试,避免由于代码原因导致内存飙升,并且居高不下。


另一方面,关于垃圾回收器的选择需要结合到实际情况进行选择

五:升华

博客中相当一部分内容是之间自己处理内存飙升和内存泄露的总结笔记。但是但是并没有进行及时总结导致还是缺很多东西。及时总结还真是一个事。进行及时总结,1+n,n+1。

目录
相关文章
|
6月前
|
存储 编译器 Go
Go 语言内存逃逸案例
Go 语言内存逃逸案例
33 0
|
2月前
|
存储 负载均衡 算法
负载均衡案例:如何只用2GB内存统计20亿个整数中出现次数最多的整数
负载均衡案例:如何只用2GB内存统计20亿个整数中出现次数最多的整数
32 2
|
2月前
|
缓存 Dubbo Java
案例 1: 某财险承保系统内存泄漏问题
案例 1: 某财险承保系统内存泄漏问题
|
9月前
|
Java 关系型数据库 MySQL
19-案例实战剖析-日处理上亿数据的系统内存分析和优化
这是当时开发中遇到的一个真实场景,也是大部分人在开发项目中有可能会遇到的一些场景,该系统主要是做大数据相关计算分析的,日处理数据量在上亿的规模。这里我们重点针对JVM内存的管理来进行模型分析,数据的来源获取主要是MYSQL数据库以及其他数据源里提取大量的数据,通过加载到JVM内存的过程我们来一起分析出现的问题以及如何优化解决
69 0
19-案例实战剖析-日处理上亿数据的系统内存分析和优化
|
1月前
|
存储 JSON 监控
Higress Controller**不是将配置信息推送到Istio的内存存储里面的**。
【2月更文挑战第30天】Higress Controller**不是将配置信息推送到Istio的内存存储里面的**。
14 1
|
1月前
|
存储 C语言
C语言--------数据在内存中的存储
C语言--------数据在内存中的存储
26 0
|
1天前
|
存储 算法
【三种方法】求一个整数存储在内存中二进制中的1的个数附两道课外练习题
【三种方法】求一个整数存储在内存中二进制中的1的个数附两道课外练习题
6 0
|
1天前
|
存储
数据在内存中的存储之整数存储
数据在内存中的存储之整数存储
8 0
|
8天前
|
存储 NoSQL Oracle
Oracle 12c的内存列存储:数据的“闪电侠”
【4月更文挑战第19天】Oracle 12c的内存列存储以超高速度革新数据处理,结合列存储与内存技术,实现快速查询与压缩。它支持向量化查询和并行处理,提升效率,但需合理配置以平衡系统资源。作为数据管理员,应善用此功能,适应业务需求和技术发展。