0、html
在真正試圖解決你的疑問的以前,咱們來看一下,從發出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運算)。
服務器
至此,一個流程就這樣簡單地構造完畢了網絡
一、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,具備一些性能上的缺陷。socket
例如,一個包含有許多圖像的網頁文件中並無包含真正的圖像數據內容,而只是指明瞭這些圖像的URL地址,當WEB瀏覽器訪問這個網頁文件時,瀏覽器首先要發出針對該網頁文件的請求,當瀏覽器解析WEB服務器返回的該網頁文檔中的HTML內容時,發現其中的圖像標籤後,瀏覽器將根據標籤中的src屬性所指定的URL地址再次向服務器發出下載圖像數據的請求。顯 然,訪問一個包含有許多圖像的網頁文件的整個過程包含了屢次請求和響應,每次請求和響應都須要創建一個單獨的鏈接,每次鏈接只是傳輸一個文檔和圖像,上一次和下一次請求徹底分離。即便圖像文件都很小,可是客戶端和服務器端每次創建和關閉鏈接倒是一個相對比較費時的過程,而且會嚴重影響客戶機和服務器的性能。當一個網頁文件中包含JavaScript文件,CSS文件等內容時,也會出現相似上述的狀況。tcp
同時,帶寬和延遲也是影響一個網絡請求的重要因素。在網絡基礎建設已經使得帶寬獲得極大的提高的當下,大部分時候都是延遲在於響應速度。基於此會發現,http1.0被抱怨最多的就是鏈接沒法複用,和head of line blocking這兩個問題。理解這兩個問題有一個十分重要的前提:客戶端是依據域名來向服務器創建鏈接,通常PC端瀏覽器會針對單個域名的server同時創建6~8個鏈接,手機端的鏈接數則通常控制在4~6個。顯然鏈接數並非越多越好,資源開銷和總體延遲都會隨之增大。鏈接沒法複用會致使每次請求都經歷三次握手和慢啓動。三次握手在高延遲的場景下影響較明顯,慢啓動則對文件類大請求影響較大。head of line blocking會致使帶寬沒法被充分利用,以及後續健康請求被阻塞。post
二、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 表示最高優先級, 數值越大優先級越低。