1. 程式人生 > >too many open files linux服務器 golang java

too many open files linux服務器 golang java

add -m 使用 san awk margin 1.0 占用 sim

1. 現象

服務的cpu跑滿(golang實現), 並大量報too many open files錯誤.服務使用systemd來運行,部署在阿裏ecs.

2.分析

從日誌來看,cpu的上升主要為到達文件數限制引起的,但之前已經更改過系統的文件數及所有用戶的文件數,按道理是不應該出現這個問題的,後來查閱資料發現,文件數可以從三個維度限制分別為操作系統限制,用戶態限制,以及進程限制,對於這三個維度選取最小值生效.於是對系統進行分析.

首先查看當前打開文件數, 進程占用的文件數並不多.

lsof -n|awk ‘{print $2}‘|sort|uniq -c|sort -nr|more



然後獲取系統級文件數限制

輸入命令

cat /etc/sysctl.conf

得到

fs.file-max = 1000000

查詢用戶級文件數限制

cat /etc/security/limits.conf

得到

* soft nofile 655350

* hard nofile 655350

單獨獲取程序文件數限制(9928為進程id)

cat /proc/9928/limits

得到

Max open files 1024 4096 files

如上可以發現, 雖然系統及用戶的文件數調大了,但是程序的仍然是一個很低的值, 這裏進程的文件數一般情況下是默認繼承用戶級的值的,而這裏卻沒有繼承

,一開始懷疑是systemd啟動的問題,但是手寫了另外一個測試服務,發現該服務又繼承了用戶文件數.

百思不得其解的情況下在systemd的啟動腳本裏加了文件數的初始化值.

如下:

[Service]

Type=simple

LimitNOFILE=40960

LimitNPROC=40960

單獨獲取程序(9928為進程id)

cat /proc/9928/limits

得到

Max open files 40960 40960 files



發現文件數被設置成了啟動時的初始化值.至於為什麽沒有繼承用戶級的值,懷疑是程序裏做了參數設置

,這裏如果有人知道golang裏具體情況的話,還望不吝賜教.

3. 總結

歸結來說出現文件描述符的錯誤的排查步驟如下:

首先,判斷配置參數是否正確,這裏涉及到對上面提到的三個維度的檢查,特別時進程維度的,如果只是ulimit -n 一下就完事了,那估計舊要像我一樣進坑了.

如果參數都正確,那麽查看一下當前系統被使用了多少文件數,如果使用的確實多,那要看一下使用在什麽地方,這裏一般有兩種情況,大量連接未關閉,或者大量讀文件的句柄未關閉.具體原因相信到這裏就可以排查出來了.

too many open files linux服務器 golang java