0、
在真正試圖解決你的疑問的之前,我們來看一下,從發出request之前到接收respon之后,都發生了什么。
0.你向瀏覽器的地址欄輸入一個域名.如 http://www.zhihu.com
1.瀏覽器向你的本地DNS服務器請求解析該域名,即將你的http://www.zhihu.com 解析為真實的IP地址.詳細協議請查詢RFC文檔,其中對DNS協議的格式內容,指令意義,壓縮算法,等都作出了規定。
2.拿到ip地址之后,發起TCP 握手(3次),詳情請看計算機網絡TCP協議部分
3.握手成功,構造request,即 HTTP 中request請求.並發送到目的地。有關HTTP協議的內容請查閱RFC文檔可以購買HTTP權威指南作為參考和釋疑.
4.服務器接受到一個完整的request(該邊界的指定一般是conten-length,chunked也有),根據用戶的request內容運算出相應的response。
5.服務器將response 沿着request建立的連接,向瀏覽器(客戶端)發送數據。
5.5 keepalive的時候不關閉該連接,沒有keepalive的時候發起tcp close,4次握手
6.瀏覽器根據接收到的response開始渲染頁面。
至此,一個網頁的打開過程完畢,我們從中提取出耗時的部分。
1.DNS查詢時間(一來一回,走UDP協議) 網絡IO
2.tcp 建立連接握手 網絡IO
3.request構造時間(cpu運算)
4.request發送完畢時間(網絡IO)
5.服務器接收request運算構造response(CPU運算,特指構造response過程中沒有任何IO操作)
6.服務器發送response到客戶端的時間(網絡IO)
6.5 服務器關閉連接時間(IO)
7.客戶端接收數據渲染頁面時間(cpu運算)。
至此,一個流程就這樣簡單地構造完畢了
1、http 1.0:每一個http請求都會打開一個tcp socket連接,當交互完畢后會關閉這個連接。之后, 從1996年開始,很多HTTP/1.0瀏覽器與服務器都對協議進行了擴展,那就是“keep-alive”擴展協議。使用HTTP/1.0的客戶端在首部中加上"Connection:Keep-Alive",請求服務端將一條連接保持在打開狀態。服務端如果願意將這條連接保持在打開狀態,就會在響應中包含同樣的首部。如果響應中沒有包含"Connection:Keep-Alive"首部,則客戶端會認為服務端不支持keep-alive,會在發送完響應報文之后關閉掉當前連接。
對於http 1.0,具有一些性能上的缺陷。
例如,一個包含有許多圖像的網頁文件中並沒有包含真正的圖像數據內容,而只是指明了這些圖像的URL地址,當WEB瀏覽器訪問這個網頁文件時,瀏覽器首先要發出針對該網頁文件的請求,當瀏覽器解析WEB服務器返回的該網頁文檔中的HTML內容時,發現其中的圖像標簽后,瀏覽器將根據標簽中的src屬性所指定的URL地址再次向服務器發出下載圖像數據的請求。顯 然,訪問一個包含有許多圖像的網頁文件的整個過程包含了多次請求和響應,每次請求和響應都需要建立一個單獨的連接,每次連接只是傳輸一個文檔和圖像,上一次和下一次請求完全分離。即使圖像文件都很小,但是客戶端和服務器端每次建立和關閉連接卻是一個相對比較費時的過程,並且會嚴重影響客戶機和服務器的性能。當一個網頁文件中包含JavaScript文件,CSS文件等內容時,也會出現類似上述的情況。
同時,帶寬和延遲也是影響一個網絡請求的重要因素。在網絡基礎建設已經使得帶寬得到極大的提升的當下,大部分時候都是延遲在於響應速度。基於此會發現,http1.0被抱怨最多的就是連接無法復用,和head of line blocking這兩個問題。理解這兩個問題有一個十分重要的前提:客戶端是依據域名來向服務器建立連接,一般PC端瀏覽器會針對單個域名的server同時建立6~8個連接,手機端的連接數則一般控制在4~6個。顯然連接數並不是越多越好,資源開銷和整體延遲都會隨之增大。連接無法復用會導致每次請求都經歷三次握手和慢啟動。三次握手在高延遲的場景下影響較明顯,慢啟動則對文件類大請求影響較大。head of line blocking會導致帶寬無法被充分利用,以及后續健康請求被阻塞。
2、http 1.1:HTTP/1.1采取持久連接的方式替代了Keep-Alive。HTTP/1.1的連接默認情況下都是持久連接。如果要顯式關閉,需要在報文中加上Connection:Close首部。即在HTTP/1.1中,所有的連接都進行了復用。然而如同Keep-Alive一樣,空閑的持久連接也可以隨時被客戶端與服務端關閉。不發送Connection:Close不意味着服務器承諾連接永遠保持打開。HttpClient通過連接池來管理持久連接。
HTTP/1.1的KeepAlive就是串行的會話模式,一去一回,省掉的是TCP層面重復創建的成本。
在 HTTP/2 中,有了二進制分幀之后,HTTP/2 不再依賴 TCP 鏈接去實現多流並行了,在 HTTP/2 中:
- 同域名下所有通信都在單個連接上完成,同個域名只需要占用一個 TCP 連接,使用一個連接並行發送多個請求和響應。
- 單個連接可以承載任意數量的雙向數據流,單個連接上可以並行交錯的請求和響應,之間互不干擾。
- 數據流以消息的形式發送,而消息又由一個或多個幀組成,多個幀之間可以亂序發送,因為根據幀首部的流標識可以重新組裝。每個請求都可以帶一個 31bit 的優先值,0 表示最高優先級, 數值越大優先級越低。