在2019年10月21日,公司的一个后台应用中【生成营销活动数据】的操作,执行到一半突然不执行了,导致部分活动数据没生成,运营人员对此怨声载道的,因为影响了他们的运营效率了,要求我们技术人员尽快解决。
用的是腾讯云,内存配置是8G。
首先是从日志入手,grep
一下,发现线程执行到某一行代码后,就不往下执行了,因为:
try catch
捕获所有异常,但是也没看到异常日志;真是活见鬼了,线程不可能凭空消失,当时又从下面两个方向找了一下:
1、 有没有可能执行业务代码的过程中,代码里把异常给吞掉了,没有抛出来,后面一行一行代码仔细的看,并没有这样的代码;
2、 内存泄漏了,操作系统直接将进程给kill
掉了,通过查看/var/log/messages
日志,发现了如下信息:
java invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
看了一下时间点,刚好是线程不打印日志的时间点。那到底是谁想申请内存的时候,内存不足触发了这次的oom-killer
呢?从上面的信息里,看到了是JAVA
应用本身触发的。
java invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
从红色部分的java
字眼就可以看出来。那么当时这个JAVA
进程占用的实际物理内存是多少呢?可以从messages
文件里看到的。
[ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name
[ 353] 0 353 33677 169 72 0 0 systemd-journal
[ 386] 0 386 31198 102 28 0 0 lvmetad
[ 390] 0 390 11089 168 24 0 -1000 systemd-udevd
[ 574] 0 574 13877 165 27 0 -1000 auditd
[ 593] 0 593 6627 176 18 0 0 systemd-logind
[ 594] 998 594 135161 1429 61 0 0 polkitd
[ 598] 81 598 15074 233 34 0 -900 dbus-daemon
[ 603] 0 603 1096 42 8 0 0 acpid
[ 608] 997 608 2144 38 10 0 0 lsmd
[ 614] 0 614 31578 242 21 0 0 crond
[ 619] 0 619 6476 50 18 0 0 atd
[ 836] 0 836 143454 3314 99 0 0 tuned
[ 981] 0 981 9433 4597 14 0 0 secu-tcs-agent
[ 1251] 0 1251 27522 41 10 0 0 agetty
[ 1253] 0 1253 27522 41 11 0 0 agetty
[ 4595] 0 4595 24363 187 20 0 0 sgagent
[ 8538] 0 8538 38819 1642 30 0 0 barad_agent
[ 8539] 0 8539 41134 2094 34 0 0 barad_agent
[ 8540] 0 8540 316655 3358 62 0 0 barad_agent
[27410] 0 27410 25579 176 20 0 0 YDLive
[ 2537] 0 2537 28203 279 56 0 -1000 sshd
[ 2583] 995 2583 21282 218 42 0 0 zabbix_agentd
[ 2584] 995 2584 21282 358 42 0 0 zabbix_agentd
[ 2585] 995 2585 21313 333 44 0 0 zabbix_agentd
[ 2586] 995 2586 21313 302 44 0 0 zabbix_agentd
[ 2587] 995 2587 21313 320 44 0 0 zabbix_agentd
[ 2588] 995 2588 21315 287 44 0 0 zabbix_agentd
[ 9679] 0 9679 104952 70374 171 0 0 YDService
[32245] 0 32245 2850134 1825088 4092 0 0 java
[ 2450] 0 2450 222649 6005 265 0 0 rsyslogd
[23801] 0 23801 28293 108 14 0 0 watchdog.sh
[ 2370] 0 2370 26987 52 11 0 0 sleep
[ 2483] 0 2483 32643 292 21 0 0 crond
[ 2484] 0 2484 32643 292 21 0 0 crond
[ 2485] 0 2485 32643 292 21 0 0 crond
[ 2486] 0 2486 32643 292 21 0 0 crond
Out of memory: Kill process 32245 (java) score 886 or sacrifice child
Killed process 32245 (java) total-vm:11400536kB, anon-rss:7300352kB, file-rss:0kB, shmem-rss:0kB
被操作系统kill
掉的是java
进程是32245,占用的物理内存是:anon-rss:7300352kB,换算成G
的单位:
7300352/(1024*1024)=6.9G
而当时整个应用服务器上,所有进程占用的总的物理库存是(将rss列上的值累加起来):
(169+102+168+165+176+1429+233+42+38+242+50+3314+4597+41+41+187+1642+2094+3358+176+279+218+358+333+302+320+287+70374+1825088+6005+108+52+292+292+292+292)4/(10241024)=7.3G
这样看起来,还有几百兆的空余内存,但是还是触发了oom-killer
。谷歌一把,发现确实存在这种情况,但是具体是为啥,相关的文章讲的都不太清楚。暂时搞不懂,有网友知道原因,麻烦告知一下。
【生成营销活动数据】的操作是比较耗内存,且由于历史数据堆积的越来越多,造成了线程查询的数据会越来越多,便先将历史数据归档。另外由于该应用是个单体应用,堆积了非常多的功能,只要某个功能耗内存多了,都可能导致oom killer
,运营人员又死催烂催的,让我们感觉解决,因此先将机器的内存配置升级到16G
。
后面又多次跑了这个批量指派任务,没触发oom killer
了。