问题现象:部署在中农网的mock系统启动过程中catalina.out日志启动过程日志打印突然暂停,无报错,tomcat进程停止
问题定位:tomcat下logs日志都看过,没有任何出现异常日志输出,同项目下所有应用在同一台机器上,怀疑可能是资源不够问题导致,但是其它应用可正常启动,无此问题,经过比较后发现mock系统catalina.sh里未配置JAVA_OPTS="-Xms1024m -Xmx1024m -Xss1024K",而其它项目里有,加上后重启,问题不再复现。
疑问:如果是启动过程中内存不够应该会报内存溢出等问题,实际没有,请教运维提供查看系统日志得方式定位。
问题分析:再去掉堆内存配置等信息复现下问题,观察系统日志
journalctl -xe >> 1.log
发现有进程被kill掉。
为了理解这个错误,我们先回顾一下操作系统相关的基础知识。
我们知道,操作系统(operating system)构建在进程(process)的基础上. 进程由内核作业(kernel jobs)进行调度和维护, 其中有一个内核作业称为 “Out of memory killer(OOM终结者)”, 与本节所讲的 OutOfMemoryError 有关。
Out of memory killer在可用内存极低的情况下会杀死某些进程。只要达到触发条件就会激活,选中某个进程并杀掉。 通常采用启发式算法, 对所有进程计算评分(heuristics scoring), 得分最低的进程将被 kill 掉。因此 Out of memory: Kill process or sacrifice child和前面所讲的OutOfMemoryError都不同,因为它既不由JVM触发,也不由JVM代理, 而是系统内核内置的一种安全保护措施。
默认情况下, Linux kernels(内核)允许进程申请的量超过系统可用内存. 这是因为,在大多数情况下, 很多进程申请了很多内存, 但实际使用的量并没有那么多. 有个简单的类比,宽带租赁的服务商, 可能他的总带宽只有 10Gbps, 但却卖出远远超过100份以上的 100Mbps 带宽, 原因是多数时候, 宽带用户之间是错峰的, 而且不可能每个用户都用满服务商所承诺的带宽。
这样的话,可能会有一个问题, 假若某些程序占用了大量的系统内存, 那么可用内存量就会极小, 导致没有内存页面(pages)可以分配给需要的进程。可能这时候会出现极端情况, 就是 root 用户也不能通过 kill 来杀掉流氓进程. 为了防止发生这种情况, 系统会自动激活 killer, 查找流氓进程并将其杀死。
总结下来就是,tomcat启动未配置堆内存时,tomcat会无限的申请内存,申请到一定容量时候,触发了killer进程,killer进程根据算法清除掉了当前的tomcat进程。