我在运行 CentOS 的虚拟托管服务器上遇到了问题。上个月,一个运行良好的进程(基于 Java)在启动 JVM 时开始出现获取内存的问题。
我注意到一件奇怪的事情,当我启动该进程时,PID 显示它正在使用 470mb 的 RAM,而“已用”内存立即下降了 1GB 以上。如果我运行“top”,所有进程使用的总 RES 比顶部列出的“已用”内存少了近 700mb。
支持人员说这意味着我的进程有内存泄漏。我不知道该相信什么,因为我认为内存泄漏只会浪费分配给进程的内存,而不会消耗使用“top”时未显示的额外内存。
我是一名开发人员,而不是服务器人员,所以我向专家求助。对我来说,如果总 RES 内存不等于总“已用”内存,则表明我的虚拟服务器设置有问题。在这种情况下,我是否应该怀疑存在内存泄漏的 Java 进程?
如果我free
之前使用:
total used free shared buffers cached
Mem: 2097152 149264 1947888 0 0 0
-/+ buffers/cache: 149264 1947888
Swap: 0 0 0
free
后:
total used free shared buffers cached
Mem: 2097152 1094116 1003036 0 0 0
-/+ buffers/cache: 1094116 1003036
Swap: 0 0 0
因此看起来该进程正在使用(或导致使用)近 1GB 的 RAM。由于该进程(基于)top
仅使用 470mb,这是否意味着内核突然使用了额外的 500mb?
编辑:添加了cat proc/meminfo
- 的输出,并且 Java 应用程序正在运行:
MemTotal: 2097152 kB
MemFree: 1112672 kB
Buffers: 0 kB
Cached: 0 kB
SwapCached: 0 kB
Active: 0 kB
Inactive: 0 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 2097152 kB
LowFree: 1112672 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 0 kB
Mapped: 0 kB
Slab: 0 kB
PageTables: 0 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
CommitLimit: 0 kB
Committed_AS: 0 kB
VmallocTotal: 0 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 2048 kB
答案1
中的“已使用”字段top
反映的是正在使用的 RAM 总量,包括进程、文件缓冲区和缓存。但 RES 数字仅显示进程正在使用的 RAM 量,不包括文件缓冲区。
要真正了解没有缓冲区的情况下使用了多少 RAM,请使用该free
命令并查看该-/+ buffers/cache
行。“已用”列中的数字显示进程实际使用了多少 RAM。
以下是一个例子:
$ free
total used free shared buffers cached
Mem: 2057196 1812352 244844 0 344768 833660
-/+ buffers/cache: 633924 1423272
Swap: 2097148 0 2097148
此输出显示系统有 2GB RAM,其中 1.8GB 已被使用。但是,其中 344MB 由缓冲区使用,833MB 由缓存使用。减去这些后,只剩下 633MB 由进程和内核使用。
在启动 Java 应用程序之前和之后运行该free
命令,以更好地了解正在发生的事情。
编辑:删除了对内核内存的引用,这些工具并未报告这一点。
答案2
由于它是 VPS 主机,因此不要担心缓存和交换零。
I/O 缓存和交换可能由底层虚拟化主机处理,他们可能认为,通过他们的设置,在客户机中交换和缓存 I/O 会带来性能损失或其他影响,这可能是一件好事,因为这意味着您仅为您的进程就获得了 2GB 的 RAN。通常,托管服务提供商的工程师知道他们在做什么。
这也可能是为什么事情不太对劲的原因,因为由于您的 VPS 被监禁的方式(如果它们使用类似 OpenVZ 的东西),您可能无法看到所有占用您 RAM 的东西,但这些东西对于您的进程运行是必需的,因此会计入您的配额。
此外,如果您只比较一个 Java 进程,那么您无法了解全部情况,因为您的应用可能会启动其他进程,甚至一堆进程,这些进程加起来会很多。但是,没有考虑到这么多内存,这很容易导致 Java 应用出现内存泄漏。它很可能生成进程并分配 RAM,但没有正确地将它们返回给操作系统。
您的应用是否启动或使用任何本机进程?它是否生成其他进程或线程?