HTTP事務的延遲—TCP的影響
最近看完了大部頭著作《HTTP權威指南》,對于此類指南類、手冊類圖書,往往讓我們聯(lián)想到的就是枯燥無味的使用講解、技術指標講解......使人頭大。但是這本書卻讓我覺得讀起來很“清新”,一方面作者用了淺顯易懂的語言和大量的圖示讓我們很容易知所以然,另一方面應該是我一直以來對網(wǎng)絡編程的興趣和此書的內(nèi)容有很大的契合點,今天要講的內(nèi)容也是與自己的興趣有關的HTTP協(xié)議中有關TCP的部分,是從書中第四章——”連接管理“的部分內(nèi)容總結而來。
HTTP請求過程中會有哪些網(wǎng)絡時延?

域名解析:域名解析是進行網(wǎng)絡訪問的第一步,把域名識別為TCP認識的IP地址。這步往往會因為域名解析服務的質量造成諸多問題,我在實際的工程實踐中遇到的最常見的問題就是選擇的域名服務商質量不好或者客戶端本身設置的域名解析服務地址錯誤導致域名解析慢或者失敗。不過現(xiàn)在對于大多數(shù)的HTTP客戶端都有一個小的DNS緩存,用來保存近期所訪問站點的IP地址,可以有效的緩解此問題。
接下來,客戶端會向服務器發(fā)送一條TCP連接請求,并等待服務器回送一條響應。每條新的TCP連接都有連接建立時延(通常最多只有一兩秒鐘),對于單線程瀏覽器而言,如果有數(shù)百個并發(fā)的HTTP事務的話,可想而知時間疊加值也會很大。
一旦連接建立起來,客戶端和服務器端就會通過這個建立的TCP管道來進行請求的收發(fā)了,這些TCP的網(wǎng)絡時延的大小取決于硬件速度、網(wǎng)絡和服務器的負載,請求和響應報文的尺寸,以及客戶端和服務器之間的距離。請參見我的文章《構建高性能服務的考量》。
TCP相關時延
TCP連接建立握手

建立一條新的TCP連接時,TCP兩端之間會交換一系列的IP分組,如果連接只是用來傳送少量的數(shù)據(jù),相比而這種建立連接的過程會大大影響HTTP的性能。
通常HTTP的事務都不會交換太多數(shù)據(jù),SYN/SYN+ACK兩次握手會產(chǎn)生一個可測量的時延,但第三次握手——TCP連接ACK分組通常都足夠大,可以承載整個HTTP的請求報文(現(xiàn)代的TCP協(xié)議棧都允許客戶端在這個確認分組中發(fā)送數(shù)據(jù)),而且很多HTTP服務器響應報文都可以放到一個IP分組中去。
可以看出,小的HTTP事務可能會在TCP建立連接上花費50%的時間之多。所以我們現(xiàn)實中常常會有重用HTTP連接的需求。
TCP的延遲確認機制
我們都知道因特網(wǎng)自身是無法保證可靠的分組傳輸?shù)模訲CP實現(xiàn)了自己的確認機制來確保數(shù)據(jù)的傳輸成功。在這種確認機制中使用的就是確認報文,由于確認報文很小,于是TCP將要返回的確認信息與輸出的數(shù)據(jù)分組結合在一起發(fā)送可以更有效的利用網(wǎng)絡。為了增加確認報文找到同向傳輸數(shù)據(jù)分組的可能性,很多TCP協(xié)議棧都實現(xiàn)了一種“延遲確認”算法——在一個特定的窗口時間(通常是100-200毫秒)內(nèi)將輸出確認放在緩沖區(qū)中,以尋找能夠捎帶它的輸出數(shù)據(jù)分組,否則超出這個時段就將確認數(shù)據(jù)單獨發(fā)送。
但是HTTP具有雙峰特征的請求——應答行為降低了捎帶信息的可能。當希望有相反方向回傳分組的時候,偏偏沒有那么多。通常,延遲確認算法會引入相當大的時延,所以我們應該依據(jù)相應的操作系統(tǒng)的不同調整或者禁用延遲確認算法。
注:在對TCP協(xié)議棧的任何參數(shù)進行修改之前,一定要對自己做什么有清醒的認識。TCP中引入這些算法的目的是防止設計欠佳的應用程序對網(wǎng)絡造成破壞。所以修改這些配置后都應該保證應用程序不會引發(fā)這些算法所要避免的問題。
TCP慢啟動(擁塞控制)
為了更好的保護網(wǎng)絡,TCP慢啟動限制了一個TCP端點在任意時刻可以傳輸?shù)姆纸M數(shù)。TCP數(shù)據(jù)傳輸起初會限制傳輸速度(傳輸分組數(shù)),如果數(shù)據(jù)成功傳輸,會隨著時間的推移提高傳輸速度(傳輸分組數(shù))。如果某個HTTP事務有大量數(shù)據(jù)要發(fā)送,是不能一次將所有分組都發(fā)送出去的。必須依賴慢啟動逐漸的打開擁塞窗口。
由于存在這種擁塞控制特性,所以新連接的傳輸速度會比已經(jīng)交換過一定量數(shù)據(jù)的連接慢一些。這樣又需要我們從重用HTTP連接(持久連接)的角度去考慮提高傳輸性能。
Nagle算法與TCP_NODELAY
如果TCP連接總是發(fā)送大量包含少量數(shù)據(jù)的分組,網(wǎng)絡的性能就會嚴重下降。Nagle算法就是試圖在發(fā)送一個分組之前,將大量TCP數(shù)據(jù)綁定在一起發(fā)送(鼓勵發(fā)送全尺寸的段,比如以太網(wǎng)上的段大小是1500字節(jié),否則就進行緩存,要么當所有其他分組都被確認之后,Nagle算法才允許發(fā)送非全尺寸的分組),以提高網(wǎng)絡效率。
Nagle算法會引發(fā)幾種HTTP的性能問題。比如小的HTTP報文可能無法填滿一個分組,所以要緩存等待起來,要么就等待確認分組的抵達(確認分組的時延大概在100-200毫秒)。
所以HTTP應用程序常常會在自己的協(xié)議棧中設置參數(shù)TCP_NODELAY,禁用Nagle算法來提高性能。
TIME_WAIT累積與端口耗盡
關于TIME_WAIT狀態(tài)的解釋請看我的這篇博文《網(wǎng)絡編程釋疑之:TCP的TIME_WAIT狀態(tài)在服務器開發(fā)中的影響?》,之前TIME_WAIT時間的設置為2分種之多是因為早期路由器的處理速度還比較慢,但是現(xiàn)在高速路由器的使用已經(jīng)大大弱化了這個問題,所以對于web服務器來說可以通過操作系統(tǒng)設置來減小TIME_WAIT狀態(tài)的持續(xù)時間,否則如果服務器存在大量的TIME_WAIT狀態(tài)會大大影響服務器的性能。至于端口耗盡的情況則是針對少量客戶端主機對web服務器進行基準測試時可能出現(xiàn)的問題,與TCP連接四元組有關。



























