Nginx

處於 TIME-WAIT 狀態的套接字數量高,伺服器在負載時無響應

  • December 7, 2014

我們的應用程序在高負載時變得無響應,等待時間更長。程序使用率異常低(每個程序約 15% 的 CPU 使用率,我們的應用程序在 8 個程序上執行)。

Nginx 錯誤日誌輸出顯示了其中的一些:

2014/12/04 03:39:31 [crit] 24383#0: *2008067 connect() to 127.0.0.1:4567 failed (99: Cannot assign requested address) while connecting to upstream, client: 108.162.246.229, server: example.org, request: "GET /socket.io/?EIO=3&transport=polling&t=1417682366937-11501 HTTP/1.1", upstream: "http://127.0.0.1:4567/socket.io/?EIO=3&transport=polling&t=1417682366937-11501", host: "example.org", referrer: "https://example.org/unread"

我所看到的

  • 輸出ss -tan | grep TIME-WAIT | wc -l在 30,000 左右,哎喲!

  • 該應用程序將響應,然後:

    • 所有程序都會突然下降到接近 0 的 CPU 使用率
    • 應用程序將變得無響應
    • 約 30 秒後,應用程序將備份,無限重複

需要啟動應用程序,所以創可貼解決方案:

  • echo 28000 65535 > ip_local_port_range(MongoDB 在 27101 上執行,所以我選擇了一個高於此的下限)
  • echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
  • echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle

這將TIME-WAIT狀態中的套接字數量減少到更易於管理的約 400 個。


這是一個片段ss -tan | grep TIME-WAIT

State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port
TIME-WAIT  0      0                 127.0.0.1:29993            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:28522            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:29055            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:31849            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:32744            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:28304            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34858            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:36707            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34756            127.0.0.1:4567  
TIME-WAIT  0      0            104.131.91.122:443          108.162.250.6:55549 
TIME-WAIT  0      0                 127.0.0.1:32629            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34544            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34732            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:33820            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:33609            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34504            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:32463            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:35089            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:30003            127.0.0.1:4567  
TIME-WAIT  0      0            104.131.91.122:443         199.27.128.100:36383 
TIME-WAIT  0      0                 127.0.0.1:33040            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34038            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:28096            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:29541            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:30022            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:31375            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:29827            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:29334            127.0.0.1:4567  

我的問題:

  • 其中很多是從 127.0.0.1 到 127.0.0.1,這正常嗎?對等地址不應該都來自外部IP嗎?

    • 我們的 Node.js 應用程序在 nginx 代理後面,在 CloudFlare DNS 後面,這限制了唯一入站 IP 地址的數量,這可能有關係嗎?
  • 如何正確減少狀態中的套接字數量TIME-WAIT

  • 我很肯定我們每秒沒有 3000 個唯一的套接字連接,我們是否配置錯誤並在應該打開一個時打開了數百個套接字?

提前感謝您提供的任何幫助!

最後,我做了更多的研究並閱讀了這篇非常優秀的關於在 nginx 代理後面擴展 Node 應用程序的指南。

當我將keepalive參數添加到upstreamnginx 中的塊時,主要區別就出現了。事實證明,nginx 工作人員不會記憶體傳入的連接並重新使用它們,從而導致創建數千個新連接(尤其是使用 socket.io 握手等)

@MichaelHampton 關於使用 unix 域套接字的建議也可以很好地解決這個問題。

引用自:https://serverfault.com/questions/649262