幾乎所有的HTTP通信都是由TCP/IP承載的,TCP/IP是全球計算機網絡設備都在使用的一種分組交換網絡分層協議集。
它的特點是只要連接建立,客戶端與服務器之間的報文交換就永遠不會丟失、受損或失序。
一、TCP連接
1、TCP是可靠數據通道
TCP是英特網上的可靠連接,TCP為HTTP提供了一條可靠地比特傳輸通道,從TCP連接一端填入的字節會從另一端以原有的順序、正確的傳送出來。
TCP會按序、無差錯的承載HTTP數據,如下圖:
2、TCP流是分段的,由IP分組傳送
TCP的數據是通過名為IP分組的小數據塊發送的,HTTP就是“HTTP over TCP over IP”這個“協議棧”中的最頂層,其安全版本HTTPS就是在HTTP和TCP之間插入一個(TLS或SSL)密碼加密層。
如下圖所示:
HTTP在傳送一條報文時,會以流的形式將報文數據通過打開的TCP連接按序傳輸。TCP收到數據流之后,將其划分為被稱為段的小數據塊,封裝在IP分組中,通過英特網進行傳輸。
每個TCP段都是由IP分組承載,從一個IP地址發送到另一個IP地址,其中包括:
①、一個IP分組首部(通常為20字節):包含源和目的IP地址、長度和其他一些標記;
②、一個TCP 段首部(通常為20字節):包含TCP端口號、TCP控制標記以及用於數據排序和完整性檢查的數據值;
③、一個TCP數據塊(0個或多個字節);
3、保持TCP連接不斷運行
TCP通過端口號來保持連接持續不斷的運行。IP地址可以連接到正確的計算機,端口號可以連接到正確的應用程序,TCP連接通過四個值來識別:
<源IP地址、源端口號、目的IP地址、目的端口號>
這四個值唯一的定義了一個連接(兩條不同的TCP連接不能擁有4個完全相同的地址組件值,不同連接部分可以擁有同樣的值)。
4、TCP套接字
操作系統提供了一些操縱TCP連接的編程接口,即套接字API,這個套接字API隱藏了所有的TCP和IP實現細節,下表是一些套接字API的主要接口:
套接字API調用 | 描述 |
s= socket(<sparameters>) | 創建一個新的、未命名、未關聯的套接字 |
bind(s,<local IP:port>) | 向套接字賦一個本地端口號和接口 |
connect(s, <remote IP:port>) | 創建一條連接本地套接字與遠程主機及端口的連接 |
listen(s,...) | 標識一個本地套接字,使其可以合法接受連接 |
s2 = accept(s) | 等待某人建立一條到本地端口的連接 |
n = read(s, buffer, n) | 嘗試從套接字向緩沖區讀取n個字節 |
n = write(s, buffer, n) | 嘗試從緩沖區中向套接字寫入n個字節 |
close(s) | 完全關閉TCP連接 |
shutdown(s,<side>) | 只關閉TCP連接的輸出或輸入端 |
getsockopt(s,...) | 讀取某個內部套接字配置選項的值 |
setsockopt(s,...) | 修改某個內部套接字配置選項的值 |
套接字API允許用戶創建TCP的端點數據結構,將其與遠程服務器的TCP端點進行連接,並對數據流進行讀寫。
TCP API隱藏了所有底層網絡協議的握手細節,以及TCP數據流與IP分組之間的字段和重裝細節。
二、TCP性能
1、HTTP事務的時延
首先來看一個HTTP請求的過程,如下圖:
一般來說,相比於建立TCP連接及傳輸請求和響應報文的時間,事務處理時間可能是很短的(除非客戶端或服務端超載或正在處理復雜的動態資源),否則HTTP時延是由TCP網絡時延造成的。
http事務時延的原因有以下幾點:
①、DNS將服務器域名轉換解析為一個IP地址所花費的時間;
②、客戶端向服務端發送一個TCP連接請求所造成的時延(一般不會花費很多時間,但如果有很多的HTTP事務的話,時延就會變大);
③、服務端處理請求報文以及回傳給客戶端,都需要花費一定的時間;
④、服務器回送HTTP響應,也會花費一定的時間;
2、性能聚焦區域
常見的TCP相關時延如下:
①、TCP連接建立握手;
如下圖,新建TCP連接時會交換一系列的IP分組,對連接的有關參數進行溝通,如果連接只用來傳送少量數據,交換的過程就會嚴重降低HTTP性能。
②、TCP慢啟動擁塞機制;
TCP連接剛建立時為了防止網絡突然過載和擁塞,會限制鏈接的最大速度,如果數據成功傳輸,會隨着時間的推移提高傳輸速度。
③、數據聚集的Nagle算法;
④、用於捎帶確認的TCP延遲確認算法;
⑤、TIME_WAIT時延和端口耗盡;
三、HTTP連接處理
目前現存和常用的連接方法大概有一下四種:
1、串行連接
最早的連接方式,即HTTP事務需要按順序進行傳輸,等待服務端完成處理並回傳,如下圖所示:
這樣做有兩個缺點:
①、TCP性能時延會不斷疊加;
②、在請求處理完成之前,客戶端無法對結果進行提前展示,只能被動等待;
2、並行連接
通過多條TCP連接發情並發的HTTP請求,如下圖所示:
並行連接有如下幾個特點:
①、可能會提高頁面加載速度,即連接請求和傳輸時間重疊,減小了連接時延和傳輸時延,但每個事務都會打開/關閉一個新的連接,耗費時間和帶寬;
②、可以讓用戶“感覺更快”(與WEB頁面渲染的異步展示類似的原理),但實際上,由於TCP慢啟動特性的存在,每個新連接的性能都會有所降低,且並行鏈接數量有限;
③、並行連接不一定比串行連接塊(受限於帶寬,可能造成資源競爭);
3、持久連接
重用TCP連接,以消除連接及關閉時延,持久連接+並行連接,可能是最高效的連接方式,如下圖所示:
持久連接有兩種方式,分別為HTTP/1.0+的“Keep-alive”連接,以及HTTP/1.1的“persistent”連接。
Keep-alive:該首部只是請求將連接保持在活躍狀態,客戶端和服務端可以隨時關閉空閑的Keep-alive連接。
限制和規則:
①、必須客戶端發送一個Connection:Keep-alive請求首部來激活Keep-alive連接;
②、該首部必須隨請求的報文一起發送;
③、只有在確定實體主體部分大小的情況下,連接才能保持在打開狀態;
④、代理和網關必須執行Connection首部的規則;
Persistent:該首部默認情況下是激活的,除非特別指明,否則HTTP/1.1假定所有連接都是持久的。
限制和規則:
①、如果需要在事務處理結束后將連接關閉,則應用程序必須向報文中顯式的添加一個Connection-close首部;
②、只有當連接上所有報文都有正確的、自動以報文長度時,連接才能持久保持;
③、每個持久連接都只適用於一跳傳輸;
④、應用程序可以在任意時刻關閉連接,但應該能夠從異步關閉中恢復,重試這條請求;
⑤、一個客戶端對任何服務器或代理最多只能維護2條持久連接;
4、管道化連接
通過共享TCP連接發起並發的HTTP請求,這也是在持久連接的基礎上對性能的一種優化。
原理:在響應到達前,將多條請求放入隊列,在高延時網絡條件下,可以降低網絡環回時間,提高性能。
限制和規則:
①、如果HTTP客戶端無法確認連接是持久的,就不應使用管道連接;
②、必須按照與請求相同的順序回送HTTP響應;
③、客戶端必須做好連接會在任何時刻關閉的准備,以及重發所有未完成的管道化請求;
④、HTTP客戶端不應用管道化的方式發送非冪等性請求(比如POST);
四種不同連接方式的區別:
某些關於請求和響應首部的字段詳細介紹,可以參考《HTTP權威指南》這本書中的內容。。。