java進程被內核kill的分析

前幾日,同事收到不少異常報警,發現調用下游一個基礎服務大量超時。通過討論,爲了防止服務宕機,咱們把流量入口給攔住(咱們的系統主要是處理上游推下來的Mq消息,就是將Mq消費入口給攔了)。咱們還想着這樣就能萬事大吉應該不會產生髒數據。默默的等着下游系統解決問題。忽然陸續收到服務宕機,7臺核心業務服務器無一倖免全都掛了。java

這時,咱們想找出dump信息,看是否是jvm觸發的,結果找了一圈都沒有看到相關信息。既然,沒有dump信息那確定就不是JVM觸發的kill(由於咱們線上服務都開啓異常自動dump堆棧的功能)。難道是內核由於內存不足觸發的嗎?觸發日誌在哪裏能夠看到呢?因爲頭次遇到,只能藉助網上的力量,網上說輸入 grep 'Out of memory' /var/log/messages。(其實就是在系統日誌裏面查看是否是能找到內存溢出的相關信息),果真有相似日誌,以下圖所示: linux

可是,日誌也看不出來是什麼緣由致使的kill啊。想着上下翻動日誌,看不懂。這個時候又只能藉助網絡。網上說內核觸發了kill也能夠經過 dmesg 命令查看(該命令是記錄開機啓動信息的)。經過現學,發現其實在上圖的那條日誌前面還保存了,內核kill進程以前的內存佔用狀況。以下圖所示: 算法

這是在圖中找到了答案,系統總內存是8G,而filebeat(架構組的日誌採集工具)佔用2個多G,java進程佔用4個多G(大小取上圖RSS列,這裏表明的是有多少個pageCache,liunx每pageCache等於4kb。因此就是pageCache * 4kb)。系統殺掉了java進程(就是linux內核的OOM Killer殺掉的)。可是爲何進程不殺filebeat進程,而是殺java進程呢?其實這裏系統本身有個算分算法(基礎分+系統根據內存狀況自動打分 ,存放目錄在:/proc/pid/oom_score),OOM Killer會找到等分最高的殺掉。咱們能夠手動修改每一個進程的基礎分(-1000到1000,默認是0,存放目錄:/proc/pid/oom_score_adj)。其實架構組已經將基礎分調整到100了。可是系統打分仍是過低了。因此就殺掉了java進程。圖一能夠看到,java進程的得分是 578 分。如今咱們把filebeat的基礎得分調成了 999。但願下次若是有類型狀況發生先kill filebeat的進程服務器

上面只分析了,爲何老是殺掉的Java進程。可是,爲何filebeat會佔用如此大的內存,一般filebeat的內存大小也就在300M左右,此次忽然上了2G。這個現象很奇怪。其實filebeat有兩個因素直接影響內存佔用狀況,1.是日誌大小 2.是filebeat處理日誌時配置的queue大小。咱們的系統偏偏是這兩個緣由致使的,1.調用下游系統超時,因此產生了不少堆棧日誌。2.沒有指定隊列大小,默認是2048.網絡

相關文章
相關標籤/搜索