同事找我说突然服务挂掉了,无法启动。
查看服务日志
查看服务的报错日志报错信息
查看机器内存情况,物理课内存充足
[root@tdh1 ~]# free -mh
total used free shared buff/cache available
Mem: 187G 28G 78G 4.1G 80G 151G
Swap: 1.0G 0B 1.0G
cat /proc/meminfo
MemTotal: 196423944 kB
MemFree: 71891980 kB
MemAvailable: 149490964 kB
Buffers: 144056 kB
Cached: 70853176 kB
SwapCached: 0 kB
Active: 82742608 kB
Inactive: 25516240 kB
Active(anon): 39656096 kB
Inactive(anon): 1874780 kB
Active(file): 43086512 kB
Inactive(file): 23641460 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 1048572 kB
SwapFree: 1048572 kB
Dirty: 2440 kB
Writeback: 0 kB
AnonPages: 37263872 kB
Mapped: 732200 kB
Shmem: 4269264 kB
Slab: 14016912 kB
SReclaimable: 13310244 kB
SUnreclaim: 706668 kB
KernelStack: 130928 kB
PageTables: 163696 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 99260544 kB
Committed_AS: 241684328 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 737812 kB
VmallocChunk: 34258188984 kB
HardwareCorrupted: 4 kB
AnonHugePages: 6144 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 721096 kB
DirectMap2M: 39806976 kB
DirectMap1G: 161480704 kB
查看java日志,java 报申请不到内存。
奇怪了服务之前正常运行,中途也没有修改过服务的启动参数,物理机的内存也是充足的,java 怎么突然申请不到内存,突然挂掉了。
正要去看系统参数时,其他同事自首了,说他偷偷改了centos系统参数修改了**/etc/sysctl.conf** 配置文件把其他环境的直接cp到当前环境。还原原来的配置。服务正常启动。
看了他的配置文件改了vm.overcommit_memory = 2 这个参数(默认为0)。
科普时间:
overcommit_memory=0
默认设置,当应用进程尝试申请内存时,内核会做一个检测。内核将检查是否有足够的可用内存供应用进程使用;
如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
比如1G的机器,A进程已经使用了500M,当有另外进程尝试malloc 500M的内存时,内核就会进行check,发现超出剩余可用内存,就会提示失败。
overcommit_memory=1
对于内存的申请请求,内核不会做任何check,直到物理内存用完,触发 OOM 杀用户态进程。
比如1G 的机器,A进程500M,B进程尝试 malloc 500M,会成功,但是一旦kernel发现内存使用率接近1个G(内核有策略),就触发OOM,杀掉一些用户态的进程(有策略的杀)。
overcommit_memory=2
当请求申请的内存 >= SWAP内存大小 + 物理内存 * N,则拒绝此次内存申请。解释下这个N:N是一个百分比,根据overcommit_ratio/100来确定,比如overcommit_ratio=50,那么N就是50%。 vm.overcommit_ratio 只有当 vm.overcommit_memory = 2 的时候才会生效,内存可申请内存为 SWAP内存大小 + 物理内存 * overcommit_ratio/100。
当vm.overcommit_memory=2 下面参数生效:
CommitLimit:最大能分配的内存,具体的值是:SWAP内存大小(ecs均未开启) + 物理内存 * overcommit_ratio / 100;
Committed_AS:当前已经分配的内存大小;