TCP優化學習筆記(二):參數調優

目錄

TCP 的三次握手

狀態解釋

TCP 四次揮手

狀態解釋

參數調優

TCP連接優化

time-wait調優:減少time-wait

參數說明:

長連接

Nginx TCP配置優化

tcp_nodelay 

tcp_nopush

sendfile

 

TCP 的三次握手

狀態解釋

  • CLOSED: 表示初始狀態。
  • LISTEN:表示服務器端的某個SOCKET處於監聽狀態,可以接受連接
  • SYN_RCVD:表示接受到了SYN報文,在正常情況下,這個狀態是服務器端的SOCKET在建立TCP連接時的三次握手會話過程中的一箇中間狀態,很短暫,基本上用netstat你是很難看到這種狀態的,除非你特意寫了一個客戶端測試程序,故意將三次TCP握手過程中最後一個ACK報文不予發送。因此這種狀態時,當收到客戶端的ACK報文後,它會進入到ESTABLISHED狀態。
  • SYN_SENT:這個狀態與SYN_RCVD遙想呼應,當客戶端SOCKET執行CONNECT連接時,它首先發送SYN報文,因此也隨即它會進入到了SYN_SENT狀態,並等待服務端的發送三次握手中的第2個報文。SYN_SENT狀態表示客戶端已發送SYN報文。
  • ESTABLISHED:表示連接已經建立

完成三次握手,客戶端與服務器開始傳送數據,在上述過程中,還有一些重要的概念:

  • 未連接隊列:在三次握手協議中,服務器維護一個未連接隊列,該隊列爲每個客戶端的SYN包(syn=j)開設一個條目,該條目表明服務器已收到 SYN包,並向客戶發出確認,正在等待客戶的確認包。這些條目所標識的連接在服務器處於Syn_RECV狀態,當服務器收到客戶的確認包時,刪除該條目, 服務器進入ESTABLISHED狀態。
  • Backlog參數:表示未連接隊列的最大容納數目。
  • SYN-ACK 重傳次數:服務器發送完SYN-ACK包,如果未收到客戶確認包,服務器進行首次重傳,等待一段時間仍未收到客戶確認包,進行第二次重傳,如果重傳次數超 過系統規定的最大重傳次數,系統將該連接信息從半連接隊列中刪除。注意,每次重傳等待的時間不一定相同。
  • 半連接存活時間:是指半連接隊列的條目存活的最長時間,也即服務從收到SYN包到確認這個報文無效的最長時間,該時間值是所有重傳請求包的最長等待時間總和。有時我們也稱半連接存活時間爲Timeout時間、SYN_RECV存活時間。

TCP 四次揮手

狀態解釋

  • FIN_WAIT_1:FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。
  • FIN_WAIT_2:FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你,稍後再關閉連接。
  • TIME_WAIT:表示收到了對方的FIN報文,併發送出了ACK報文,就等2MSL後即可回到CLOSED可用狀態了。如果FIN_WAIT_1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。
  • CLOSING:正常情況下,發送FIN報文後,按理來說是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING狀態表示你發送FIN報文後,並沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什麼情況下會出現此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方幾乎在同時close一個SOCKET的話,那麼就出現了雙方同時發送FIN報文的情況,也即會出現CLOSING狀態,表示雙方都正在關閉SOCKET連接。
  • CLOSE_WAIT:表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後發送FIN報文給自己,你係統毫無疑問地會迴應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那麼你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連接。
  • LAST_ACK:被動關閉一方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也即可以進入到CLOSED可用狀態了。
     

參數調優

開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少量SYN攻擊,默認爲0,表示關閉;
net.ipv4.tcp_syncookies = 1

系統默認的TIMEOUT時間。
net.ipv4.tcp_fin_timeout = 5

當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時,改爲20分鐘(20*60s)
net.ipv4.tcp_keepalive_time = 1200

表示用於向外連接的端口範圍。缺省情況下很小:32768到61000,改爲10000到65000
net.ipv4.ip_local_port_range = 10000 65000

SYN隊列的長度,默認爲1024,加大隊列長度爲8192,可以容納更多等待連接的網絡連接數
net.ipv4.tcp_max_syn_backlog = 8192系統同時保持TIME_WAIT的最大數量,如果超過這個數字,TIME_WAIT將立刻被清除並打印警告信息。默認爲180000,改爲5000
net.ipv4.tcp_max_tw_buckets = 5000

TCP連接優化

time-wait調優:減少time-wait

time-wait會發生在發起斷開請求的一端。一般這樣的服務器會是我們的代理節點或web服務器,因爲他們需要作爲客戶端向後端節點發起訪問。而系統進入time-wait後會等待60s的時間,在這段時間內,系統不會釋放socket,仍然會佔據端口,這樣對於高併發的業務非常不利。

對此我們就需要對處於time-wait狀態的socket進行快速回收。

參數說明:

開啓重用:net.ipv4.tcp_tw_reuse

允許將TIME-WAIT sockets重新用於新的TCP連接,默認關閉;當啓用tcp_tw_reuse時,在TIME_WAIT狀態下的套接字可以在它們過期之前使用,並且內核將嘗試確保沒有關於TCP序列號的衝突。如果啓用tcp_timestamps(a.k.a. PAWS,防止包裝序列號),它將確保這些衝突不會發生。但是,需要在服務器兩端都啓用TCP時間戳。

開啓TCP連接中TIME-WAIT sockets的快速回收:net.ipv4.tcp_tw_recycle

啓用tcp_tw_recycle時,內核變得更加積極回收time wait,並且將對遠程主機使用的時間戳作出假設判斷。它將跟蹤具有TIME_WAIT狀態的連接的每個遠程主機使用的最後時間戳),並允許在時間戳正確增加的情況下重新使用套接字。但是,如果主機使用的時間戳發生變化(即時間回退),則SYN數據包將被靜默地丟棄,並且連接不會建立(您將看到類似於“連接超時”的錯誤)。

開啓時間戳:tcp_timestamps 

Timestamps 用在其它一些東西中﹐可以防範那些僞造的 sequence 號碼。一條1G的寬帶線路或許會重遇到帶 out-of-line數值的舊sequence 號碼(假如它是由於上次產生的)。Timestamp 會讓它知道這是個 ‘舊封包’。(該文件表示是否啓用以一種比超時重發更精確的方法(RFC 1323)來啓用對 RTT 的計算;爲了實現更好的性能應該啓用這個選項。)
 

提示:如果關閉tcp_timestamp, tcp_tw_recycle則不能開啓。

長連接

長連接會加快訪問速度,減少time-wait,但長連接會長時間佔用socket。

Nginx TCP配置優化

在nginx的配置文件中有相關TCP連接的優化,分別是sendfile,tcp_nopush和tcp_nodelay。

sendfile on|off;  # 是否啓用文件快速傳輸
tcp_nopush on|off; # 是否緩存數據後集中發送,適用於大文件傳輸  
tcp_nodelay on|off; # 是否立即發送數據包,使用於即時性傳輸

tcp_nodelay 

TCP_NODELAY選項允許繞過Naggle算法,然後儘快發送數據。當下載完整的網頁時,TCP_NODELAY可以在每個HTTP請求上節省更多的時間,這樣可以有更佳的用戶體驗。 在在線遊戲或高頻交易時的場景,即使以相對網絡飽和的代價,擺脫延遲至關重要。

Nginx在HTTP keepalive連接上使用TCP_NODELAY。 keepalive連接是在發送數據後保持打開幾次的套接字。 keepalive允許發送更多的數據,而不會啓動新的連接,並重復每次HTTP請求的TCP 3次握手方式。 這樣可以節省重新創建socket的時間,因爲每次數據傳輸後都不會切換到FIN_WAIT。 Keep-alive是HTTP 1.0和HTTP 1.1默認行爲的一個選項。

tcp_nopush

在Nginx上,配置選項tcp_nopush與tcp_nodelay相反。 不是優化延遲,但是它可以優化一次發送的數據量,和Nagle算法非常接近。

TCP_NOPUSH會調用tcp_cork函數,tcp_cork函數會阻塞數據,直到數據包到達MSS的長度,MSS長度等於MTU減去IP數據包的40(IPV4)或60(IPV6)字節,和Nagle算法不同的是,TCP_CORK軟件將等待的時間上限設置爲200毫秒,而不是等待上個數據包的ACK。 如果達到上限,則排隊的數據將自動傳輸。

TCP(7)聯機幫助頁解釋說TCP_NODELAY和TCP_CORK是互斥的,但是Linux 2.5.9以後的版本中兩者可以兼容。

在Nginx的配置中,sendfile和tcp_nopush必須配合使用。

sendfile

Nginx之所以在靜態文件的傳輸上有很高的性能,主要原因就在於這裏所說的三個參數。

 Nginx的sendfile選項可以使用sendfile(2)來處理與發送文件相關的所有內容。

sendfile(2)允許在文件描述符中直接在內核空間中傳輸數據,節省大量資源:

  • sendfile是一個系統調用,這意味着在內核空間內執行,因此沒有昂貴的上下文切換。

  • 替換了read和write兩者的組合。

  • 允許零拷貝,這意味着通過DMA從塊設備內存直接寫入內核緩衝區。

如果nginx是在爲本地存儲的靜態文件提供服務,則sendfile對於加快Web服務器響應至關重要。 但是,如果使用Nginx作爲反向代理來從應用程序服務器提供頁面,則可以禁用它。 除非在tmpfs上提供微型緩存。 


參考:

TCP參數調優詳解https://blog.csdn.net/erlib/article/details/50236919

TCP連接優化https://blog.51cto.com/tryingstuff/1961464

發佈了67 篇原創文章 · 獲贊 10 · 訪問量 6762
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章