Tomcat killed 应用进程被Linux主动Killed
异常场景
- 接到反馈,应用中对外的RPC接口无响应
异常排查
- 检查dubbo admin ,应用接口无提供者
- 检查服务,top 检查不同应用的进程
- 查看日志,catalina.sh 打印 /data/application_name/tomcat/bin/catalina.sh: line 398: 30413 killed
- 场景收集:应用的上游接口在做接口压测,每次压测都会导致应用挂掉
- 堆栈日志:增加自动导出堆栈配置,应用挂掉后无日志生成;与应用本身无关
异常定位
- 服务器内存不足;当内存不足时,服务器会选择一个应用执行killed命令以释放内存
Linux 内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,这部分内存是属于每个进程的,内核直接回收利用的话比较麻烦,所以内核采用一种过度分配内存(over-commit memory)的办法来间接利用这部分 “空闲” 的内存,提高整体内存的使用效率。一般来说这样做没有问题,但当大多数应用程序都消耗完自己的内存的时候麻烦就来了,因为这些应用程序的内存需求加起来超出了物理内存(包括 swap)的容量,内核(OOM killer)必须杀掉一些进程才能腾出空间保障系统正常运行。用银行的例子来讲可能更容易懂一些,部分人取钱的时候银行不怕,银行有足够的存款应付,当全国人民(或者绝大多数)都取钱而且每个人都想把自己钱取完的时候银行的麻烦就来了,银行实际上是没有这么多钱给大家取的。
内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码 linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory() 被触发,然后调用 select_bad_process() 选择一个 “bad” 进程杀掉,如何判断和选择一个 “bad” 进程呢,总不能随机选吧?挑选的过程由 oom_badness() 决定,挑选的算法和想法都很简单很朴实:最 bad 的那个进程就是那个最占用内存的进程 1
异常反思
- 查询被killed进程的命令:
dmesg | egrep -i -B100 ‘killed process’
- dmesg 显示内核缓存区的内容
- egrep 正则表达式匹配内容2
- egrep是用extended regular expression语法来解读的,而grep则用basic regular expression 语法解读
- -i:ignore-case,忽略字符大小写3
- -A:显示之后两行 after
- -B:显示之前两行 before
- -C:显示上下两行 center