移動網絡性能揭秘--網絡協議及性能提升實踐
網絡處理的性能與延遲時間的增加是不成比例的。這是由于大多數網絡協議的內在操作是雙向信息交換。本章的其余部分則側重于理解為什么會產生這些信息交換以及如何減少甚至消除它們交換的頻率。
圖3:網絡協議
傳輸控制協議
傳輸控制協議(TCP)是一種面向連接、基于ip的傳輸協議。TCP影響下的無差錯雙工通信信道對其他協議如HTTP或TLS來說都必不可少。
TCP展示了許多我們需要盡量避免的雙向通訊。這其中一些可以通過采用擴展協議如TCP Fast Open協議來替代;另一些則可以通過調整系統參數來達到最小化,比如初始化擁塞窗口。在本節中,我們將探討這兩種方法同時也提供一些TCP內部組件的背景。
TCP Fast Open
初始化一個TCP連接約定需要3次信息交換,也就是我們所說的3次握手。TCP Fast Open(TFO)是TCP的一個擴展,它消除了通常握手過程中的往返延遲。
TCP在客戶端和服務端的三次握手協商操作參數使得雙方做健壯的雙向通信稱為可能。最開始的SYN信息(同步信息)代表客戶端的連接請求;如果服務端接受這個請求,那么它將返回一個SYN-ACK消息(同步和接受消息);最后,客戶端發送一個ACK消息來應答服務器。這時,一個邏輯連接就已經建立完成,客戶端就可以發送數據了。這其中你如果注意到,3次握手過程中至少引入了一個RTT的延遲那就很好了。
圖4:TCP3次握手
從傳統角度來看,除了對連接進行回收利用外沒有其他方法來避免TCP3次握手造成的延遲。然而,這種想法發生隨著Tcp Fast Open IETF規范的引入發生了變化。
TFO允許客戶端在邏輯連接建立之前就開始發送數據。這實際上否定了3次握手中的往返延遲。這種優化的累積效應是讓人印象深刻。根據谷歌的調查,TFO可以減少頁面40%的加載時間。雖然這個規范只是草案,但是TFO已經被主流瀏覽器(Chrome22以上)和平臺(Linux3.6以上)所支持,并且其他供應商也保證將在不久以后會完全支持它。
TCP Fast Open是對3次握手協議的一個修正,它允許在同步消息(SYN Message)內有少量的數據負載(如HTTP請求)。這個有效負責會傳遞給應用服務器,否則連接握手完成。
早些時候擴展方案像TFO最終因安全問題而失敗。而TFO通過使用安全令牌或者cookie來解決這個問題,也就是說在傳統的TCP連接握手過程中給客戶端分安全令牌(tooken),并且期望將安全令牌包含在TFO優化請求的SYN消息中。
對于TFO的使用,這里有一些小的警告。其中最值得注意的是,在初始化的SYN消息中請求的數據缺乏冪等性保證。雖然TCP保證重復數據包(重復經常發生)會被接受者忽略,但是這個保證并不適用于連接的握手過程。目前在規范草案中正在標準化這個解決方案,但是于此同時TFO仍然可以被安全的應用于冪等性處理。
初始擁塞窗口
初始擁塞窗口是TCP的一個可配置項并且有巨大的潛在能力來加速小的網絡事務。
最近的IETF規范促進通常的初始擁塞窗口的設置增長到3個報文段(如數據包)到10個報文段。這個建議是基于谷歌進行的廣泛研究,這個研究證明了這個參數的設置對性能有平均10%的提升。但如果不介紹TCP的擁塞窗口(cwnd)的話,這種設置的目的和潛在影響就不會被真正領會。
當在一個不可靠的網絡上進行操作時,TCP來保證客戶端和服務端的可靠性。這相當于一個承諾,所有發送出去的數據都會被接收到,或者至少看起來是這樣。其中,包丟失是滿足可靠性要求的最大障礙,這需要偵測、糾錯以及預防。
TCP采用一個肯定應答機制來檢測丟包情況,即每個發送出去的包都應該被它預定的接收方應答,如果沒有應答就意味著這個包在傳輸過程中丟失。在等待確認的過程中,傳輸數據包保存在一個特殊的緩沖區中,也就是所說的擁塞窗口。當這個緩沖區被塞滿時,一個被稱作cwnd耗盡的事件發生,所有傳輸停止,直到接收方應答后騰出有效空間來發送更多的數據包。這些事件在TCP性能中至關重要。
除了網絡帶寬的限制,TCP吞吐量根本上受cwnd耗盡事件發生頻率的限制,而這可能與擁塞窗口的大小有關。當TCP性能達到峰值時需要一個擁塞沖口來調節當前的網絡狀態:擁塞窗口過大將增加網絡堵塞的風險--過度擁堵的網絡狀況會增加大量包丟失;過小則珍貴的網絡帶寬將不能充分被利用。從邏輯上講,對網絡情況了解的越多,肯能越能選擇一個最佳的擁塞窗口大小。實際情況則是,關鍵網絡屬性比如容量和延遲,是很難衡量的并且不斷在變化。而且,如果一個基于互聯網的TCP連接需要穿過許多網絡的這又會是一件更加復雜的事情。
由于缺乏手段來準確確定網絡容量大小,相反TCP通過網絡擁堵情況來推斷擁塞窗口大小。當TCP發現有包丟失時它就會擴大擁塞窗口的大小,提示下行某處有一個網絡無法處理當前的傳輸速率。通過采用這種擁塞避免機制,TCP最終最小化cwnd耗盡事件在某種程度上它消耗完為所有連接所分配的容量。那么現在,最終,我們也達到了目的,解釋清楚了初始擁塞窗口參數的重要性。
網絡擁堵情況只能通過丟包測試來檢測。一個新的或者空閑的連接由于沒有足夠丟包數據來證明創建擁塞窗口的最佳大小;TCP采用了一個比較明智的做法就是以一個可能最小情況導致網絡擁堵的大小一開始作為擁塞窗口大小;這最初意味著需要設置1個分片(大約1480字節),而且有些時候這種做法是推薦的。而稍后的實驗會演示一個高達4的設置也是有效的。在實踐中你也通常發現初始擁塞窗口設置為3報文段(大約4kb)。
初始擁塞窗口不利于小的網絡事務處理。這種效果很容易說明。在表中的3個報文段設置下,在發送3個數據包或者4k的數據后cwnd耗盡時間就會發生。假設數據包是連續發送的,響應的響應不會在任何所允許的往返時間(RTT)之前到達;假如RTT是100ms的話,那么有效傳輸速率只有可憐的400字節/秒。盡管TCP會調節自身的擁塞窗口來充分利用有效容量,但是它在一開始將會很慢。事實上,這種方式被稱為慢啟動。
為了減少慢啟動對較小的下載的性能影響,它需要重新評估初始擁塞窗口的風險回報。谷歌正是這樣做的,而且發現將初始擁塞窗口設置在10個報文段(約14kb)會在最小網絡擁堵情況下達到最大吞吐量。現實世界中也證明了這樣設置總共可以減少頁面10%的加載時間;連接的往返延遲將得到更大的改善。
修改初始擁塞窗口的默認值也并不是那么簡單的。在大多數服務器操作系統下,一個系統級的配置只有有特權的用戶才可設置;這個參數也很少甚至不能被沒有權限的應用在客戶端配置。需要注意的是一個更大的初始擁塞窗口在服務器端可以加速下載,而在客戶端則可以加速上傳。如果無法在客戶端改變這個設置就意味著應該特別努力去減少請求負載的大小。
超文本傳輸協議
本節將討論在超文本傳輸協議(HTTP)性能方面來減少高的往返延遲的技術。
KeepAlive
KeepAlive是一個HTTP約定來允許同步連續的HTTP請求來使用同一個TCP連接。至少一個單組往返請求所需要的TCP的3次握手可以避免,每次請求可以節省幾十或者幾百毫秒。更深層次的,keepalive還有一個額外的但是未被提及的好處就是它在各個請求之間保留了當前TCP的擁塞窗口大小,這將導致更少的cwnd耗盡事件發生。
圖5:HTTP pipelining
實際上,管道使網絡延遲分布于網絡往返的各個HTTP事務中。例如,5個管線式的HTTP請求通過一個100毫秒的RTT連接時將產生一個平均20毫秒的往返延遲;在同樣條件下,10個管線式請求時這個平均延遲將減少到10毫秒。
但是,HTTP pipeling有明顯的缺點阻止了它被廣泛使用,即歷史上參差不齊的HTTP代理支持和拒絕服務攻擊的影響。
安全傳輸層協議
傳輸層安全性(Transport Layer Security,TLS)是一個面向會話的網絡協議允許在公共網絡安全地交換敏感信息。雖然TLS在安全通信方面卓有成效,但是在高延遲網絡下它的性能會下降。
TLS采用一個復雜的握手協議包括兩次交換客戶端-服務端信息。一個TLS安全的HTTP傳輸明顯比較慢也正是這個原因。通常,發現一個TLS慢實際上是在抱怨它的握手協議中多重往返所產生的延遲。
圖6:DNS查詢
通常,主平臺提供了緩存實現來避免頻繁的DNS查詢。DNS緩存的語義非常簡單:每個DNS響應包含一個存活時間(time-to-live,TTL)屬性來聲明結果會被緩存多長時間。TTL的范圍通常在幾秒鐘到幾天之間,但通常為幾分鐘。非常低的TTL值,通常在一分鐘以下,被用在影響負載分配或者減少服務器替換或ISP故障轉移的時間。
刷新失敗
高可用系統通常依賴于他們IP機房的冗余基礎設施主機。TTL值較小的DNS條目可以減少客戶指向失敗主機的時間,但是同時會導致大量額外的DNS查詢。所以說,TTL的值應該是減少停機時間和客戶端性能最大化的一個折中。
通常降低客戶端性能是沒有意義的,但當服務器故障時是個例外。有一個簡單的方法來解決這個問題,也就是說不是嚴格的遵守TTL,而是僅僅當更高層協議如TCP或HTTP檢測到不可恢復錯誤時才刷新DNS緩存。這種技術在大多數場景下模擬TTL保持DNS緩存一致的行為,然而這幾乎消除了任何基于DNS高可用性解決方案中的性能損失。
但是需要注意的是這個技術方案和其他基于DNS的分布式負載方案不兼容。
異步刷新
異步刷新是一個DNS緩存方法,它遵守已經設置TTL規則但是在很大程度上消除了頻繁查詢DNS的延遲。在這項技術中,需要一個異步DNS客戶端庫如c-ares來實現。
這個方法很簡單,一個過期的請求仍然返回的是老的結果,但是后臺有一個非阻塞的DNS查詢來定時刷新DNS緩存。這種方案如果采用阻塞式(如同步)回調來查詢每條老的DNS數據,那么這個方案幾乎不受DNS查詢延遲的影響,但是仍然和很多基于DNS的故障轉移方案以及分布式負載方案兼容。
總結
要減少移動網絡高延遲的影響就需要通過減少使移動網絡延遲急劇增加的網絡往返次數來實現。而采用軟件優化專注于最大限度地減少或消除往返協議的消息是克服這項艱巨的性能問題的關鍵。