一、问题背景
某项目运行内存占用异常。
[root@JiJian bakend]# free -m
total used free shared buffers cached
Mem: 15886 15431 455 24 34 2461
-/+ buffers/cache: 12934 2951
Swap: 8071 2 8069
二、问题排查
1、查询进程内存占用情况,并排序,未发现异常:
ps aux --sort=-%mem | awk '{print $2, $6/1024 " MB", $11}' | head -n 11
PID 0 MB COMMAND
1159 765.434 MB /usr/lib/jvm/java-1.8.0-amazon-corretto//bin/java
2964 503.453 MB /opt/kaspersky/kesl/libexec/kesl
5057 394.562 MB /usr/sbin/mysqld
3838 42.2266 MB /opt/kaspersky/klnagent64/sbin/klnagent
2951 34.9102 MB /usr/bin/Xorg
3827 32.3945 MB /opt/kaspersky/klnagent64/sbin/klnagent
2871 29.1055 MB /usr/bin/python
2865 27.4727 MB /usr/bin/python
3741 27.1797 MB /temp/YLMonitor/YLMonitor
639 26.4492 MB /usr/lib/systemd/systemd-journald
2、查询特定进程的虚拟内存占用情况
ps -p 1159 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
[root@JiJian bin]# ps -p 1159 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
765.301 MB 10326.3 MB /usr/lib/jvm/java-1.8.0-amazon-corretto//bin/java
[root@JiJian bin]# ps -p 2964 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
503.496 MB 1311.21 MB /opt/kaspersky/kesl/libexec/kesl
[root@JiJian bin]# ps -p 5057 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
394.562 MB 1608.03 MB /usr/sbin/mysqld
[root@JiJian bin]# ps -p 3741 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
27.1797 MB 709.848 MB /temp/YLMonitor/YLMonitor
可以看到,存在某java程序占用虚拟内存超过10G,该进程或许存在问题。
三、相关措施【待验证】
Java进程占用的内存过大,可以考虑以下一些优化措施:
调整堆内存大小:通过修改Java虚拟机的
-Xms
和-Xmx
参数来调整堆内存大小。减小堆内存大小可以降低内存占用,但需要确保应用程序仍能正常运行。可以通过监控应用程序的内存使用情况来进行调整。检查代码:分析应用程序代码,查找内存泄漏或不必要的对象引用。确保在使用完对象后将其及时释放,以避免内存泄漏。
选择合适的垃圾收集器:根据应用程序的性能需求选择适当的垃圾收集器。某些垃圾收集器可能会更有效地管理内存,并减少内存占用。
使用内存分析工具:使用工具如Java VisualVM、MAT(Memory Analyzer Tool)等来分析内存使用情况,识别内存泄漏和性能瓶颈。
减少线程数量:减少不必要的线程和线程池的使用,因为每个线程都会占用一定的内存。
优化数据结构:选择合适的数据结构和集合类型,以减少内存占用。
升级到更高版本的Java:一些Java版本可能会提供更好的内存管理和性能优化,考虑升级到最新的Java版本。
考虑使用压缩类指针:Java 8及更高版本支持使用压缩类指针来减小元数据(Metaspace)的内存占用。
定期进行性能测试和监控:持续监控应用程序的内存使用情况,并定期进行性能测试,以确保内存占用在可接受范围内。
四、临时解决、待观察【测试成功】
1、先查看内存信息:cat /proc/meminfo
[root@JiJian ~]# cat /proc/meminfo
MemTotal: 16267700 kB
MemFree: 2694716 kB
MemAvailable: 3140684 kB
Buffers: 35500 kB
Cached: 749144 kB
SwapCached: 1328 kB
Active: 1662432 kB
Inactive: 985644 kB
Active(anon): 1231376 kB
Inactive(anon): 657568 kB
Active(file): 431056 kB
Inactive(file): 328076 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 8265724 kB
SwapFree: 8263416 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 1862316 kB
Mapped: 366572 kB
Shmem: 25508 kB
Slab: 121064 kB
SReclaimable: 49432 kB
SUnreclaim: 71632 kB
KernelStack: 9792 kB
PageTables: 66476 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 16399572 kB
Committed_AS: 2940700 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 181448 kB
VmallocChunk: 34346814608 kB
HardwareCorrupted: 0 kB
AnonHugePages: 1224704 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 219072 kB
DirectMap2M: 7120896 kB
DirectMap1G: 11534336 kB
2、查看Linux系统内核slab分配器信息。
3、查看dentry(目录项缓存)的信息。
cat /proc/sys/fs/dentry-state
[
23582 10007 45 0 0 0
4、释放系统内存。
echo 2 > /proc/sys/vm/drop_caches
5、查看释放后的内存占用情况,可以看到恢复正常。
[root@JiJian ~]# free -m
total used free shared buffers cached
Mem: 15886 13252 2633 24 34 706
-/+ buffers/cache: 12511 3375
Swap: 8071 2 8069
五、命令区别
echo 3 > /proc/sys/vm/drop_caches
和 echo 2 > /proc/sys/vm/drop_caches
都是用于清空Linux内核中的文件系统缓存(页缓存、目录项缓存和inode缓存)的命令,但它们的行为略有不同:
echo 3
> /proc/sys/vm/drop_caches
:
这个命令清空文件系统缓存,并且会清空目录项缓存、inode缓存以及页缓存。
它将释放大部分文件系统缓存,包括已缓存的文件数据和文件元数据。
这个命令通常在进行性能基准测试之前使用,以确保测试不受之前缓存的影响,或者在系统性能问题时可能需要释放缓存以解决问题。
echo 2
> /proc/sys/vm/drop_caches
:
这个命令清空文件系统缓存,但只清空页缓存,不会影响目录项缓存和inode缓存。
它只会释放已缓存的文件数据,而不会影响文件元数据(目录项和inode)。
这个命令在需要释放文件数据缓存时使用,但保留文件系统元数据,这对于某些应用和工作负载可能很有用。
通常情况下,echo 3 > /proc/sys/vm/drop_caches
用于清空全部文件系统缓存,而 echo 2 > /proc/sys/vm/drop_caches
用于清空文件数据缓存。选择使用哪个取决于具体需求,例如你是否需要保留目录项缓存和inode缓存。在生产环境中,请谨慎使用这些命令,因为清空缓存可能会对性能产生一些瞬时影响。