來自:互扯程式(微訊號:chat_routine)
作者:互扯程式,某網際網路公司P8級專家攻城獅,曾參與過央視全臺網的研發工作。目前正在做車聯網專案的雲平臺的架構設計與研發工作。平時喜歡打球游泳,偶爾發表一些技術文章。
開篇HTTP發展的心路歷程
上圖:連線無法復用
上圖:設定Connection:Keep-Alive,保持連線在一段時間內不斷開。
上圖:HTTPpipelining:建立多個連線
上圖:多路復用
-
HTTP協議 :Hyper Text Transfer Protocol(超文字傳輸協議),是用於從全球資訊網(WWW:World Wide Web )伺服器傳輸超文字到本地瀏覽器的傳送協議。是網際網路上應用最為廣泛的一種網路協議。所有的WWW檔案都必須遵守這個標準。
-
HTTP是一個基於TCP/IP通訊協議來傳遞資料(HTML 檔案, 圖片檔案, 查詢結果等)。
-
HTTP是一個屬於應用層的面向物件的協議,由於其簡捷、快速的方式,適用於分散式超媒體資訊系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和擴充套件。
-
HTTP協議工作於客戶端-服務端架構為上。瀏覽器作為HTTP客戶端透過URL向HTTP服務端即WEB伺服器傳送所有請求。Web伺服器根據接收到的請求後,向客戶端傳送響應資訊。
-
HTTP 0.9作為HTTP協議的第一個版本。是非常弱的。請求(Request)只有一行,比如: GET www.leautolink.com
-
HTTP1.0最早在網頁中使用是在1996年,那個時候只是使用一些較為簡單的網頁上和網路請求上。
-
HTTP1.1則在1999年才開始廣泛應用於現在的各大瀏覽器網路請求中,同時HTTP1.1也是當前使用最為廣泛的HTTP協議。
HTTP 1.1 做了哪些升級:
-
快取處理,在HTTP1.0中主要使用essay-header裡的If-Modified-Since,Expires來做為快取判斷的標準,HTTP1.1則引入了更多的快取控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供選擇的快取頭來控制快取策略。
-
頻寬最佳化及網路連線的使用,HTTP1.0中,存在一些浪費頻寬的現象,例如客戶端只是需要某個物件的一部分,而伺服器卻將整個物件送過來了,並且不支援斷點續傳功能,HTTP1.1則在請求頭引入了range頭域,它允許只請求資源的某個部分,即傳回碼是206(Partial Content),這樣就方便了開發者自由的選擇以便於充分利用頻寬和連線。
-
錯誤通知的管理,在HTTP1.1中新增了24個錯誤狀態響應碼,如409(Conflict)表示請求的資源與資源的當前狀態發生衝突;410(Gone)表示伺服器上的某個資源被永久性的刪除。
-
Host頭處理,在HTTP1.0中認為每臺伺服器都系結一個唯一的IP地址,因此,請求訊息中的URL並沒有傳遞主機名(hostname)。但隨著虛擬主機技術的發展,在一臺物理伺服器上可以存在多個虛擬主機(Multi-homed Web Servers),並且它們共享一個IP地址。HTTP1.1的請求訊息和響應訊息都應支援Host頭域,且請求訊息中如果沒有Host頭域會報告一個錯誤(400 Bad Request)。
-
長連線,HTTP 1.1支援長連線(PersistentConnection)和請求的流水線(Pipelining)處理,在一個TCP連線上可以傳送多個HTTP請求和響應,減少了建立和關閉連線的消耗和延遲,在HTTP1.1中預設開啟Connection: keep-alive,一定程度上彌補了HTTP1.0每次請求都要建立連線的缺點。
如何建立連線(三次握手)
HTTP 是基於 TCP 協議的,瀏覽器最快也要在第三次握手時才能捎帶 HTTP 請求報文,達到真正的建立連線,但是這些連線無法復用會導致每次請求都經歷三次握手和慢啟動。三次握手在高延遲的場景下影響較明顯,慢啟動則對檔案類大請求影響較大。
-
第一次握手:建立連線時,客戶端傳送syn包(syn=j)到伺服器,併進入SYN_SENT狀態,等待伺服器確認;SYN:同步序列編號(Synchronize Sequence Numbers)。
-
第二次握手:伺服器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態;
-
第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包ACK(ack=k+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED(TCP連線成功)狀態,完成三次握手。
完成三次握手,客戶端與伺服器開始傳送資料。
如何關閉連線(四次揮手):
由於TCP連線是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的資料傳送任務後就能傳送一個FIN來終止這個方向的連線。收到一個 FIN只意味著這一方向上沒有資料流動,一個TCP連線在收到一個FIN後仍能傳送資料。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
TCP的連線的拆除需要傳送四個包,因此稱為四次揮手(four-way handshake)。客戶端或伺服器均可主動發起揮手動作,在socket程式設計中,任何一方執行close()操作即可產生揮手操作。
-
客戶端A傳送一個FIN,用來關閉客戶A到伺服器B的資料傳送。
-
伺服器B收到這個FIN,它發回一個ACK,確認序號為收到的序號加1。和SYN一樣,一個FIN將佔用一個序號。
-
伺服器B關閉與客戶端A的連線,傳送一個FIN給客戶端A。
-
客戶端A發回ACK報文確認,並將確認序號設定為收到序號加1。
瀏覽器阻塞(HOL blocking):
瀏覽器對於同一個域名,一般PC端瀏覽器會針對單個域名的server同時建立6~8個連線,手機端的連線數則一般控制在4~6個(這個根據瀏覽器核心不同可能會有所差異),超過瀏覽器最大連線數限制,後續請求就會被阻塞。
SPDY協議是Google提出的基於傳輸控制協議(TCP)的應用層協議,透過壓縮、多路復用和優先順序來縮短載入時間。該協議是一種更加快速的內容傳輸協議,於2009 年年中釋出。
GoogleChrome、MozillaFirefox以及Opera已預設開啟SPDY。Google曾經稱它的測試顯示,頁面載入提高了一倍。該協議是一種更加快速的內容傳輸協議。
SPDY協議設定的標的
1. 頁面載入時間(PLT,Page • Load Time)降低 50%;
2. 無需網站作者修改任何內容;
3. 最小化配置複雜度,無需變更網路基礎設施;
註:為了達到降低50% 頁面載入時間的標的,SPDY 引入了一個新的二進位制分幀資料層,以實現多向請求和響應、優先次序、最小化及消除不必要的網路延遲,目的是更有效地利用底層TCP 連線;
-
HTTP-WG(HTTP Working Group)在2012 年初把HTTP 2.0提到了議事日程,吸取SPDY 的經驗教訓,併在此基礎上制定官方標準。
-
HTTP/2 的主要標的是改進傳輸效能,更有效地利用網路資源,實現低延遲和高吞吐量。從另一方面看,HTTP 的高層協議語意並不會因為這次版本升級而受影響。所有HTTP 首部、值,以及它們的使用場景都不會變。
-
HTTP/2 致力於突破上一代標準眾所周知的效能限制,但它也是對之前1.x 標準的擴充套件,而非替代。之所以要遞增一個大版本到2.0,主要是因為它改變了客戶端與伺服器之間交換資料的方式
HTTP/2 是如何提高效率呢?
二進位制分幀:HTTP 2.0 的所有幀都採用二進位制編碼
-
幀:客戶端與伺服器透過交換幀來通訊,幀是基於這個新協議通訊的最小單位。
-
訊息:是指邏輯上的 HTTP 訊息,比如請求、響應等,由一或多個幀組成。
-
流:流是連線中的一個虛擬通道,可以承載雙向的訊息;每個流都有一個唯一的整數識別符號(1、2…N);
多路復用 (Multiplexing)
多路復用允許同時透過單一的 HTTP/2 連線發起多重的請求-響應訊息。有了新的分幀機制後,HTTP/2 不再依賴多個TCP 連線去實現多流並行了。每個資料流都拆分成很多互不依賴的幀,而這些幀可以交錯(亂序傳送),還可以分優先順序。最後再在另一端把它們重新組合起來。HTTP 2.0 連線都是持久化的,而且客戶端與伺服器之間也只需要一個連線(每個域名一個連線)即可。
請求優先順序
-
把HTTP 訊息分解為很多獨立的幀之後,就可以透過最佳化這些幀的交錯和傳輸順序,每個流都可以帶有一個31 位元的優先值:0 表示最高優先順序;2的31次方-1 表示最低優先順序。
-
伺服器可以根據流的優先順序,控制資源分配(CPU、記憶體、頻寬),而在響應資料準備好之後,優先將最高優先順序的幀傳送給客戶端。
-
HTTP 2.0 一舉解決了所有這些低效的問題:瀏覽器可以在發現資源時立即分派請求,指定每個流的優先順序,讓伺服器決定最優的響應次序。這樣請求就不必排隊了,既節省了時間,也最大限度地利用了每個連線。
essay-header壓縮
HTTP1.x的essay-header帶有大量資訊,而且每次都要重覆傳送,HTTP/2使用encoder來減少需要傳輸的essay-header大小,通訊雙方各自cache一份essay-header fields表,既避免了重覆essay-header的傳輸,又減小了需要傳輸的大小。
服務端推送
-
伺服器可以對一個客戶端請求傳送多個響應。伺服器向客戶端推送資源無需客戶端明確地請求。
-
HTTP 2.0 連線後,客戶端與伺服器交換SETTINGS 幀,藉此可以限定雙向併發的流的最大數量。
-
所有推送的資源都遵守同源策略。換句話說,伺服器不能隨便將第三方資源推送給客戶端,而必須是經過雙方確認才行。
-
伺服器必須遵循請求- 響應的迴圈,只能藉著對請求的響應推送資源
伺服器推送到底是什麼?
服務端推送能把客戶端所需要的資源伴隨著index.html一起傳送到客戶端,省去了客戶端重覆請求的步驟。正因為沒有發起請求,建立連線等操作,所以靜態資源透過服務端推送的方式可以極大地提升速度。
普通的客戶端請求過程:
服務端推送的過程:
HTTP/2的多路復用和HTTP1.1中的長連線復用有什麼區別?
-
HTTP/1.0 一次請求-響應,建立一個連線,用完關閉;每一個請求都要建立一個連線;
-
HTTP/1.1 Pipeling解決方式為,若干個請求排隊序列化單執行緒處理,後面的請求等待前面請求的傳回才能獲得執行機會,一旦有某請求超時等,後續請求只能被阻塞,毫無辦法,也就是人們常說的線頭阻塞;
-
HTTP/2多個請求可同時在一個連線上並行執行。某個請求任務耗時嚴重,不會影響到其它連線的正常執行;
現有的任何網站和應用,無需做任何修改都可以在HTTP 2.0 上跑起來。不用為了利用HTTP 2.0 的好處而修改標記。HTTP 伺服器必須執行HTTP 2.0 協議,但大部分使用者都不會因此而受到影響。
如果你使用NGINX,只要在配置檔案中啟動相應的協議就可以了,可以參考NGINX白皮書,NGINX配置HTTP2.0官方指南。
使用了HTTP2.0那麼,原本的HTTP1.x怎麼辦,這個問題其實不用擔心,HTTP2.0完全相容HTTP1.x的語意,對於不支援HTTP2.0的瀏覽器,NGINX會自動向下相容的。
●本文編號328,以後想閱讀這篇文章直接輸入328即可
●輸入m獲取文章目錄
前端開發
更多推薦《18個技術類微信公眾號》
涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。