概述
在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
了。