http连接管理
1.TCP連接
幾乎所有的HTTP通信都有由TCP/IP承載的,TCP/IP是全球計算機及網絡設備都在使用的一種常用的分組交換網絡分層協議集。一旦連接建立起來,客戶端和服務器之間交換的報文就永遠不會丟失、受損或失序。但計算機或網絡崩潰,會使通信終端。
1.1.TCP可靠數據管道
?
TCP為HTTP提供了一條可靠的比特傳輸管道。
瀏覽器接受到一個URL的時候,會執行以下步驟:
#1:客戶端解析出主機名;
#2:客戶端查詢這個主機名的IP地址(DNS);
#3:客戶端解析出端口號;
#4:客戶端發起到對應IP和端口的連接;
#5:客戶端向服務器發送一條HTTP GET請求報文;
#6:客戶端等待響應,響應回送客戶端,客戶端讀取HTTP響應報文;
#7:關閉連接。
1.2.數據分段傳送
HTTP要傳送報文時,會以流的形式將報文數據內容通過已經打開的TCP連接按序傳輸。TCP收到數據流后,會將數據流切割成小數據塊,封裝在IP分組中,通過Internet傳輸。所有這些工作都由TCP/IP軟件來處理。
每個IP分組都包括:
#1:一個IP分組首部(通常20字節);
#2:一個TCP段首部(通常20字節);
#3:一個TCP數據塊(0到n個字節)。
1.3.TCP連接識別
TCP連接是通過4個值來識別的:
<源IP地址 , 源端口號 , 目的IP地址 , 目的端口號>
倆條不同的TCP連接不能擁有4個完全相同的地址組件值。
2.TCP性能
HTTP位于TCP上層,所以HTTP的性能很大程度上取決于底層TCP通道的性能。
2.1.HTTP事務時延原因
#1:客戶端根據URL確定web服務器的IP地址和端口。通過DNS解析系統將URL的主機名換成一個IP地址可能需要耗費數十秒的時間,如果近期有有訪問過,則客戶端會緩存起來,這時候就不需要訪問DNS了,但這個DNS緩存不大;
#2:客戶端向服務器發送一條TCP連接請求。每條TCP連接都會有連接建立時延;
#3:因特網傳輸請求報文以及處理請求報文;
#4:服務器回送HTTP響應。
2.2.TCP時延
#1:TCP連接建立握手;
#2:TCP慢啟動擁塞控制;
#3:數據聚集的Nagle算法;
#4:用于捎帶確認的TCP的延遲確認算法;
#5:TIME_WAIT時延和端口耗盡。
2.3.TCP連接建立握手時延
#1:請求新的TCP連接時,客戶端會向服務器發送一個小的TCP分組(通常40~60字節),這個分組設置一個特殊的SYN標記;
#2:如果服務器接受了連接,會想客戶端回送TCP分組,這二個分組中的SYN和ACK標記都會被置位,說明請求已被接受;
#3:客戶端向服務器回送一條確認信息,通知連接已成功建立。
NOTE:小的HTTP事務都會在TCP建立耗費50%或者以上的時間。
2.4.捎帶確認的TCP的延遲確認算法
#1:每個TCP段都有一個序列號和數據完整性校驗和。每個段的接收者收到完好的段時,都會向發送者回送確認報文。
#2:如果發送者沒有在指定的窗口時間內收到確認信息,發送者就認為分組已被破壞或毀壞,并重發數據。
#3:由于確認報文很小,所以TCP允許在發往相同方向的輸出數據分組中對其進行“捎帶”,如果在特定的時間窗口(通常100~200毫秒)沒有輸出數據分組,就將確認信息放在單獨的分組中傳送。
2.5.TCP慢啟動
#1:TCP連接的使用期(age)是TCP數據傳輸性能的影響因數之一。
#2:起初會限制連接的最大速度,如果數據成功傳輸,會隨著時間的推移提高傳輸的數據。這種調諧被稱為TCP慢啟動,用于防止Internet的突然過載和擁堵。
#3:TCP慢啟動限制了一個TCP端點再任意時刻可以傳輸的分組數。
#4:由于存在這種擁塞控制特性,所以新的連接的傳輸速度會比已經交換過一定量數據的、”已調諧“連接慢一些。
2.6.Nagle算法與TCP_NODELAY
#1:Nagle算法試圖發送一個分組之前,將大量TCP數據綁定在一起,以提高網絡效率。鼓勵發送全尺寸(LAN最大尺寸分組大約1500字節,Internet上是幾百字節),只有當所有其他分組都被確認,或者緩存積累一個全尺寸的分組數據之后,才允許發送;
#2:Nagle算法會阻塞數據的發送。若小HTTP報文無法填滿一個分組,可能會因為等待那些永遠不會到來的額外數據而產生時延;阻塞數據的發送,但本身分組確認延遲100~200毫秒;
#3:TCP_NODELAY可以設置禁用Nagle算法,提供性能,但要確保TCP寫入大塊數據。
2.7.TIME_WAIT時延和端口耗盡
#1:在TCP端點關閉連接時,會在內存中維護一個用來記錄最近所關閉連接的IP地址和端口號的控制塊,通常只會維持最大分段試用期的倆倍(2MSL,通常為2分鐘)左右,以確保這段時間內不會創建具有相同地址和端口號的新連接;
#2:有些操作系統會將2MSL設置為一個較小的值,但超過這個值,要小心,分組確實會被復制,如果來自之前連接的復制分組插入到具有相同連接值的新TCP流,會破壞TCP數據;
#3:客戶端每次連接到服務器時,都會獲得一個新的源端口,以實現連接的唯一性。但源端口有限,而且在2MSL內連接是無法重用,連接率就被限制住了;
#4:在有大量打開連接或控制塊的情況下,有些操作系統的速度會嚴重減緩。
3.HTTP性能
3.1.http串行處理時延
對連接進行簡單的管理,TCP的性能時延可能會疊加。
假如一個包含3個嵌入圖片的web頁面,瀏覽器需要發起4個HTTP事務來顯示此頁面,每個事務都需要(串行地創建)一條新的連接,那么連接時延和慢啟動時延就會疊加起來。
提高http連接性能:
#1:并行連接:多條TCP連接發起并發的http請求;
#2:持久連接:重用TCP連接,消除連接及關閉時延;
#3:管道化連接:共享TCP連接發起并發的HTTP請求;
#4:復用的連接:交替傳送請求和響應報文(實驗階段)。
3.2.并行連接
#1:并行可能會提高頁面的加載速度
并行連接,克服單條連接的空載時間和帶寬限制,加速速度也會有所提高。
#2:并行連接不一定更快
1)客戶端的網絡帶寬不足時,大部分時間都在用來傳數據,帶來的提升不大;
2)打開大量的連接,會造成服務器性能嚴重下降;
3)實際上,瀏覽器使用并行連接,一般連接總數限制通常4個,服務器可以隨意關閉來自特定客戶端的超量連接。
3.3.持久連接
客戶端經常要打開同一個站點的連接,重用對目標服務器打開的空閑持久連接,就可以避免緩慢的連接建立階段和慢啟動的擁塞適應階段,以便更快地進行數據的傳輸。
持久連接有倆種類型:HTTP/1.0+ "keep-alive"(較老)和HTTP/1.1 ”persistent“
#1:HTTP/1.0+ keep-alive連接
早期的HTTP/1.0+ keep-alive持久性連接,受到了一些互操作行設計方面問題的困擾,問題在HTTP/1.1修正,單很多客戶端和服務器仍然使用1.0版本。
1>Keep-Alive操作
實現HTTP/1.0 keep-alive連接的客戶端,通過包含Connection: Keep-Alive首部請求將一條連接保持在打開狀態。
如果響應沒有Connection: Keep-Alive首部,客戶端就認為服務器不支持Keep-Alive。
2>Keep-Alive選項
Note:
1)發出Keep-Alive請求,客戶端和服務器不一定會同意;
2)客戶端和服務器可以在任意時刻可以關閉空閑的Keep-Alive連接;
3)可以隨意限制Keep-Alive連接所處理事務的數量。
Keep-Alive首部可以調節以上行為:
格式:
Connection: Keep-Alive
Keep-Alive: (["max""="n] [",""timeout""="seconds ][header[value]])
服務器最多會為另外5個事務保持連接打開狀態,或者打開狀態保持到連接空閑了2分鐘,例子:
?
Connection: Keep-Alive
Keep-Alive: max=5, timeout=120
參數:
max:估計服務器還希望為多少個事務保持此連接活躍狀態。非承諾值。
timeout:估計服務器還希望將連接保持在活躍狀態的時間。非承諾值。
header:任意為經處理的屬性,用于診斷和調試。
3>Keep-Alive連接的限制和規則
1)HTTP/1.0中,Keep-Alive不是默認使用的,需要Connection: Keep-Alive;
2)Connection: Keep-Alive必須隨所有希望持久連接的報文一起發送,否則會在那條請求后關閉連接;
3)響應報文中沒有Connection: Keep-Alive,則服務器會在發出響應后關閉持久連接;
4)實體部分必須有正確的Content-Length,否則無法精確一條報文的結束和另一條報文的開始,不能持久連接;
5)代理或網關必須在將報文轉發出去或將其高速緩存之前,刪除Connection首部中命名的所有首部字段以及Connection首部;
6)不應該與無法確定是否支持Connection首部的代理服務器建立Keep-Alive連接。
4>Keep-Alive和啞代理
1)不支持Connection首部的代理盲中繼
step-1:客戶端發送一條包含Connection: Keep-Alive首部的請求報文;
step-2:啞代理不理解Connection首部,只是沿著鏈路將該首部發送到服務器;
step-3:服務器收到Connection: Keep-Alive,認為對方希望進行Keep-Alive對話,則回送包含Connection: Keep-Alive的響應報文;
step-4:啞代理回送來自服務器的響應報文到客戶端,然后等待源端服務器關閉連接,但服務器不會關閉連接;
step-5:客戶端收到含有Connection: Keep-Alive首部的響應報文,就認為代理同意進行Keep-Alive對話;
step-6:客戶端在Keep-Alive連接上向代理發送請求報文,而代理并不認為同一條連接上會有其他請求到來,請求被忽略;
step-7:客戶端一直掛起狀態,直到連接超時,并將其關閉為止。
2)代理與逐跳首部
為了避免以上問題發生,現代代理都絕不能轉發Connection首部和所有名字出現在Connection值中的首部。
Proxy-Authenticate/Proxy-Connection/Transfer-Encoding/Upgrade同樣不能被代理轉發或作為緩存響應使用的首部。
5>插入Proxy-Connection
聰明的代理(能理解持久連接的握手動作),就用一個Connection首部來取代Proxy-Connection首部,將其轉發到服務器達到預期的效果。
但是對于多層次代理,Proxy-Connection仍然不能解決問題。
#2:HTTP/1.1 持久連接
HTTP/1.1用了持久連接(persistent connection)取代了Keep-Alive,目的與Keep-Alive一樣;
HTTP/1.1默認情況下激活持久連接,要在事務處理結束之后關閉連接,要在響應報文包含Connection: close;
響應報文不包含Connection: close,并不意味著服務器承諾永遠將連接保持打開,客戶端和服務器仍然可以隨時關閉空閑的連接。
#3:持久連接的限制和規則
1)發送了Connection: close,客戶端無法在那條連接上發送更多請求;
2)連接保持,連接上的所有報文都需要正確、自定義報文長度正確;
3)HTTP/1.1的代理服務器不應該與HTTP/1.0客戶端建立連接;
4)客戶端對任務服務器或代理最多只能維持2條持久連接,防止服務器過載。
3.4.管道化連接
HTTP/1.1允許在持久連接上可選使用請求管道。在響應到達前,可以將多條請求放入隊列。可以降低網絡的換回時間,提高性能。
管道化限制:
#1:確定客戶端支持持久連接;
#2:必須按照與請求順序回送HTTP響應;
#3:客戶端做好任意時刻連接關閉、重發所有未完成管道化的請求準備。
3.5.關閉連接
#1:“任意時刻”解除連接
管道化持久連接很常見。持久連接空閑一段時間,服務器可能會決定關閉連接。但是服務器無法確定關閉的那一刻,連接的另一頭有沒有報文要發送,若客戶端此時在寫入半截請求報文,會發生報錯。
#2:Content-Length及截尾操作
連接關閉依據正確的Content-Length首部或包含Connection: close的響應報文。
#3:連接關閉容限、重試以及冪等性
如果一個事務,不管是執行多少次,得到的結果都是相同的,那么這個事務就是冪等的。
在非錯誤的情況下,連接會在任意時刻關閉,客戶端要做好正確處理非預期關閉的準備,對于冪等事務可以重新請求,但是對于非冪等事務要另作考慮(如果只是響應報文沒有返回,那再次請求會造成非預想結果)。
#4:正常關閉連接
TCP連接是雙向的,每一段都有一個輸入隊列和一個輸出隊列。
1>TCP關閉及重置錯誤
簡單的http應用程序可以只使用全關閉。
很多客戶端、服務器和代理通信已經開始使用管道化持久連接,使用半關閉來防止對等實體收到非預期的寫入錯誤。
若另一端往你已關閉的輸入信道發送數據,操作系統就會向另一端回送一條TCP"連接被對端重置"的報文。大部分系統都會作為很嚴重的錯誤處理,清空對端還未讀取的所有緩存數據。
2>正常關閉
先關閉自己的輸出信道,然后等待另一端的對等實體關閉它的輸出信道。
如果在一段時間內對端沒有關閉輸入信道,應用程序可以強制關閉連接。
?
附錄:
HTTP/1.1官網規范
持久連接HTTP實例
P-HTTP與TCP之間實現性能交互
TCP慢啟動、避免擁塞、快速重傳以及快速恢復算法
TCP確認和延遲確認
Nagle算法
傳輸控制協議
總結
- 上一篇: Linux文件查找Find命令使用解析
- 下一篇: KoalaUI的DateTimePick