首頁  >  文章  >  運維  >  Ulimit的故障怎麼解決

Ulimit的故障怎麼解決

WBOY
WBOY轉載
2023-05-16 15:39:091542瀏覽

最近遇到一個非常有趣的問題。其中有一組HAProxy,經常出現問題。登入上伺服器,cpu、記憶體、網路、io一頓猛查。最後發現有超過6萬個連線處於機器的TIME_WAIT狀態。

Ulimit的故障怎麼解決

TIME_WAIT狀態,通常會出現在HAProxy、Nginx這種代理機器上,主要是因為頻繁的主動關閉所造成的。透過修改reuse和回收參數,可以比較快速的解決問題。

網路狀態的統計數量,可以使用下面的命令進行統計。

netstat -ant|awk '/^tcp/ {++S[$NF]} END {for(a in S) print (a,S[a])}' ESTABLISHED 70 FIN_WAIT2 30 CLOSING 33 TIME_WAIT 65520

Ulimit的故障怎麼解決

這本來沒什麼神奇的,但65535這個數字,實在是太過於敏感。應該是觸發了某種上限。

使我們更加感到疑惑的是:為什麼TIME_WAIT狀態的連接,僅僅達到了65535,服務就不可用了?

到處號稱的單機百萬連接,是在吹牛皮麼?怎麼這麼經不起折騰?

65535,表示等於2的16次方減一,是一個神奇的數字。把這個小數字暫且擱置,我們先來了解Linux支援多大的連線容量。

1. Linux能夠支援多少連線?

答案是無數個。可是埠只有65535個啊。

為什麼連接埠只有65535個?

TCP和UDP協定在開頭分別用16位元儲存來源埠號和目標埠號,這是基於歷史原因。很遺憾的是,這個值是short類型的,大小也是2^16-1。

因為歷史原因造成的不可改變的標準,就是那麼根深蒂固。

那Linux到底能支援多少個連結呢?答案是無數個。

拿nginx來說,我們把它監聽在80埠上。這時候A機器去連接Nginx,可以發起多達6w多條長連線。如果B機器去連接Nginx,同樣也可以發起6w多個連線。這是由於確定一條連接,是由src和dst來共同決定的。

認為Linux只能接受65535條連結的想法,只能說是犯了非常淺顯的想當然主義。

65535個端口,作為壓測機可能對你來說太小了一些。但對於伺服器來說,已經綽綽有餘了。

2. 如何支援百萬連接?

從上面可以看到,連接數,是沒有限制的。但Linux還有一層防護,那就是檔案句柄數。透過lsof指令查看到的那些東西,就是所謂的檔案句柄。

先來看幾個指令的展示。

ulmit,展示了每個行程所能佔用的檔案句柄數量。

ulimit -n 65535

file-max,展示了作業系統能夠佔用的檔案句柄數量總和,針對的是所有的進程。

cat /proc/sys/fs/file-max 766722

file-nr,展示了目前已經使用的句柄數量和總的句柄數量。可以拿來做監控。

cat /proc/sys/fs/file-nr 1824  0 766722

為了支援百萬連接,需要釋放作業系統層級的句柄和進程層級的句柄。也就是說,ulimit和file-max的顯示,都要大於百萬才成。

3. 如何設定?

雖然常用的方案是ulimit來設定進程句柄數,但我非常不建議使用。只有在同一shell中啟動的進程,才會受到ulimit設定的影響,原因沒有其他的。如果你打開另一個shell或重新啟動機器,那麼ulimit的變更都會消失。就是下面這種方式:

ulimit -n 1000000

正確的方式,就是修改/etc/security/limits.conf檔。比如下面的內容。

root soft nofile 1000000 root hard nofile 1000000 * soft nofile 1000000 * hard nofile 1000000

可以看到,我們可以針對於特定的用戶,修改其句柄數量。這在安裝es等應用程式時,常碰到。

es  -  nofile  65535

使用這種方法,仍需要開啟一個新的shell才能進行操作。這個指令無論是在修改後的shell還是在修改之前的shell中,都不會生效。 xjjdog曾經遇到多個案例,儘管限制已經放開,但仍發生了問題。

查看進程的記憶體映射檔案可以確定這些變更是否已經生效。例如,在指令「cat /proc/180323/limits」中,將會展示詳細資訊。

這個數值,也不是想要設多大就多大的。它的大小上限,是由nr_open決定的。要增加大小,需要在/ect/sysct.conf中更改fs.nr_open的值。

cat /proc/sys/fs/nr_open 1048576

如果想要修改file-max參數,建議在/etc/sysctl.conf檔案中加入以下內容。足足有6百多萬!

fs.file-max = 6553560

當檔案數量超出的時候,就會報kernel: VFS: file-max limit 65535 reached的錯誤。

總結一下。

Ulimit的故障怎麼解決

Linux即使放開一個端口,能夠接受的連接也是海量的。這些連線的上限,受到單一進程檔案句柄數量和作業系統檔案句柄數量的限制,也就是ulimit和file-max。

為了能夠將參數修改持久化,我們傾向於將改動寫入到檔案中。行程的檔案句柄限制,可以放在/etc/security/limits.conf中,它的上限受到fs.nr_open的限制;作業系統的檔案句柄限制,可以放到/etc/sysctl.conf檔案中。最終,一定要檢查/proc/$id/limits文件,確認修改是否生效於進程。

以上是Ulimit的故障怎麼解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除