[linux] Apache 下 TIME_WAIT 太多的問題

  1. 問題:
    apache與負載均衡器的的連接數過多,導致鏈接延遲;

  2. 原因:
    通過查看服務器網絡狀態檢測到服務器有大量的 TIME_WAIT 的狀態;
    檢查命令 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

    	它會顯示例如下面的信息:
    	TIME_WAIT 814
    	CLOSE_WAIT 1
    	FIN_WAIT1 1
    	ESTABLISHED 634
    	SYN_RECV 2
    	LAST_ACK 1
    	#常用的三個狀態是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主動關閉,CLOSE_WAIT 表示被動關閉
    
  3. 解決方法:
    解決思路很簡單,就是讓服務器能夠快速回收和重用那些 TIME_WAIT 的資源。

    1. vi /etc/sysctl.conf
    2. 增加或修改代碼如下:
    #表示開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少量SYN攻擊,默認爲0,表示關閉
    net.ipv4.tcp_syncookies = 1
    #表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉 
    net.ipv4.tcp_tw_reuse = 1
    #表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉  
    net.ipv4.tcp_tw_recycle = 1
    #表示如果套接字由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間 
    net.ipv4.tcp_fin_timeout = 30
    
    1. 然後,執行 /sbin/sysctl -p 讓參數生效。

追溯

tcp 三次和四次握手示意圖
因爲 linux 分配給一個用戶的文件句柄是有限的,而 TIME_WAIT 和 CLOSE_WAIT 兩種狀態如果一直被保持,那麼意味着對應數目的通道就一直被佔着,而且是“佔着茅坑不使勁”,一旦達到句柄數上限,新的請求就無法被處理了,接着就是大量Too Many Open Files異常。。。
1. 什麼原因導致的 TIME_WAIT 的?
從上面的示意圖可以看得出來,TIME_WAIT 是主動關閉連接的一方保持的狀態,對於爬蟲服務器來說他本身就是“客戶端”,在完成一個爬取任務之後,他就 會發起主動關閉連接,從而進入 TIME_WAIT 的狀態,然後在保持這個狀態 2MSL(max segment lifetime)時間之後,徹底關閉回收資源。爲什麼要這麼做?明明就已經主動關閉連接了爲啥還要保持資源一段時間呢?這個是 TCP/IP 的設計者規定 的,主要出於以下兩個方面的考慮: 1. 防止上一次連接中的包,迷路後重新出現,影響新連接(經過2MSL,上一次連接中所有的重複包都會消失) 2. 可靠的關閉 TCP 連接。在主動關閉方發送的最後一個 ack(fin) ,有可能丟失,這時被動方會重新發 fin, 如果這時主動方處於 CLOSED 狀態 ,就會響應 rst 而不是 ack。所以主動方要處於 TIME_WAIT 狀態,而不能是 CLOSED 。另外這麼設計 TIME_WAIT 會定時的回收資源,並不會佔用很大資源的,除非短時間內接受大量請求或者受到攻擊。

[引用] MSL:
MSL 為一個 TCP Segment (某一塊 TCP 網路封包) 從來源送到目的之間可續存的時間 (也就是一個網路封包在網路上傳輸時能存活的時間),由於 RFC 793 TCP 傳輸協定是在 1981 年定義的,當時的網路速度不像現在的網際網路那樣發達,你可以想像你從瀏覽器輸入網址等到第一個 byte 出現要等 4 分鐘嗎?在現在的網路環境下幾乎不可能有這種事情發生,因此我們大可將 TIME_WAIT 狀態的續存時間大幅調低,好讓連線埠 (Ports) 能更快空出來給其他連線使用。
[引用] 網絡資源:
值得一說的是,對於基於 TCP 的 HTTP 協議,關閉 TCP 連接的是Server 端,這樣,Server 端會進入 TIME_WAIT 狀態,可 想而知,對於訪 問量大的 Web Server,會存在大量的TIME_WAIT狀態,假如server一秒鐘接收 1000 個請求,那麼就會積壓 240*1000=240,000 個 TIME_WAIT 的記錄,維護這些狀態給 Server 帶來負擔。當然現代操作系統都會用快速的查找算法來管理這些 TIME_WAIT,所以對於新的 TCP 連接請求,判斷是否hit中一個TIME_WAIT不會太費時間,但是有這麼多狀態要維護總是不好。 HTTP協議1.1版規定 default 行爲是 Keep-Alive,也就是會重用 TCP 連接傳輸多個 request/response,一個主要原因就是發現了這個問題。

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