線上服務被幹爆了,居然是日誌的鍋!!

本文要介紹的是一個發生在咱們線上環境的真實案例,問題發生在某次大促期間,對咱們的線上集羣形成了比較大的影響,這篇文章簡單覆盤一下這個問題。問了方便你們理解,實際排查和解決過程可能和本文描述的並不徹底一致,可是思路是同樣的。程序員

問題過程

某次大促期間,某一個線上應用忽然發生大量報警,提示磁盤佔用率太高,一度達到了80%多。數據庫

這種狀況咱們第一時間登陸線上機器,查看線上機器的磁盤使用狀況。使用命令:df查看磁盤佔用狀況。服務器

$df
Filesystem     1K-blocks    Used Available Use% Mounted on
/               62914560 58911440 4003120  93% /
/dev/sda2       62914560 58911440 4003120   93% /home/admin

發現機器磁盤確實耗費的比較嚴重,由於大促期間請求量比較多,因而咱們最早開始懷疑是否是日誌太多了,致使磁盤耗盡。網絡

這裏插播一個背景,咱們的線上機器是配置了日誌的自動壓縮和清理的,單個文件達到必定的大小,或者機器內容達到必定的閾值以後,就會自動觸發。運維

可是大促當天並無觸發日誌的清理,致使機器磁盤一度被耗盡。工具

通過排查,咱們發現是應用的某一些Log文件,佔用了極大的磁盤空間,而且還在不斷的增大。操作系統

du -sm * | sort -nr
512 service.log.20201105193331
256 service.log
428 service.log.20201106151311
286 service.log.20201107195011
356 service.log.20201108155838

du -sm * | sort -nr :統計當前目錄下文件大小,並按照大小排序計算機網絡

因而通過和運維同窗溝通,咱們決定進行緊急處理。日誌

首先採起的手段就是手動清理日誌文件,運維同窗登陸到服務器上面以後,手動的清理了一些不過重要的日誌文件。code

rm service.log.20201105193331

可是執行了清理命令以後,發現機器上面的磁盤使用率並無減小,並且仍是在不斷的增長。

$df
Filesystem     1K-blocks    Used Available Use% Mounted on
/               62914560 58911440 4003120  93% /
/dev/sda2       62914560 58911440 4003120  93% /home/admin

因而咱們開始排查爲何日誌被刪除以後,磁盤空間沒有被釋放,經過命令,咱們查到了是有一個進程還在對文件進行讀取。

lsof |grep deleted
SLS   11526  root   3r   REG   253,0 2665433605  104181296 /home/admin/****/service.log.20201205193331 (deleted)

lsof |grep deleted 的做用是:查看全部已打開文件並篩選出其中已刪除狀態的文件

通過排查,這個進程是一個SLS進程,在不斷的從機器上讀取日誌內容。

SLS是阿里的一個日誌服務,提供一站式提供數據收集、清洗、分析、可視化和告警功能。簡單點說就是會把服務器上面的日誌採集到,持久化,而後供查詢、分析等。

咱們線上日誌都會經過SLS進行採集,因此,經過分析,咱們發現磁盤空間沒釋放,和SLS的日誌讀取有關。

到這裏,問題基本已經定位到了,那麼咱們插播一下原理,介紹一下這背後的背景知識。

背景知識

Linux系統中是經過link的數量來控制文件刪除的,只有當一個文件不存在任何link的時候,這個文件纔會被刪除。

通常來講,每一個文件都有2個link計數器:i_count 和 i_nlink,也就是說:Linux系統中只有i_nlink及i_count都爲0的時候,這個文件纔會真正被刪除。   

  • i_count表示當前文件使用者(或被調用)的數量
  • i_nlink表示介質鏈接的數量(硬連接的數量);
  • 能夠理解爲i_count是內存引用計數器,i_nlink是磁盤的引用計數器。   

當一個文件被某一個進程引用時,對應i_count數就會增長;當建立文件的硬連接的時候,對應i_nlink數就會增長。

在Linux或者Unix系統中,經過rm或者文件管理器刪除文件,只是將它會從文件系統的目錄結構上解除連接(unlink),實際上就是減小磁盤引用計數i_nlink,可是並不會減小i_count數。

若是一個文件正在被某個進程調用,用戶使用rm命令把文件"刪除"了,這時候經過ls等文件管理命令就沒法找到這個文件了,可是並不意味着這個文件真正的從磁盤上刪除了。

由於還有一個進程在正常的執行,在向文件中讀取或寫入,也就是說文件其實並無被真正的"刪除",因此磁盤空間也就會一直被佔用。

而咱們的線上問題就是這個原理,由於有一個進程正在對日誌文件進行操做,因此其實rm操做並無將文件真正的刪除,因此磁盤空間並未釋放。

問題解決

在瞭解了線上的問題現象以及以上的相關背景知識以後,咱們就能夠想到辦法來解決這個問題了。

那就是想辦法把SLS進程對這個日誌文件的引用幹掉,文件就能夠真正的被刪除,磁盤空間就能真正的被釋放掉了。

kill -9 11526
$df
Filesystem     1K-blocks    Used Available Use% Mounted on
/               62914560 50331648 12582912  80% /
/dev/sda2       62914560 50331648 12582912  80% /home/admin

特別提醒下,在執行kill -9 以前,必定要考慮下執行的後果是什麼,背後原理能夠參考:我到服務器執行kill -9後,就被通知次日別來了!

過後,咱們通過覆盤,發現之因此出現這樣的問題,主要有兩個緣由:

  • 一、線上日誌打印太多,太頻繁
  • 二、SLS日誌拉取速度太慢

深刻分析後咱們發現,這個應用打印了不少過程日誌,最初日誌打印是爲了方便排查線上的問題,或者作數據分析用的,可是大促期間日誌量激增,致使磁盤空間佔用極速上升。

另外,由於該應用和幾個其餘的大應用共用了一份SLS的project,致使SLS拉取速度被拉低,進而致使進程一直沒法結束。

過後,咱們也總結了一些改進項,對於第二個問題,咱們對於該應用的SLS配置作拆分,獨立出來進行管理。

對於第一個問題,那就是大促期間引入日誌降級的策略,一旦發生磁盤爆滿,就是將日誌降級掉。

關於日誌降級,我開發了一個通用的工具,就是經過配置的方式,動態推送日誌級別,動態修改線上的日誌輸出級別。而且把這份配置的修改配置到咱們的預案平臺上,大促期間進行定時或者緊急預案處理,便可避免這個問題。

關於日誌降級工具的開發思路和相關代碼,下一篇文章中給你們分享。

思考

每次大促以後咱們覆盤,都會發現其實大多數問題都是由幾個不起眼的小問題堆積到一塊兒而引起的。

在問題分析過程當中每每會須要運用到不少非開發技能相關的知識,如操做系統、計算機網絡、數據庫、甚至硬件相關的知識。

因此我一直認爲,判斷一個程序員是否牛X,就看他的解決問題的能力!

相關文章
相關標籤/搜索