linux一次Too many open files的排錯經歷

轉自:http://www.zuidaima.com/blog/3193963557981184.htm

這是一個發生在穩定性測試環境上的bug,簡單描述下項目的架構:

項目的結構可分爲四個部分,web端、數據中心、監控節點、ping節點。web端和具體的業務分開,只負責展示(tomcat進程),數據中心負責任務下發和數據回寫的解析、分析以及入庫(java進程),監控節點接收數據中心下發的任務,負責採集需要監控的設備的數據並解析組裝然後發送給數據中心進行數據保存(java進程);ping節點接收數據中心下發的ping任務,負責可用性檢測(當然現在很多企業對設備都是禁ping的,這種檢測機制我們後面在做改變)(java進程);這幾個服務間通過zeromq的push/pull方式進行通信。

從上面簡單的描述可以看出,監控節點和ping節點是可以多機分佈式部署的,也可以單機多進程部署

問題:在測試環境跑了一段時間後,突然出現設備全面宕機的問題,但是實際情況是這是一次假宕機,設備真實的狀態是正常的,從監控節點的日誌中可以看出任務一直是按照給定的頻率在執行。這大概能夠判斷是ping節點的問題,因爲設備的可用性狀態是根據ping結果去判斷的,於是拿出ping節點的日誌來看,發現執行了一段時間後,報錯如下:

linux一次Too many open files的排錯經歷

too many open files,除了這個異常其他任何異常都沒有,簡單解釋下這個報錯,在linux環境下,任何事物都是以文件的形式存在,我們模擬一條ping命令都是會打開一個文件句柄,造成這個問題的原因是linux中的文件句柄數已經達到了設置的最高值,所以後面再來ping任務,都不會去執行了,結果我們的系統默認就是宕機狀態了。

找到了產生這個異常的原因後,我查了下我們系統設置的最大文件句柄數 ulimit -n,果真是默認值1024

linux一次Too many open files的排錯經歷

將最大文件數修改爲65536,查看,ulimit -a

linux一次Too many open files的排錯經歷

至此,我簡單的以爲這個問題就解決了,可是過了大概一週,這種情況又出現了....

執行命令:lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more,第一個是句柄數,第二個進程ID,3033是ping節點的進程ID,ping的句柄數爲4132,但是也沒達到最大數的限制,不知道爲什麼不能創建模擬的ping命令,但是可以肯定的是,肯定是項目中某處導致系統的文件數持續增長。

linux一次Too many open files的排錯經歷

然後我開始翻閱我們ping這塊的代碼,所有調用結束後都釋放了啊

linux一次Too many open files的排錯經歷

 

但是我發現每一次ping執行,都會調用兩次模擬ping命令,第一次是去拿ping標識(ping通還是ping不通),第二次是拿額外的一些信息,比如響應時間啥的,這塊問了相關開發人員後確定是沒必要進行兩次操作的,只需要一次就可以搞定。調用代碼如下:

linux一次Too many open files的排錯經歷

上面這兩行代碼都會調用下面的這行代碼

linux一次Too many open files的排錯經歷

修改爲一次後,每一個監控週期,產生的文件數會減少一半,但這肯定不是導致ping節點文件句柄數不斷增大的原因,然後猜想應該是項目中存在很多流沒有關閉導致的,翻看節點日誌也看到了每隔三分鐘(三分鐘是我們的調度頻率),都會打印加載監控模板文件(監控模板配置成xml形式,是監控依據的最基礎的數據),這個不對啊,我們雖然部署的多個服務,但是使用的是memcached的分佈式緩存,按道理應該加載一次的,後面都會從緩存中獲取,然後看了下spring的配置文件,發現監控節點沒有引入memcached.xml的配置文件,所以導致每一次監控都要加載全部的監控模板,而且之前讀取這些xml都沒有進行流關閉,我自己分析了下:我們的監控週期是3分鐘,每三分鐘監控節點都會去加載一遍所有的監控模板,並且流沒有關閉,導致文件句柄數不斷增加,其實並不是ping節點的問題,而是監控節點的問題。

在項目中找那些文件流沒有關閉,還真找到了很多地方,一通修改後,修改後信心滿滿的部署上去,過了9天,這個問題又復現了。

再去仔仔細細的翻看了了一遍ping節點的代碼,發現有這麼一個業務,每次ping的時候,還會有一個獲取系統時間的操作,windows設備會用snmp或者wmi協議去獲取,linux設備用ssh或者telnet去獲取,嗯,這些設備獲取系統時間後所有的鏈接都沒有釋放,這會我大概有70%的把握是這塊導致的,我去測試環境上執行如下命令:lsof -p ping節點的進程ID,這個命令是查看進程裏具體的打開句柄的東東,如下圖,發現滿屏都是創建ssh鏈接打開的文件句柄,至此就可以解釋清楚了,我們測試環境只監控了24臺設備,Linux和Solaris(配置了ssh憑證)加起來大概15臺左右,ping節點每隔6分鐘對這15臺設備進行ping操作,一個監控週期就會打開15個文件句柄,一天就會打開15*10*24 = 3600,我們設置的最大句柄數是65536,大概能支撐的天數也就是65536/3600,大概18天左右,當然系統中不可能只有ping去打開文件句柄數,還有很多服務,也能解釋的通ping節點運行9天后出現這個問題。

lsof -p 3033

linux一次Too many open files的排錯經歷

將ping節點獲取系統時間的鏈接關閉後,重新部署項目,再也沒有出現假宕機的問題,雖然該問題解決了,但還是有如下疑慮:

1.從ping節點打開的文件句柄來看,只有45和51兩臺機器,且均是Solaris,其他的linux設備每次獲取系統時間創建的鏈接也是沒有關閉的,不清楚是不是有的linux設備有保護機制,長時間的ssh鏈接會被關閉掉?

2.進程和進程間是否不存在影響?每個進程系統是否都會分配一定量的文件數來保證某個進程導致文件句柄數增大而不影響其他進程的運行?從測試環境的情況看來,monitor節點每隔三分鐘執行一次調度一直都是正常的,監控節點生成的ssh鏈接在結束後都會釋放掉的。如果兩個進程間的文件數沒有限制,不可能只有ping節點出問題,監控數據也應該中斷纔對

通過這次排查,也能看出平時養成一種良好的編碼習慣有多重要,每一行簡單的代碼,不留心也許會給系統帶來意想不到的後果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章