從開發&運維角度方面來看,總體來說分為以下幾個過程:
- DNS 解析:將域名解析成 IP 地址
- TCP 連線:TCP 三次握手
- 傳送 HTTP 請求
- 伺服器處理請求並返回 HTTP 報文
- 瀏覽器解析渲染頁面
- 斷開連線:TCP 四次揮手
一、什麼是URL?
URL(Uniform Resource Locator),統一資源定位符,用於定位網際網路上資源,俗稱網址。
scheme: // host.domain:port / path / filename ? abc = 123 # 456789
scheme - 定義因特網服務的型別。常見的協議有 http、https、ftp、file,
其中最常見的型別是 http,而 https 則是進行加密的網路傳輸。
host - 定義域主機(http 的預設主機是 www)
domain - 定義因特網域名,比如 baidu.com
port - 定義主機上的埠號(http 的預設埠號是 80)
path - 定義伺服器上的路徑(如果省略,則文件必須位於網站的根目錄中)。
filename - 定義文件/資源的名稱
query - 即查詢引數
fragment - 即 # 後的hash值,一般用來定位到某個位置
二、DNS域名解析
在瀏覽器輸入網址後,首先要經過域名解析,因為瀏覽器並不能直接透過域名找到對應的伺服器,而是要透過 IP 地址。
- IP 地址
IP 地址是指網際網路協議地址,是 IP Address 的縮寫。IP 地址是 IP 協議提供的一種統一的地址格式,
它為網際網路上的每一個網路和每一臺主機分配一個邏輯地址,以此來遮蔽實體地址的差異。
- 什麼是域名解析
DNS 協議提供透過域名查詢 IP 地址,或逆向從 IP 地址反查域名的服務。
DNS 是一個網路伺服器,我們的域名解析簡單來說就是在 DNS 上記錄一條資訊記錄。
- 瀏覽器如何透過域名去查詢 URL 對應的 IP 呢?
DNS域名解析分為遞迴查詢和迭代查詢兩種方式,現一般為迭代查詢。
DNS的最佳化與應用
- DNS快取
DNS存在著多級快取,從離瀏覽器的距離排序的話,有以下幾種: 瀏覽器快取,系統快取,路由器快取,IPS伺服器快取,根域名伺服器快取,頂級域名伺服器快取,主域名伺服器快取。
- DNS負載均衡
(DNS重定向) DNS負載均衡技術的實現原理是在DNS伺服器中為同一個主機名配置多個IP地址,在應答DNS查詢時, DNS伺服器對每個查詢將以DNS檔案中主機記錄的IP地址按順序返回不同的解析結果,將客戶端的訪問 引導到不同的機器上去,使得不同的客戶端訪問不同的伺服器,從而達到負載均衡的目的。
- 大家耳熟能詳的CDN(Content Delivery Network)就是利用DNS的重定向技術,DNS伺服器會返回一個跟
使用者最接近的點的IP地址給使用者,CDN節點的伺服器負責響應使用者的請求,提供所需的內容。 - dns-prefetch
DNS Prefetch 是一種 DNS 預解析技術。當你瀏覽網頁時,瀏覽器會在載入網頁時對網頁中的域名進行解析快取,這樣在你單擊當前網頁中的連線時就無需進行 DNS 的解析,減少使用者等待時間,提高使用者體驗。
OSI參考模型與TCP/IP四層模型
三、TCP三次握手
- 客戶端傳送一個帶 SYN=1,Seq=X 的資料包到伺服器埠
(第一次握手,由瀏覽器發起,告訴伺服器我要傳送請求了)
- 伺服器發回一個帶 SYN=1, ACK=X+1, Seq=Y 的響應包以示傳達確認資訊
(第二次握手,由伺服器發起,告訴瀏覽器我準備接受了,你趕緊傳送吧)
- 客戶端再回傳一個帶 ACK=Y+1, Seq=Z 的資料包,代表“握手結束”
(第三次握手,由瀏覽器傳送,告訴伺服器,我馬上就發了,準備接受吧)
四、傳送 HTTP 請求
TCP 三次握手結束後,開始傳送 HTTP 請求報文。
為避免篇幅過長,http協議、快取等相關內容請參閱:
從HTTP到WEB快取
五、伺服器處理請求並返回 HTTP 報文
每臺伺服器上都會安裝處理請求的應用——Web server。常見的web server產品有apache、nginx、IIS、Lighttpd等。
假裝我是一個傳統的MVC模型,RD同學請無視
參考 前端進階面試題詳細解答
六、瀏覽器解析渲染頁面
瀏覽器的主要構成
使用者介面 (User Interface) - 包括位址列、後退/前進按鈕、書籤目錄等,也就是你所看到的除了用來顯示你所請求頁面的主視窗之外的其他部分
瀏覽器引擎 (Browser Engine) - 用來查詢及操作渲染引擎的介面
渲染引擎 (Rendering Engine) - 用來顯示請求的內容,例如,如果請求內容為html,它負責解析html及css,並將解析後的結果顯示出來
網路 (Networking) - 用來完成網路呼叫,例如http請求,它具有平臺無關的介面,可以在不同平臺上工作
JS直譯器 (JS Interpreter) - 用來解釋執行JS程式碼
UI後端 (UI Backend) - 用來繪製類似組合選擇框及對話方塊等基本元件,具有不特定於某個平臺的通用介面,底層使用作業系統的使用者介面
資料儲存 (DB Persistence) - 屬於持久層,瀏覽器需要在硬碟中儲存類似cookie的各種資料,HTML5定義了web database技術,這是一種輕量級完整的客戶端儲存技術
1.多程式的瀏覽器
瀏覽器是多程式的,有一個主控程式,以及每一個tab頁面都會新開一個程式(某些情況下多個tab會合並程式),
程式可能包括主控程式,外掛程式,GPU,tab頁(瀏覽器核心)等等
- Browser程式:瀏覽器的主程式(負責協調、主控),只有一個
- 第三方外掛程式:每種型別的外掛對應一個程式,僅當使用該外掛時才建立
- GPU程式:最多一個,用於3D繪製
- 瀏覽器渲染程式(核心):預設每個Tab頁面一個程式,互不影響,控制頁面渲染,指令碼執行,事件處理等(有時候會最佳化,如多個空白tab會合併成一個程式)
2.多執行緒的瀏覽器核心
每一個tab頁面可以看作是瀏覽器核心程式,然後這個程式是多執行緒的,它有幾大類子執行緒:
- GUI執行緒
- JS引擎執行緒
- 事件觸發執行緒
- 定時器執行緒
- 網路請求執行緒
瀏覽器核心拿到內容後,渲染步驟大致可以分為以下幾步:
1. 解析HTML,構建DOM樹
2. 解析CSS,生成CSS規則樹
3. 合併DOM樹和CSS規則,生成render樹
4. 佈局render樹(Layout/reflow),負責各元素尺寸、位置的計算
5. 繪製render樹(paint),繪製頁面畫素資訊
以webkit核心為例
1. HTML解析,構建DOM
簡單的理解,這一步的流程是這樣的:瀏覽器解析HTML,構建DOM樹。
解析HTML到構建出DOM當然過程可以簡述如下:
Bytes → characters → tokens → nodes → DOM
其中比較關鍵的幾個步驟
1. Conversion轉換:瀏覽器將獲得的HTML內容(Bytes)基於他的編碼轉換為單個字元
2. Tokenizing分詞:瀏覽器按照HTML規範標準將這些字元轉換為不同的標記token。每個token都有自己獨特的含義以及規則集
3. Lexing詞法分析:分詞的結果是得到一堆的token,此時把他們轉換為物件,這些物件分別定義他們的屬性和規則
4. DOM構建:因為HTML標記定義的就是不同標籤之間的關係,這個關係就像是一個樹形結構一樣
例如:body物件的父節點就是HTML物件,然後段略p物件的父節點就是body物件
2. 解析CSS,生成CSS規則樹
同理,CSS規則樹的生成也是類似。
Bytes → characters → tokens → nodes → CSSOM
3. 合併DOM樹和CSS規則,生成render樹
當DOM樹和CSSOM都有了後,就要開始構建渲染樹了
一般來說,渲染樹和DOM樹相對應的,但不是嚴格意義上的一一對應,因為有一些不可見的DOM元素不會插入到渲染樹中,如head這種不可見的標籤或者display: none等
4. 佈局render樹(Layout/Reflow),負責各元素尺寸、位置的計算
佈局:透過渲染樹中渲染物件的資訊,計算出每一個渲染物件的位置和尺寸。
5. 繪製render樹(Paint),繪製頁面畫素資訊
繪製階段,系統會遍歷呈現樹,並呼叫呈現器的“paint”方法,將呈現器的內容顯示在螢幕上。
這張圖片中重要的四個步驟
1. 計算CSS樣式
2. 構建渲染樹
3. 佈局,主要定位座標和大小,是否換行,各種position overflow z-index屬性
4. 繪製,將影像繪製出來
- Layout,也稱為Reflow,即迴流。一般意味著元素的內容、結構、位置或尺寸發生了變化,需要重新計算樣式和渲染樹
- Repaint,即重繪。意味著元素髮生的改變只是影響了元素的一些外觀之類的時候(例如,背景色,邊框顏色,文字顏色等),此時只需要應用新樣式繪製這個元素就可以了
七、斷開連線
當資料傳送完畢,需要斷開 tcp 連線,此時發起 tcp 四次揮手。
- 發起方向被動方傳送報文,Fin、Ack、Seq,表示已經沒有資料傳輸了。並進入 FIN_WAIT_1 狀態。
(第一次揮手:由瀏覽器發起的,傳送給伺服器,我請求報文傳送完了,你準備關閉吧)
- 被動方傳送報文,Ack、Seq,表示同意關閉請求。此時主機發起方進入 FIN_WAIT_2 狀態。
(第二次揮手:由伺服器發起的,告訴瀏覽器,我請求報文接受完了,我準備關閉了,你也準備吧)
- 被動方向發起方傳送報文段,Fin、Ack、Seq,請求關閉連線。並進入 LAST_ACK 狀態。
(第三次揮手:由伺服器發起,告訴瀏覽器,我響應報文傳送完了,你準備關閉吧)
- 發起方向被動方傳送報文段,Ack、Seq。然後進入等待 TIME_WAIT 狀態。被動方收到發起方的報文段以後關閉連線。發起方等待一定時間未收到回覆,則正常關閉。
(第四次揮手:由瀏覽器發起,告訴伺服器,我響應報文接受完了,我準備關閉了,你也準備吧)