瀏覽器工作原理與實踐(三)之HTTP請求流程


Set-Cookie: SERVERID=1fa1f330efedec1559b3abbcb6e30f50|1587649463|1587649463;Path=/

 

Cache-Control:Max-age=2000

 

GET /index.html HTTP1.1

 

在瀏覽器實踐與原理(二)之TCP協議介紹了TCP協議是如何保證數據傳輸完成性的。

一個TCP鏈接包括了了建立連接、傳輸數據和斷開連接三個階段

HTTP協議是建立在TCP連接基礎之上的,HTTP是一種允許瀏覽器向服務器獲取資源的協議是 Web的基礎,通常由瀏覽器發起請求,用來獲取不同類型的文件,例如HTML、CSS、JS、圖片、文件、視頻等。

你是否有過下面這些疑問

  1. 為什么第一次打開一個站點速度很慢,當再次訪問這個站點速度就很快了
  2. 當登陸過一個網址之后,下次再訪問該站點就已經處於登錄狀態了

 這是怎么做到的呢?在今天這篇文章中,將通過分析一個HTTP請求過程中的每一步狀態來了解完整的HTTP請求

瀏覽器端發起HTTP請求流程

如果你在瀏覽器地址欄里輸入極客時間網站的地址:www.taobao.com

接下來瀏覽器會完成哪些動作呢?一步一步來追蹤一下

1.構建請求

首先,瀏覽器構建請求行信息(如下所示),構建好后,瀏覽器准備發起網絡請求

GET /index.html HTTP1.1

 2.查找緩存

 在真正發起網絡請求前,瀏覽器會現在瀏覽器緩存中查詢是否有要請求的文件。其中,瀏覽器緩存是一種在本地保存資源富文本,以供下次請求時直接使用的技術

 當瀏覽器發現請求的資源已經在瀏覽器緩存中存有副本,它會攔截請求,返回該資源的副本,並直接結束請求,而不會去資源服務器重新下載。這的好處:

  • 緩解服務器壓力,提升性能(獲取資源的耗時更短了)
  • 對於網站來說,緩存是實現快速資源加載的重要組成部分

當然查找失敗會進入網絡請求

3.准備IP地址和端口 

在了解網絡請求之前,我們需要先看看HTTP和TCP的關系。

因為瀏覽器使用HTTP作為應用層協議,用來封裝請求的文本信息;並使用TCP/IP作傳輸協議將它發送到網絡上,所以在HTTP開始工作之前,瀏覽器需要通過TCP與服務器建立連接,也就是說HTTP的內容是通過TCP的傳輸數據階段來實現的

 

看上圖,你可以思考這么一連串問題

  • HTTP網絡請求的第一步是做什么呢?結合上圖看是服務器和TCP鏈接
  • 那建立連接的信息都有了嗎?在瀏覽器實踐與原理(二)之TCP協議說到建立TCP連接的第一步需要准備IP和端口號
  • 那么怎么獲取IP和端口號呢?這得看看我們現在有什么,我們有一個URL地址,是否可以利用URL地址來獲取IP和端口信息呢

 數據包是通過IP地址傳輸給接收方的,由於IP地址是數字標識如:39.106.233.176,難以記憶,但使用域名(www.xxx.com)就方便多了,所以基於這個需求又出現了一個服務,

負責把域名和IP地址做一一映射關系,這套域名映射為IP的系統就叫做域名系統,簡稱DNS

 所以,你會發現第一步瀏覽器會請求DNS返回域名對應的IP。瀏覽器還提供了DNS數據緩存服務,如果某個域名已經解析過了,瀏覽器會緩存解析結果,供下次使用

 拿到IP之后,接下來基因獲取端口號了,如果URL沒有特別指明端口號,那么HTTP協議默認是80端口。

4.等待TCP隊列

 准備好端口和IP地址,下一步就是建立TCP鏈接了嗎?

答案是不闊以哦,Chrome有個機制,同一個域名同時最多只能建立6個TCP連接,如果在同一個域名下同時有10個請求發生,那么其中四個請求會進入排隊等待狀態,直至請求完成

如果請求數小於6,建立TCP連接

 5.建立TCP連接

排隊結束后,可以快樂的和服務器握手了,在HTTP工作之前,瀏覽器先通過TCP建立連接

 6.發送HTTP請求

 一旦建立了連接,瀏覽器就可以和服務器進行通信,而HTTP中的數據正是在這個通信過程中傳輸

可以結合下圖理解瀏覽器如何發送請求信息給服務器的 

 

  • 首先,瀏覽器會像服務器發送請求行,它包括了請求方法、請求URL和HTTP版本協議,發送請求行,就是告訴瀏覽器需要什么資源,最常用的是Get。比如,直接在瀏覽器地址欄輸入極客時間的域名(https://time.geekbang.org/)就告訴瀏覽器要Get首頁資源。
  • 另外一個常用的請求方法是POST,它用於發送一些數據給服務器,比如一個登陸網站,使用post方法,瀏覽器要准備數據給服務器,這里准備的數據通過請求體發送
  • 在瀏覽器發送請求命令之后,還要以請求頭形式發送一些其他信息,把瀏覽器的一些基礎信息告訴服務器,包括了瀏覽器的操作系統、瀏覽器內核等信息,以及當前請求的域名信息,瀏覽器的cookie等。

 服務器處理HTTP請求流程

歷經千辛萬苦,HTTP的請求信息終於被送達了服務器,接下來,服務器會根據瀏覽器的請求信息准備相應內容

1.返回請求 

curl -i https://time.geekbang.org/

 

 這里加上了 i 是為了返回響應行、響應頭和響應體的數據,返回的結果如下圖:

 首先,服務器會返回響應行,包括協議版本和狀態碼

但不是所有的請求都會被服務器成功處理的,那么一些無法處理或者處理出錯的信息,怎么辦呢?

服務器會通過響應行的狀態碼來告訴瀏覽器它的處理結果,比如

  • 最常用的狀態碼是200,表示處理成功
  • 如果沒有找到頁面返回404

隨后,服務器也會隨同響應向瀏覽器發送響應頭。響應頭包含了服務器自身的一些信息,比如服務器生成返回數據的時間、返回的數據類型,以及服務器在客戶端保存的Cookie等信息。

發送完響應頭后,服務器可以繼續發送響應體的數據

2.斷開連接

 通常情況下,一旦服務器向客戶端返回了請求數據,就關閉TCP連接,不過瀏覽器或者服務器在其頭信息加入了

Connection: keep-alive

 那么TCP連接在發送后仍保持打開狀態,這樣瀏覽器就可以繼續通過同一個TCP連接發送請求。

保持TCP連接可以省去下次請求時需要建立連接的時間,提升資源加載速度

比如同一個Web頁面中內嵌的圖片都來自同一個Web站點,如果初始化了一個持久連接,就可以復用該連接,以請求其他資源。

 3.重定向

到這里似乎請求快結束了,不過還有一只能情況需要了解一下,比如你在瀏覽器中打開geekbang.org后,會發現最終打開的地址是https://www.geekbang.org/

這兩個URL之所以不一樣,是因為涉及到了一個重定向操作,在控制台輸入

curl -I geekbang.org 

注意這里輸入的參數是-I,和-i不一樣,-I是只需要獲取響應頭和響應數據,不需要獲取響應體數據

 

  • 從上圖可以看到,響應行返回的狀態碼是301,狀態301是告訴瀏覽器,我需要重定向到另外一個地址
  • 需要重定向的網址正是包含在響應頭的Location字段中的地址,並使用改地址重新導航

注:不過也不要認為這種跳轉是必然的,如果你打開 https://12306.cn會發現這個站點是打不開的,因為12306的服務器並沒有處理跳轉操作所以需要輸入完整的https://www.12306.cn/才能打開頁面

 問題解答

為什么很多站點打開第二次速度會很快?

如果打開第二次速度會很快,主要原因是第一次加載過程中,緩存了一些耗時的數據

哪些數據會被緩存呢?

從上面介紹請求路徑看, DNS緩存和頁面緩存資源這兩塊數據是會被瀏覽器緩存的

看下瀏覽器資源緩存,如下圖

首先,來看下服務器是通過什么方式讓瀏覽器緩存數據的?

從上圖可以看出第一次請求可以看出,當服務器返回HTTP響應頭給瀏覽器時,瀏覽器通過響應頭中的Cache-Control字段來設置一個緩存的過期時長,而這個時長是通過Max-age參數來設置的,如上圖設置緩存過期時間是2秒 

Cache-Control:Max-age=2000

 這也就意味着,在該緩存資源還未過期的情況下,如果再次請求資源,會直接返回緩存中的資源給瀏覽器

 但如果資源過期了,瀏覽器會繼續發起網絡請求,並且在HTTP請求頭帶上

If-None-Match:"4f80f-13c3alxb12a"

 服務器收到請求后,會根據If-None-Match的值來判斷請求的資源是否有更新

  • 如果沒有更新,就返回304狀態碼,相當於告訴瀏覽器:“z這個緩存可以繼續使用,這次就不重復發送數據給你了”
  • 如果資源有更新,服務器就直接返回最新資源給瀏覽器

 簡單來說,瀏覽器第二次訪問能夠秒開,是因為這些網站把很多資源都緩存在了本地,瀏覽器緩存直接使用本地副本回應請求,不會產生真正的網絡請求

2.登錄狀態是如何保持的?

  • 用戶打開登錄界面,在登錄框填入用戶名和密碼,點擊登錄按鈕,調用post提交登錄信息給服務端
  • 服務器收到瀏覽器提交的信息之后,查詢后台,驗證用戶信息是否正確,如果正確,會生成一段表示用戶身份的字符串,並把該字符串寫到響應頭的Set-cookie字段,發送給瀏覽器 
  • 瀏覽器在接受到服務器響應后,開始解析響應頭,如果遇到響應頭含義Set-Cookie字段的情況,瀏覽器會把這個字段信息保存到本地
  • 當用戶再次訪問時瀏覽器會發起HTTP請求,但在發起請求之前,瀏覽器會之前保存的Cookie數據,並把數據寫到請求頭里的Cookie字段里
  • 服務器在收到HTTP請求頭數據之后,就會查找包含用戶Cookie的信息,然后查詢后台,判斷用戶已是登錄狀態,生成有該用戶的頁面數據,發送給瀏覽器
  • 瀏覽器在接收到該含有當前用戶的頁面數據后,就可以正確展示登錄狀態信息了
Set-Cookie: SERVERID=1fa1f330efedec1559b3abbcb6e30f50|1587649463|1587649463;Path=/

 通過上面這個流程可以知道瀏覽器頁面狀態是通過Cookie實現的

 如圖

 

簡單地說,如果服務器端發送的響應頭內有 Set-Cookie 的字段,那么瀏覽器就會將該字段的內容保持到本地當下次客戶端再往該服務器發送請求時,客戶端會自動在請求頭中加入 Cookie 值后再發送出去。服務器端發現客戶端發送過來的 Cookie 后,會去檢查究竟是從哪一個客戶端發來的連接請求,然后對比服務器上的記錄,最后得到該用戶的狀態信息。

下圖幫你理解 HTTP請求示意圖

 

在 PDFlux 中打開
無數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM