延遲與帶寬
網站越快,用戶黏性越高;
網站越快,用戶忠誠度越高;
網站越快,用戶轉化率越高。
決定網絡通信的兩個方面:延遲與帶寬。
- 延遲: 分組從信息源發送到目的地所需的時間。
- 帶寬:邏輯或物理通信路徑最大的吞吐量。
目標: 低延遲,高帶寬
延遲
延遲是消息
或分組
從起點到終點經歷的時間。
影響延遲的因素:
- 傳播延遲
消息從發送端到接收端需要的時間,與信號傳播距離和速度有關。 - 傳輸延遲
把消息中的所有比特轉移到鏈路中需要的時間,與消息長度和鏈路速率有關。 - 處理延遲
處理分組首部、檢查位錯誤及確定分組目標所需的時間。 - 排隊延遲
到來的分組排隊等待處理的時間。
以上延遲的時間總和,就是客戶端到服務器的總延遲時間。
CDN
CDN(Content Delivery Network,內容分發網絡)主要就是把內容部署到全球各地,讓用戶從最近的服務器加載內容,大幅降低傳播分組的時間。
使用traceroute
測量延遲
traceroute是一個簡單的網絡診斷工具,可以列出分組經過的路由節點,以及他在IP網絡中的每一跳延遲。在windows系統中可以使用tracert
來測試。
當ICMP協議被禁用的時候,可以採用 lft, paketto, hping, superping.d , NetPerf, IPerf
TCP
TCP協議
傳輸控制協議,即Transmission Control Protocol,縮寫爲TCP,是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,由IETF的RFC 793定義。TCP協議位於IP協議之上,應用層之下的傳輸層。
TCP連接包括了三種狀態: 連接創建、數據傳送和連接終止。操作系統將TCP連接抽象爲套接字的編程接口給程序使用,並且要經歷一系列的狀態改變。
創建通路
所有的TCP連接要通過三次握手,客戶端與服務器在交換應用數據之前,必須就起始分組序列號,以及其他的一些連接相關的細節達成一致。序列號由兩端隨機生成。
- SYN
客戶端選擇一個隨機序列號X,併發送一個SYN分組,其中可能包括其他TCP標識和選項。 - SYN ACK
服務器給X加1,並選擇自己的一個隨機序列號Y,追加自己的標誌和選項,然後返回響應。 - ACK
客戶端給X和Y加1併發送握手期間的最後一個ACK分組。
三次握手完成後,客戶端與服務器就可以通信了。客戶端在發送ACK分組後就可以立即發送數據,服務器則必須等待接收到ACK分組後才能夠發送數據。
三次握手帶來的延遲使得每次創建一個新TCP連接都要付出巨大代價,所以這裏是提升TCP應用性能的關鍵。
TCP Fast Open 是減少新建TCP連接帶來性能損失的一種機制。通過握手開始時的 SYN 包中的 TFO cookie(一個 TCP 選用項)來驗證一個之前連接過的客戶端。如果驗證成功,它可以在三次握手最終的 ACK 包收到之前就開始發送數據,這樣便跳過了一個繞路的行爲,更在傳輸開始時就降低了延遲。
擁塞預防及控制
流量控制
流量控制是一種預防發送端過多向接收端發送數據的機制。爲了實現流量控制,TCP連接的每一方都要通告自己的接收窗口(rwnd),其中包含能夠保存數據的緩衝區空間大小信息。第一次建立連接時,發送端和接收端都會使用窗口默認設置來發送
rwnd
。在瀏覽器網頁時,需要從服務器向瀏覽器下載數據,所以此時客戶端的窗口成爲瓶頸。而在上傳圖片等數據時,服務器的接收窗口成爲了瓶頸。在傳輸過程中,其中一端跟不上數據傳輸,此時它可以向發送端通告一個較小的窗口。假設窗口爲0,則意味着必須有應用層先清空緩衝區,才能夠接受剩餘數據。
每個ACK分組都會攜帶相應的最新的rwnd值,以便於兩端動態調整數據流速,使之適應發送端和接收端的容量和處理能力。
在Linux操作系統中,可以通過以下命令檢查TCP窗口縮放機制。
擁塞控制
發送端、接收端在連接建立之初,無法預測雙方的網絡帶寬,因此需要一個估算機制,然後還需要根據網絡中不斷變化的條件動態改變速度。
1988年,Van Jacobson和Michael J. Karels撰文描述瞭解決這種問題的方法:慢啓動、擁塞預防、快速重發和快速恢復。
- 擁塞預防
TCP調節性能依賴於丟包反饋機制。擁塞預防算法把丟包作爲網絡擁塞的標誌,即路徑中某個連接或者路由器已經擁堵,以至於必須採取刪包策略。因此,需要調整窗口大小,以避免更多的包丟失,保證網絡暢通。重置擁塞窗口後,擁塞預防機制按照自己的算法來增大窗口以及儘量避免丟包。 - 慢啓動
新的TCP鏈接最大數據量取決於RWND和CWND的最小值。慢啓動導致了客戶端與服務器之間經過幾百毫秒才能夠達到接近最大速度的問題,對於大型流式下載服務影響不顯著,但對於大多數的HTTP連接,特別是一些短暫、突發的連接,常常會出現還沒達到最大窗口請求就被終止的情況,很多Web性能受到服務器與客戶端之間往返時間的制約。慢啓動限制了可用的吞吐量,對於小文件傳輸十分不利。
- 擁塞預防
帶寬延遲積
帶寬延遲積(Bandwidth-delay product),數據鏈路的容量與其端到端延遲的乘積。這個結果就是任意時刻處於在途未確認狀態的最大數據量。
發送端和接收端指甲的在途未確認的最大數據量,取決於擁塞窗口和接收窗口的最小值。接收窗口會隨着每次的ACK一起發送,擁塞窗口則由發送端根據擁塞控制和預防算法動態調整。當接收或發送的數據超過了未確認的最大數據量,都必須停下來等待另一方的ACK來確認某些分組才能夠繼續。等待的時間取決於往返時間。
爲了獲得最大的吞吐量,應該讓窗口足夠大,以保證任何一段能在ACK返回前持續發送數據。只有傳輸不間斷,才能夠保證最大的吞吐量。
流量控制窗口和擁塞控制窗口多大才合適呢?假設cwnd和rwnd的最小值爲16KB,往返時間爲100ms:
不論接受或發送的實際帶寬,TCP連接的數據傳輸率都不會超過1.31Mbit/s。
如果往返時間不變,發送端的帶寬爲10Mbit/s,接收端爲100Mbit/s+,且兩端之間沒有網絡擁塞。那麼窗口應該是多大呢?
窗口至少要122.1KB才能夠充分利用10Mbit/s帶寬。但在RFC 1323中,TCP接受窗口最大隻有64KB。所以,儘管窗口大小會自動調節,但也仍舊是TCP性能限制因素。
BDP是往返時間和目標傳輸速度的函數,因此往返時間不僅是高傳輸延遲中的瓶頸,也是LAN中的瓶頸。
隊首阻塞
每個TCP分組都會帶着唯一的序列號被髮出,而所有分組必須按照傳輸順序傳送到接收端。如果中途有一個分組沒能到到接收端,而後續分組必須保存在接收端的TCP緩衝區裏,等待丟失的分組重發併到達接收端。這些情況都發生在TCP層,應用程序對TCP重發和緩衝區排隊的分組一無所知,必須等待分組全部到達才能夠訪問。在此之前,應用程序只能通過套接字讀數據時感覺延遲交付。這種效應成爲TCP的隊首阻塞。
隊首阻塞造成的延遲可以讓程序不必關心分組重排和重組的事情,從而使得我們的代碼更加簡潔。但是,分組到達時間存在無法預知的延遲變化。這個時間變化通常被稱爲抖動。對延遲或者抖動要求高或者無需按序交付數據、能夠自行處理分組丟失的應用程序可以選用UDP。
丟包是TCP達到最佳性能的關鍵,被刪除的包是一種反饋機制,能夠讓接收端和發送端各自調整速度,以免網絡擁堵,同時保持延遲最短(緩衝區爆滿問題)。
針對TCP優化意見
優化目標: 最大吞吐量 最小延遲
TCP是一個自適應、對所有網絡節點一視同仁的、最大限制利用底層的網絡協議。
優化TCP的最佳路徑就是調整它感知當前網絡狀況的方式,根據它之上或之下的抽象層類型和需求來改變他的行爲。
TCP的核心原理和影響是不變的:
- TCP三次握手增加了整整一次的往返時間;
- TCP慢啓動被應用到每一次的新連接;
- TCP流量及擁塞控制會影響所有連接的吞吐量。
- TCP的吞吐量由當前擁塞窗口大小確定。
現代高速網絡中的TCP連接的數據傳輸速度受到接收端和發送端的往返時間的限制。此外,延遲依舊受限於光速,而且已經限定在其最大值的一個很小的常數因子之內。所以,大多數情況下,TCP的瓶頸都是延遲,而非帶寬。
服務器配置調優
- 增大TCP的初始擁塞窗口
加大擁塞窗口能夠讓TCP在第一次往返中就可以傳輸較多的數據,而隨後的速度提升明顯。對於突發性的短暫連接,這是一個很重要的優化的點。 - 慢啓動重啓
在連接空閒時禁用慢啓動可以改善瞬時發送數據的長TCP連接的性能。 - 窗口縮放(RFC 1323)
啓用窗口縮放可以增大最大接收窗口的大小,可以讓高延遲的連接達到更好的吞吐量。 - TCP快速打開
在某些條件下,允許在第一個SYN分組中發送應用程序數據。不過需要發送端和客戶端同時支持TFO(TCP快速打開)
在Linux系統中,可以使用ss
查看當前打開的套接字的各種統計信息。
ss --options --extended --memory --processes --info
可以查看到當前的通信節點以及他們相應的連接設置。
應用程序行爲調優
- 消除不必要的數據傳輸,如不必要的資源下載後者通過壓縮算法將傳送的數據量降到最低;
- 實現數據的短距離傳輸,如採用CDN技術來減少網絡往返的延遲,從而顯著提升TCP的性能;
- 儘可能重用TCP連接,把慢啓動和其他擁塞控制機制的影響降低到最小。
性能檢查清單
- 把服務器內核升級到最新版(Linux 3.2+)
- 確保cwnd大小爲10
- 禁用空閒後的慢啓動
- 確保啓動窗口的縮放
- 減少傳輸的冗餘數據
- 壓縮要傳輸的數據
- 把服務器放到離用戶最近的地方減少往返時間
- 盡最大可能重用已經建立的TCP連接
來源
- 《Web性能權威指南》
- 《圖解TCP/IP》