好不容易搞個週六,被總監叫回去救火,鬱悶啊!
說是BT下載有內存泄露。跑兩小時就內核掛了。亂殺進程。
又出現了傳說中的內存泄露。哎。只好回公司。
首先進行問題定位。
先看是內核的還是應用的。經過對SLABINFO進行分析。發現是內核中一個數據結構在狂飈。這個數據結構就是ip_conntrack_expect。
基本可以定位是內核問題了。一看這玩意就知道是netfilter這一塊的事。然後對SVN進行查找。發現最近將對稱NAT改成了錐形NAT。這個地方非常可疑。因爲這個是要通過IPTABLES來操作NETFILTER的。
通過CGI將錐形NAT改成對稱NAT再掛BT兩小時,內存佔用量沒有任何內存增加的績像。再改回來,內存在不斷上漲。
在內核裏找了下。發現ipt_CONENAT.c是源頭。繼續分析。發現裏面有個timeout值爲:
.timeout = 60*60*24*365*10, // never timeout
問題已經非常明朗了,做死的掛BT,大家都在擠,有的擠不過去,老化時間又是無限長,內存不暴漲纔怪。
這時候已經晚上十一點了。找到原因後先規避。不讓用戶有設置全克隆NAT的配置接口。先發貨。
等回過頭再來改。要不然我明天的週日又要泡湯了。
本文檔允許轉載,但請註明出處。謝謝。
下面是對本文的一個補充。
上班後,花了將近三天時間對這個BUG進行修理。之前發現的超時值無限長不是問題的根源。而是申請的ip_conntrack_expect沒有進行合理的釋放。
其實這個BUG的解決其實很容易。就加了一行代碼。但是在解這個BUG的過程中將整個ip_conntrack的過程給理了一遍。感覺還是有所收穫的。其中比較有價值的地方就是tuple hash這個算法。tuple hash其實就一個正一個反,一個長度爲二的數組,這當中根據IP和端口二元TUPLE得到一個哈希值。有興趣的可以仔細看看代碼,函數名我也記不起來了。也不想再去翻一遍再列出來了。另外ip_conntrack的架構其實也是依賴掛的幾個HOOK。然後在這個過程中掛HOOK的優先級顯得比較重要。因爲這當中的層次結構還是比較明顯的。每一層是對上一層的一個補充。