這塊的文章網(wǎng)上也是比較多的,但大多數(shù)都是講解DOM樹的渲染,對于頁面從請求到展示的詳細流程講解還是比較少的,而且有些說的也不容易理解,下面我將以圖文結合的形式給大伙講講。
DNS查詢
作用
DNS 的作用就是通過域名查詢到具體的 IP。
背景
因為 IP 存在數(shù)字和英文的組合(IPv6),很不利于人類記憶,所以就出現(xiàn)了域名。你可以把域名看成是某個 IP 的別名,DNS 就是去查詢這個別名的真正名稱是什么。
過程
在 TCP 握手之前就已經(jīng)進行了 DNS 查詢,這個查詢是操作系統(tǒng)自己做的。當你在瀏覽器中想訪問 www.test.com 時,會進行一下操作:
- 操作系統(tǒng)會首先在本地緩存中查詢 IP
- 沒有的話會去系統(tǒng)配置的 DNS 服務器中查詢
- 如果這時候還沒得話,會直接去 DNS 根服務器查詢,這一步查詢會找出負責 com 這個一級域名的服務器
- 然后去該服務器查詢 baidu 這個二級域名
- 接下來三級域名的查詢其實是我們配置的,你可以給 www 這個域名配置一個 IP,然后還可以給別的三級域名配置一個 IP
以上介紹的是 DNS 迭代查詢,還有種是遞歸查詢,區(qū)別就是前者是由客戶端去做請求,后者是由系統(tǒng)配置的 DNS 服務器做請求,得到結果后將數(shù)據(jù)返回給客戶端。
TCP握手
在進行完DNS解析之后,接下來就是 TCP 握手,應用層會下發(fā)數(shù)據(jù)給傳輸層,這里 TCP 協(xié)議會指明兩端的端口號,然后下發(fā)給網(wǎng)絡層。網(wǎng)絡層中的 IP 協(xié)議會確定 IP 地址,并且指示了數(shù)據(jù)傳輸中如何跳轉路由器。然后包會再被封裝到數(shù)據(jù)鏈路層的數(shù)據(jù)幀結構中,最后就是物理層面的傳輸了。
TCP建立連接的三次握手
首先假設主動發(fā)起請求的一端稱為客戶端,被動連接的一端稱為服務端。不管是客戶端還是服務端,TCP 連接建立完后都能發(fā)送和接收數(shù)據(jù),所以 TCP 是一個全雙工的協(xié)議。
起初,兩端都為 CLOSED 狀態(tài)。在通信開始前,雙方都會創(chuàng)建 TCB。 服務器創(chuàng)建完 TCB 后便進入 LISTEN 狀態(tài),此時開始等待客戶端發(fā)送數(shù)據(jù)。
第一次握手
客戶端向服務端發(fā)送連接請求報文段。該報文段中包含自身的數(shù)據(jù)通訊初始序號。請求發(fā)送后,客戶端便進入 SYN-SENT 狀態(tài)。
第二次握手
服務端收到連接請求報文段后,如果同意連接,則會發(fā)送一個應答,該應答中也會包含自身的數(shù)據(jù)通訊初始序號,發(fā)送完成后便進入 SYN-RECEIVED 狀態(tài)。
第三次握手
當客戶端收到連接同意的應答后,還要向服務端發(fā)送一個確認報文。客戶端發(fā)完這個報文段后便進入 ESTABLISHED 狀態(tài),服務端收到這個應答后也進入 ESTABLISHED 狀態(tài),此時連接建立成功。
第三次握手中可以包含數(shù)據(jù),通過快速打開(TFO)技術就可以實現(xiàn)這一功能。其實只要涉及到握手的協(xié)議,都可以使用類似 TFO 的方式,客戶端和服務端存儲相同的 cookie,下次握手時發(fā)出 cookie 達到減少 RTT 的目的。
TLS握手
TLS 協(xié)議位于傳輸層之上,應用層之下,主要是對HTTP請求進行加密。首次進行 TLS 協(xié)議傳輸需要兩個 RTT ,接下來可以通過 Session Resumption 減少到一個 RTT。
TLS 握手過程如下圖:
- 客戶端發(fā)送一個隨機值以及需要的協(xié)議和加密方式。
- 服務端收到客戶端的隨機值,自己也產生一個隨機值,并根據(jù)客戶端需求的協(xié)議和加密方式來使用對應的方式,并且發(fā)送自己的證書(如果需要驗證客戶端證書需要說明)
- 客戶端收到服務端的證書并驗證是否有效,驗證通過會再生成一個隨機值,通過服務端證書的公鑰去加密這個隨機值并發(fā)送給服務端,如果服務端需要驗證客戶端證書的話會附帶證書
- 服務端收到加密過的隨機值并使用私鑰解密獲得第三個隨機值,這時候兩端都擁有了三個隨機值,可以通過這三個隨機值按照之前約定的加密方式生成密鑰,接下來的通信就可以通過該密鑰來加密解密
通過以上步驟可知,在 TLS 握手階段,兩端使用非對稱加密的方式來通信,但是因為非對稱加密損耗的性能比對稱加密大,所以在正式傳輸數(shù)據(jù)時,兩端使用對稱加密的方式通信。
負載均衡服務器
數(shù)據(jù)在進入服務端之前,可能還會先經(jīng)過負責負載均衡的服務器,它的作用就是將請求合理的分發(fā)到多臺服務器上,這時假設服務端會響應一個 html 文件。
首先瀏覽器會判斷狀態(tài)碼是什么,如果是 200 那就繼續(xù)解析,如果 400 或 500 的話就會報錯,如果 300 的話會進行重定向,這里會有個重定向計數(shù)器,避免過多次的重定向,超過次數(shù)也會報錯。
瀏覽器解析
瀏覽器開始解析文件,如果是 gzip 格式的話會先解壓一下,然后通過文件的編碼格式去解碼文件。
文件解碼成功后會正式開始渲染流程,先會根據(jù) HTML 構建 DOM 樹,有 css 的話會去構建 CSSOM 樹。如果遇到 script 標簽的話,會判斷是否存在 async 或者 defer ,前者會并行進行下載并執(zhí)行 JS,后者會先下載文件,然后等待 HTML 解析完成后順序執(zhí)行。
如果以上都沒有,就會阻塞住渲染流程直到 JS 執(zhí)行完畢。遇到文件下載的會去下載文件,這里如果使用 HTTP/2 協(xié)議的話會極大的提高多圖的下載效率。
CSSOM 樹和 DOM 樹構建完成后會開始生成 Render 樹,這一步就是確定頁面元素的布局、樣式等等諸多方面的東西
在生成 Render 樹的過程中,瀏覽器就開始調用 GPU 繪制,合成圖層,將內容顯示在屏幕上了。
總結
總的來說,今天這篇文章主要是帶著大家從 DNS 查詢開始到渲染出畫面完整的了解一遍過程,里面涉及到DNS、HTTP、TLS、負載均衡和瀏覽器渲染等等內容,算不上非常詳細,但如果面試的時候能說出來這些,相信面試官也會對你刮目相看的。