本文要介紹的是一個發生在我們線上環境的真實案例,問題發生在某次大促期間,對我們的線上集群造成了比較大的影響,這篇文章簡單復盤一下這個問題,問了方便大家理解,實際排查和解決程序可能和本文描述的并不完全一致,但是思路是一樣的,
問題程序
某次大促期間,某一個線上應用突然發生大量報警,提示磁盤占用率過高,一度達到了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 :統計當前目錄下檔案大小,并按照大小排序
于是經過和運維同學溝通,我們決定進行緊急處理,
首先采取的手段就是手動清理日志檔案,運維同學登錄到服務器上面之后,手動的清理了一些不太重要的日志檔案,
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后,就被通知第二天別來了!
事后,我們經過復盤,發現之所以出現這樣的問題,主要有兩個原因:
- 1、線上日志列印太多,太頻繁
- 2、SLS日志拉取速度太慢
深入分析后我們發現,這個應用列印了很多程序日志,最初日志列印是為了方便排查線上的問題,或者做資料分析用的,但是大促期間日志量激增,導致磁盤空間占用極速上升,
另外,因為該應用和幾個其他的大應用共用了一份SLS的project,導致SLS拉取速度被拉低,進而導致行程一直無法結束,
事后,我們也總結了一些改進項,對于第二個問題,我們對于該應用的SLS配置做拆分,獨立出來進行管理,
對于第一個問題,那就是大促期間引入日志降級的策略,一旦發生磁盤爆滿,就是將日志降級掉,
關于日志降級,我開發了一個通用的工具,就是通過配置的方式,動態推送日志級別,動態修改線上的日志輸出級別,并且把這份配置的修改配置到我們的預案平臺上,大促期間進行定時或者緊急預案處理,即可避免這個問題,
關于日志降級工具的開發思路和相關代碼,下一篇文章中給大家分享,
思考
每次大促之后我們復盤,都會發現其實大多數問題都是由幾個不起眼的小問題堆積到一起而引發的,
在問題分析程序中往往會需要運用到很多非開發技能相關的知識,如作業系統、計算機網路、資料庫、甚至硬體相關的知識,
所以我一直認為,判斷一個程式員是否牛X,就看他的解決問題的能力!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/231521.html
標籤:其他
