TCP 性能優化淺析

前言

TCP 作為一種最常用的傳輸層協議,它的作用是在不可靠的傳輸信道上,提供可靠地數據傳輸。在各層網絡協議中,只要有一層協議是可靠的,那么整個網絡傳輸就是安全可靠的。現實中,幾乎所有的 HTTP 流量都是經過 TCP 傳輸。因此,我們要進行 web 性能優化,TCP 是其中的關鍵一環。要針對 TCP 進行性能優化,就得理解其工作原理。

三次握手

眾所周知,建立一次 TCP 連接需要進行三次握手。關于三次握手,一圖勝千言。

圖1

三次握手給 TCP 帶來了很大的延遲,不過這個握手過程是必不可少的。因為如果沒有三次握手,有可能會出現一些已經失效的請求包突然又傳到服務端,服務端認為這是客戶端發起的一次新的連接,于是發出確認包,表示同意建立連接。而客戶端并不會有響應,導致服務器出現空等,白白浪費服務器資源。

既然三次握手的過程不可避免,那么我們只能通過重用 TCP 連接,減少三次握手的次數。HTTP 1.1 引入了長連接,通過在請求頭中加入 Connection: keep-alive, 來告訴請求響應完畢后,不要關閉連接。不過 HTTP 長連接也是有限制的,服務器通常會設置 keep-alive 超時時間和最大請求數,如果請求超時或者超過最大請求數,服務器會主動關閉連接。

除此之外,TFO(TCP Fast Open,TCP 快速打開)這種機制也被設計用于優化三次握手過程。它通過握手開始時的 SYN 包中的 TFO cookie(一個 TCP 選項)來驗證一個之前連接過的客戶端。如果驗證成功,它可以在三次握手最終的 ACK 包收到之前就開始發送數據。


圖2

Linux 3.7 及以后的內核在客戶端及服務器中支持 TFO, 對于移動端,Android 和 iOS 9+ 都支持 TFO,不過 iOS 并未默認啟用。

PS: 推薦大家裝一個 wireshark,可以非常直觀的觀察到三次握手的過程。


屏幕快照 2018-02-02 下午11.30.33.png

流量控制

流量控制是一種預防發送端向接受端發送過多數據的機制。它的主要目的是為了防止接收端服務過載,從而出現丟包。為了實現流量控制,TCP 連接的每一方都要聲明自己的通告窗口(rwnd),表示自己的緩沖區最多能接收多少數據。如果其中一端跟不上對方的發送速度,就通知對方一個較小的窗口。如果窗口大小為 0,應用層必須先清空緩沖區,才能繼續接收數據。這就是所謂的滑動窗口協議。

大家可能經常遇到這種情況,自己明明是百兆寬帶,實際下載速度每秒卻只有幾M。這種情況有可能就是通告窗口(rwnd)設置的不合理造成的。最初的 TCP 規范分配給接收窗口大小的字段是 16 位,也就是 64KB(2 的 16 次方)。實際上,rwnd 的大小應該由 BDP(帶寬延遲積) 而定。BDP(bit) = bandwidth(b/s) * round-trip time(s)。比如一個 100Mbps 的寬帶,RTT 是100 ms,那么 BDP = (100 / 8) * 0.1 = 1.25M。此時,要想提高網絡傳輸吞吐量,rwnd 應該為 1.25 M。

為了解決這個問題,TCP 窗口縮放(TCP Window Scaling)出現了,它將窗口大小由 16 位擴展到 32 位。Linux 上自帶了緩沖大小調優機制,如下命令,可以查看 Linux 初始窗口大小:

sysctl net.ipv4.tcp_rmem
// 輸出 net.ipv4.tcp_rmem = 4096  87380    6291456
// 從左到右一次為最小值、默認值、最大值

慢啟動

流量控制機制可以防止發送端和接收端之間的服務過載,但無法防止任何一端向某個網絡的發送數據過載,因此還需要一個估算機制,根據網絡環境動態改變數據傳輸速度,這就是慢啟動出現的原因。

慢啟動為發送方的 TCP 增加了一個窗口:擁塞窗口(congestion window),記為 cwnd。當與另一個網絡的主機建立 TCP 連接時,cwnd 初始化為 1 個 TCP 段。每收到一個 ACK,cwnd 就增加一個 TCP 段。發送端取 cwnd 和 rwnd 中的最小值作為發送上限。可以這樣理解,擁塞窗口是發送端使用的流量控制,而通告窗口是接收端使用的流量控制。

一開始 cwnd 為 1,發送方只發送一個 mss(最大報文段長度) 大小的數據包,收到 ack 后,cwnd 加 1,cwnd=2。

此時 cwnd 2,則發送方要發送兩個 mss 大小的數據包,發送方會收到兩個 ack,則 cwnd 會進行兩次加一的操作,則也就是 cwnd+2,則
cwnd=4,也就是 cwnd = cwnd*2。

以此類推,每次 rtt 后,cwnd 都會變成上次發送前的 2 倍。因此,cwnd 的大小是呈指數級在遞增。


圖3

隨著 cwnd 的增加,會發送網絡過載,此時會出現丟包。一旦發現有這種問題,cwnd 會成倍減少。


圖4

為了減少往返次數,初始擁塞窗口的大小設定就尤為重要。默認情況下(RFC 2581),初始 cwnd 為 4 個 MSS。Google 建議將初始窗口改為 10 個 MSS。根據 Google 的研究,90% 的 HTTP 請求數據都在 16KB 以內,約為 10 個 MSS。

總結

本文介紹了 TCP 的部分工作原理,包括三次握手、流量控制、慢啟動,并闡述了 TCP 快速打開、窗口縮放、增加初始擁塞窗口大小等優化手段。內容有點偏理論,還是需要多多實踐,才能合理掌握各種優化手段。


參考文獻:

  1. 《Web性能權威指南》
  2. 《TCP/IP詳解,卷1:協議》
  3. 淺談TCP優化
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.這篇文章不是本人原創的,只是個人為了對這部分知識做一個整理和系統的輸出而編輯成的,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,129評論 6 174
  • TCP/IP協議 作者:xinyuans 本文為參考TCP/IP詳解卷一,某些知識點加上了作者自己的理解,如有錯誤...
    xinyuans閱讀 832評論 0 1
  • 個人認為,Goodboy1881先生的TCP /IP 協議詳解學習博客系列博客是一部非常精彩的學習筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,090評論 0 8
  • 24.1 引言 TCP已經在從1200 b/s的撥號SLIP鏈路到以太數據鏈路上運行了許多年。在80年代和90年代...
    張芳濤閱讀 1,516評論 0 3
  • 18.1 引言 TCP是一個面向連接的協議。無論哪一方向另一方發送數據之前,都必須先在雙方之間建立一條連接。本章將...
    張芳濤閱讀 3,411評論 0 13