天天看點

從發出http請求到伺服器響應過程

作者:艾西ONEPIECE

從發出http請求到伺服器響應過程

從發出http請求到伺服器響應過程

浏覽器輸入url經曆圖

分析過程:

1.使用者輸入url,浏覽器内部代碼将url進行拆分解析

從發出http請求到伺服器響應過程

url解析圖

舉個例子:

https://xxx.xxxxxx.xxx/article/123456.htm

其中 “xxx.xxxxxx.xxx” 表示這台伺服器,後面的/article/123456.htm

表示我們請求的檔案路徑。但是這個路徑是相對路徑,是以web伺服器根目錄為起始目錄的。

從發出http請求到伺服器響應過程

是以一個 URL 實際上對應Web伺服器裡的一個檔案資源。如果沒有輸入路徑名,例如隻輸入 “xxx.xxxxxx.xxx” ,表示通路事先設定的預設檔案,常見的有 /index.html 、 /default.html 等等。

對 URL 進行解析後,浏覽器确定了 Web 伺服器和檔案名,接下來就是根據這些資訊來構造 HTTP 請求封包。HTTP消息格式如圖:

從發出http請求到伺服器響應過程

域名解析過程

浏覽器解析 URL 并生成 HTTP 資料結構後,在發給伺服器之前,還需要查詢域名對應的 IP 位址,因為作業系統發送消息時,必須提供通信對象的 IP 位址。

DNS 伺服器就是專門儲存 域名與 IP 的對應關系,負責解析域名的伺服器 。注意:很多教材都說IP位址不友善記憶,是以才有了域名。其實域名不僅僅是友善記憶,他還有更重要的作用,比如用域名就可以實作一台伺服器同時搭建多個網站而共用一個IP。

域名是用句點來分隔的,比如 www.xxxxxx.com,這裡的句點代表了不同層級的劃分。在域名中,越靠右的位置表示其層級越高。

可能因為域名是外國人定義的,是以思維和中國人相反。比如表示一個地點,外國喜歡按照從小到大的順序說(如 XX 街道 XX 區 XX 市 XX 省),而中國喜歡按從大到小的順序(如 XX 省 XX 市 XX 區 XX 街道)。

最右邊的是頂級域名,例如上面的 “.com” 。再下面是二級域名 xxxxxx.com。是以域名的層級關系是一個樹狀結構(域名和域名伺服器是兩個概念):

根 DNS 伺服器

頂級域 DNS 伺服器(com)

權威 DNS 伺服器(xxxxxx.com)

從發出http請求到伺服器響應過程

所有的 DNS 伺服器都有根域DNS 伺服器的資訊。這樣一來,任何 DNS 伺服器都可以找到根域 DNS 。是以,用戶端隻要能夠找到任意一台 DNS 伺服器,就可以通過它找到根域 DNS 伺服器,然後再一步步找到位于下層的某台目标 DNS 伺服器。

域名解析過程:

首先查找電腦上的DNS緩存,如果有則解析完畢。否則進入第2步;

用戶端向本地DNS伺服器(可以在網絡屬性看到,一般是路由器自動設定,也可也手動設定)發送一個DNS請求,詢問 xxx.xxxxxx.com的IP位址。本地DNS收到後,如果緩存裡有,則直接傳回對應的IP位址。否則第3步;

本地DNS向根DNS發送請求,詢問 xxx.xxxxxx.com 的IP位址。根DNS收到後,發現是.com結尾的,便傳回.com頂級DNS的位址給本地DNS。本地DNS收到後,向.com頂級DNS發起請求,詢問xxx.xxxxxx.com的位址。頂級DNS傳回負責xxx.xxxxxx域名的權威DNS位址。本地DNS于是向權威DNS請求,權威DNS查詢後傳回對應的IP位址。

本地DNS收到後,把結果傳回給用戶端,再緩存起來。

我們再看下解析過程圖解:

從發出http請求到伺服器響應過程

3.浏覽器費了一頓周折終于拿到了伺服器IP,接下來就是網絡通信(過程如下圖),分層由高到低分别為:應用層、傳輸層、網絡層、資料鍊路層。發送端從應用層往下走,接收端從資料鍊路層往上走

從發出http請求到伺服器響應過程

首先:應用層用戶端發送HTTP請求

HTTP請求包括請求報頭和請求主體兩個部分,其中請求報頭包含了至關重要的資訊,包括請求的方法(GET / POST)、目标url、遵循的協定(http / https / ftp…),傳回的資訊是否需要緩存,以及用戶端是否發送cookie等。

從發出http請求到伺服器響應過程

請求封包

然後:傳輸層TCP傳輸封包

位于傳輸層的TCP協定為傳輸封包提供可靠的位元組流服務。它為了友善傳輸,将大塊的資料分割成以封包段為機關的資料包進行管理,并為它們編号,友善伺服器接收時能準确地還原封包資訊。TCP協定通過“三次握手”等方法保證傳輸的安全可靠。

用戶端發送一個帶有SYN标志的資料包給服務端,在一定的延遲時間内等待接收的回複。服務端收到後,回傳一個帶有SYN/ACK标志的資料包以示傳達确認資訊,最後用戶端再回傳一個帶ACK标志的資料包,代表握手結束,連接配接成功。

SYN (Synchronize Sequence Numbers)同步序列編号

ACK (Acknowledgement)确認字元

下圖也可以這麼了解:

用戶端:“你好,在家不,有你信件。”---SYN

服務端:“在的。”-----SYN/ACK

用戶端:“好嘞。”-----ACK

從發出http請求到伺服器響應過程

接着:網絡層IP協定查詢MAC位址

IP協定的作用是把TCP分割好的各種資料包傳送給接收方。而要保證确實能傳到接收方還需要接收方的MAC位址,也就是實體位址。IP位址和MAC位址是一一對應的關系,一個網絡裝置的IP位址可以更換,但是MAC位址一般是固定不變的。ARP協定可以将IP位址解析成對應的MAC位址。當通信的雙方不在同一個區域網路時,需要多次中轉才能到達最終的目标,在中轉的過程中需要通過下一個中轉站的MAC位址來搜尋下一個中轉目标。

資料到達資料鍊路層

在找到對方的MAC位址後,就将資料發送到資料鍊路層傳輸。這時,用戶端發送請求的階段結束

再次:伺服器接收資料

接收端的伺服器在鍊路層接收到資料包,再層層向上直到應用層。這過程中包括在運輸層通過TCP協定将分段的資料包重新組成原來的HTTP請求封包。

伺服器響應請求

服務接收到用戶端發送的HTTP請求後,查找用戶端請求的資源,并傳回響應封包,響應封包中包括一個重要的資訊——狀态碼。狀态碼由三位數字組成,

其中比較常見的是200 OK表示請求成功。

301表示永久重定向,即請求的資源已經永久轉移到新的位置。在傳回301狀态碼的同時,響應封包也會附帶重定向的url,用戶端接收到後将http請求的url做相應的改變再重新發送。

404 not found 表示用戶端請求的資源找不到。

最後: 伺服器傳回相應檔案

伺服器端收到請求後的由web伺服器(準确說應該是http伺服器)處理請求,諸如Apache、Ngnix、IIS等。web伺服器解析使用者請求,知道了需要排程哪些資源檔案,再通過相應的這些資源檔案處理使用者請求和參數,并調用資料庫資訊,最後将結果通過web伺服器傳回給浏覽器用戶端。

伺服器有自己的MVC 結構(如下圖)

從發出http請求到伺服器響應過程
從發出http請求到伺服器響應過程

關閉TCP連接配接

為了避免伺服器與用戶端雙方的資源占用和損耗,當雙方沒有請求或響應傳遞時,任意一方都可以發起關閉請求。與建立TCP連接配接的3次握手類似,關閉TCP連接配接,需要4次握手。

從發出http請求到伺服器響應過程

4次握手

上圖可以這麼了解:

用戶端:“兄弟,我這邊沒資料要傳了,咱關閉連接配接吧。”----FIN

服務端:“收到,我看看我這邊有木有資料了。”----ACK

服務端:“兄弟,我這邊也沒資料要傳你了,咱可以關閉連接配接了。”----FIN

用戶端:“好嘞。”----ACK

4.頁面的渲染階段

流程:

解析HTML生成DOM樹。

解析CSS生成CSSOM規則樹。

将DOM樹與CSSOM規則樹合并在一起生成渲染樹。

周遊渲染樹開始布局,計算每個節點的位置大小資訊。

将渲染樹每個節點繪制到螢幕。

從發出http請求到伺服器響應過程

webkit渲染引擎流程

過程的重點:

渲染阻塞

當浏覽器遇到一個 script 标記時,DOM 建構将暫停,直至腳本完成執行,然後繼續建構DOM。每次去執行JavaScript腳本都會嚴重地阻塞DOM樹的建構,如果JavaScript腳本還操作了CSSOM,而正好這個CSSOM還沒有下載下傳和建構,浏覽器甚至會延遲腳本執行和建構DOM,直至完成其CSSOM的下載下傳和建構。

是以,script 标簽的位置很重要。實際使用時,可以遵循下面兩個原則:

CSS 優先:引入順序上,CSS 資源先于 JavaScript 資源。

JS置後:我們通常把JS代碼放到頁面底部,且JavaScript 應盡量少影響 DOM 的建構。

當解析html的時候,會把新來的元素插入dom樹裡面,同時去查找css,然後把對應的樣式規則應用到元素上,查找樣式表是按照從右到左的順序去比對的。

例如: div p {font-size: 16px},會先尋找所有p标簽并判斷它的父标簽是否為div之後才會決定要不要采用這個樣式進行渲染)。

是以,我們平時寫CSS時,盡量用id和class,千萬不要過渡層疊。

渲染樹繪制

在繪制階段,周遊渲染樹,調用渲染器的paint()方法在螢幕上顯示其内容。渲染樹的繪制工作是由浏覽器的UI後端元件完成的。

reflow與repaint:

根據渲染樹布局,計算CSS樣式,即每個節點在頁面中的大小和位置等幾何資訊。HTML預設是流式布局的,CSS和js會打破這種布局,改變DOM的外觀樣式以及大小和位置。這時就要提到兩個重要概念:replaint和reflow。

replaint:螢幕的一部分重畫,不影響整體布局,比如某個CSS的背景色變了,但元素的幾何尺寸和位置不變。

reflow: 意味着元件的幾何尺寸變了,我們需要重新驗證并計算渲染樹。是渲染樹的一部分或全部發生了變化。這就是Reflow,或是Layout。

是以我們應該盡量減少reflow和replaint,我想這也是為什麼現在很少有用table布局的原因之一。

display:none 會觸發 reflow,visibility: hidden屬性并不算是不可見屬性,它的語義是隐藏元素,但元素仍然占據着布局空間,它會被渲染成一個空框,是以visibility:hidden 隻會觸發 repaint,因為沒有發生位置變化。

有些情況下,比如修改了元素的樣式,浏覽器并不會立刻 reflow 或 repaint 一次,而是會把這樣的操作積攢一批,然後做一次 reflow,這又叫異步 reflow 或增量異步 reflow。

有些情況下,比如 resize 視窗,改變了頁面預設的字型等。對于這些操作,浏覽器會馬上進行 reflow。

繼續閱讀