立秋已过,但成都仍是燥热难耐。现在已经晚上九点,经过一天暴晒的房子开始源源不断的释放热量,朝我奔袭而来,无处躲藏。不一会就已经满头大汗,在地心引力的作用下,汗珠从锁骨处越过高山,汇聚后顺着腹部深邃的沟壑往下流淌,又不断往两边分叉,肆无忌惮的在我身上写着“丰”字。我的思绪又开始天马行空的晃荡了,一会想着这个丰
字是不是预示着汗水将带来丰收,转念又思考,为什么没有汗流成河这个成语呢。
突然一阵铃声响起,我心里一惊,通常这个时候来的电话都没啥好事,不是宕机了就是宕机了。我拿起手机一看,是鹏哥打过来的,他今年给我打了四次电话,都是紧急事件。一阵寒意袭上心来,挡住了这夜的热浪。
“喂,鹏哥,找我啥事?” 我故作镇定的问道。
“水哥,是这样,我们这有台服务器,还有50多G内存,但是一启 apache ftp server
就报内存不足,它这个应该设置多大内存呀?” 鹏哥略显拘谨,小心翼翼的问道。
这让我有点不解, apache ftp server 就直接运行启动脚本就行了,也不需要特意设置内存,而且 ftp server 本身也不怎么吃内存,怎么可能启动就报错,一定是现场又把啥给搞错了,这还是第一次有人问我 ftp 部署的事。虽有一丝丝不快,但以我对鹏哥的了解,他一定又是和现场折腾了半天,实在搞不定了才来找我的。
继续追问,也用处不大,于是说到:“鹏哥,你把日志发我,我看一下”。
不一会,鹏哥发我发了 jvm crash 日志,日志显示:
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 4294967296 bytes for committing reserved memory.
# Possible reasons:
# The system is out of physical RAM or swap space
# The process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap
...
# Java VM: Java HotSpot(TM) 64-Bit Server VM (18.0.1.1+2-6, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
jvm 在 mmap 申请内存时就报错了,申请大概4G 内存。free -m
看了一下,free
内存有40多 G ,available
内存还有50多 G ,申请4G 内存咋会直接 crash 呢。
日志中显示用的 jdk 版本是 18.0 ,这是一个值得关注的点,咱公司啥时候用这么新的 jdk 了, 我们用 apache ftp server 一般也是在 jdk 1.8 上运行,是不是它俩配合有啥问题。 于是让现场运行一下 java -version
再判断一下版本,结果现场说执行 java -version
就报错了,也是无法申请足够内存。
想不到运气这么好,直接把 ftp server
与 jdk 18
结合有问题这个可能性给排除了。 内存肯定是够的,但是 java -version 都会报内存不够,这是为什么呢。我闭上眼睛,清空杂念,在脑海中把各种信息与我掌握的知识做关联,试着找出下一步排查的方向。
“爸爸,你看我画的这幅画怎么样。” 一阵可爱而又刺耳的声音不断的传来,把我从沉思中拉回来。这小调皮蛋捣乱从来不分场合呀,她没看出来我正在思考问题吗。
“你走开,爸爸有事。” 我没好气的呵斥道,边说边往屋外走去,留下宝宝委屈的呆站在原地,眼中泛着泪花。我来不及多想,径直走到客厅,继续思考。
于是又和鹏哥电话沟通,了解了一些情况
cat /proc/sys/vm/max_map_count
看了一下,配置很大,肯定用不完overcommit_memory
和 overcommit_ratio
两个值
95%
,也就是 128G * 95%网上的很多案例都指向了 overcommit_memory
这个配置,于是双让现场运行了一下命令:
grep -i commit /proc/meminfo
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fp5bn37L-1661388713525)(https://bed.cdpt.pro/ibed/2022/08/16/FGFl8Nqts.png)]
CommitLimit
好理解,就是其内存阈值: 128G * overcommit_ratio (95%)
Committed_AS
代表啥呢? 在 https://www.kernel.org/doc/html/v4.19/vm/overcommit-accounting.html
这篇贴子上有一句话:
- The current overcommit limit and amount committed are viewable in /proc/meminfo as CommitLimit and Committed_AS respectively.
意思是 Committed_AS
代表的是已经 Committed 的内存,根据前面查到的值, Committed_AS
跟 CommitLimit
只差 1G 多了,随便干点啥都可能会报申请不到足够的内存
了。
进程在申请内存时,它可能申请了并且分配使用了,这就是 Used
, 申请了但是还没用那就是 Committed
。 可以通过 overcommit_memory
参数来控制是否允许内存超配。
举个例子,航空公司售票:
Committed_AS
将 overcommit_memory
设置为 1 后,再运行 java -version
或者别的命令就不会报内存不够了,说明确实与此有关。
如果 overcommit_memory
设置为2(不允许超配),你就会发现即使还有大把内存,但是进程会报无法获取足够的内存。
那 jvm 的 Xms 和 Xmx 参数与 commit_memory 之间又有什么联系呢,我预想的是 Xms 代表 Used 内存,这个一定是被使用的内存, Xmx 代表 commit 的内存。试验之后,发现 Xmx 会占用一些 Commit 内存,但是没有分析出其比例关系。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OMNLC0uM-1661388713526)(https://bed.cdpt.pro/ibed/2022/08/16/FGIILzT3g.png)]