1. DNS域名解析
當(dāng)我們開(kāi)始在瀏覽器中輸入網(wǎng)址的時(shí)候懈万,瀏覽器其實(shí)就已經(jīng)在智能的匹配可能得 url 了。它會(huì)從歷史記錄,書(shū)簽等地方帝璧,找到已經(jīng)輸入的字符串可能對(duì)應(yīng)的 url ,找到同輸入的地址很匹配的項(xiàng)湿刽,然后給出智能提示的烁,讓你可以補(bǔ)全 url地址。用戶(hù)還沒(méi)有按下 enter 鍵诈闺, 瀏覽器已經(jīng)開(kāi)始使用 DNS 預(yù)取技術(shù)解析該域名了渴庆。
本地查找是一個(gè)遞歸查找的過(guò)程,從瀏覽器緩存中查找->本地的hosts文件查找->找本地DNS解析器緩存查找->本地DNS服務(wù)器查找雅镊,這個(gè)過(guò)程中任何一步找到了都會(huì)結(jié)束查找流程襟雷。
如果本地DNS服務(wù)器無(wú)法查詢(xún)到,則根據(jù)本地DNS服務(wù)器設(shè)置的轉(zhuǎn)發(fā)器進(jìn)行查詢(xún)仁烹。若未用轉(zhuǎn)發(fā)模式耸弄,則迭代查找過(guò)程如下圖
結(jié)合起來(lái)的過(guò)程,可以用一個(gè)圖表示:
在查找過(guò)程中卓缰,有以下優(yōu)化點(diǎn):
DNS存在著多級(jí)緩存叙赚,從離瀏覽器的距離排序的話(huà)老客,有以下幾種: 瀏覽器緩存,系統(tǒng)緩存震叮,路由器緩存胧砰,IPS服務(wù)器緩存,根域名服務(wù)器緩存苇瓣,頂級(jí)域名服務(wù)器緩存尉间,主域名服務(wù)器緩存。
在域名和 IP 的映射過(guò)程中击罪,給了應(yīng)用基于域名做負(fù)載均衡的機(jī)會(huì)哲嘲,可以是簡(jiǎn)單的負(fù)載均衡,也可以根據(jù)地址和運(yùn)營(yíng)商做全局的負(fù)載均衡媳禁。
2. 建立TCP連接
首先眠副,判斷是不是https的,如果是竣稽,則HTTPS其實(shí)是HTTP + SSL / TLS 兩部分組成囱怕,也就是在HTTP上又加了一層處理加密信息的模塊。服務(wù)端和客戶(hù)端的信息傳輸都會(huì)通過(guò)TLS進(jìn)行加密毫别,所以傳輸?shù)臄?shù)據(jù)都是加密后的數(shù)據(jù)娃弓。
進(jìn)行三次握手,建立TCP連接岛宦。
??? 1.第一次握手:建立連接台丛。客戶(hù)端發(fā)送連接請(qǐng)求報(bào)文段砾肺,將SYN位置為1挽霉,Sequence Number為x;然后变汪,客戶(hù)端進(jìn)入SYN_SEND狀態(tài)炼吴,等待服務(wù)器的確認(rèn);
??? 2.第二次握手:服務(wù)器收到SYN報(bào)文段疫衩。服務(wù)器收到客戶(hù)端的SYN報(bào)文段,需要對(duì)這個(gè)SYN報(bào)文段進(jìn)行確認(rèn)荣德,設(shè)置Acknowledgment Number為x+1(Sequence Number+1)闷煤;同時(shí),自己還要發(fā)送SYN請(qǐng)求信息涮瞻,將SYN位置為1鲤拿,SequenceNumber為y;服務(wù)器端將上述所有信息放到一個(gè)報(bào)文段(即SYN+ACK報(bào)文段)中署咽,一并發(fā)送給客戶(hù)端近顷,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài)生音;
3.第三次握手:客戶(hù)端收到服務(wù)器的SYN+ACK報(bào)文段。然后將Acknowledgment Number設(shè)置為y+1窒升,向服務(wù)器發(fā)送ACK報(bào)文段缀遍,這個(gè)報(bào)文段發(fā)送完畢以后,客戶(hù)端和服務(wù)器端都進(jìn)入ESTABLISHED狀態(tài)饱须,完成TCP三次握手域醇。
SSL握手過(guò)程
4.第一階段 建立安全能力 包括協(xié)議版本 會(huì)話(huà)Id 密碼構(gòu)件 壓縮方法和初始隨機(jī)數(shù)
5.第二階段 服務(wù)器發(fā)送證書(shū) 密鑰交換數(shù)據(jù)和證書(shū)請(qǐng)求,最后發(fā)送請(qǐng)求-相應(yīng)階段的結(jié)束信號(hào)
6.第三階段 如果有證書(shū)請(qǐng)求客戶(hù)端發(fā)送此證書(shū) 之后客戶(hù)端發(fā)送密鑰交換數(shù)據(jù) 也可以發(fā)送證書(shū)驗(yàn)證消息
7.第四階段 變更密碼構(gòu)件和結(jié)束握手協(xié)議
ACK:此標(biāo)志表示應(yīng)答域有效蓉媳,就是說(shuō)前面所說(shuō)的TCP應(yīng)答號(hào)將會(huì)包含在TCP數(shù)據(jù)包中譬挚;有兩個(gè)取值:0和1,為1的時(shí)候表示應(yīng)答域有效酪呻,反之為0减宣。TCP協(xié)議規(guī)定,只有ACK=1時(shí)有效玩荠,也規(guī)定連接建立后所有發(fā)送的報(bào)文的ACK必須為1漆腌。
SYN(SYNchronization):在連接建立時(shí)用來(lái)同步序號(hào)。當(dāng)SYN=1而ACK=0時(shí)姨蟋,表明這是一個(gè)連接請(qǐng)求報(bào)文屉凯。對(duì)方若同意建立連接,則應(yīng)在響應(yīng)報(bào)文中使SYN=1和ACK=1. 因此, SYN置1就表示這是一個(gè)連接請(qǐng)求或連接接受報(bào)文眼溶。
FIN(finis)即完悠砚,終結(jié)的意思, 用來(lái)釋放一個(gè)連接堂飞。當(dāng) FIN = 1 時(shí)灌旧,表明此報(bào)文段的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢,并要求釋放連接绰筛。
發(fā)送HTTP請(qǐng)求枢泰,服務(wù)器處理請(qǐng)求,返回響應(yīng)結(jié)果
TCP連接建立后铝噩,瀏覽器就可以利用HTTP/HTTPS協(xié)議向服務(wù)器發(fā)送請(qǐng)求了衡蚂。服務(wù)器接受到請(qǐng)求,就解析請(qǐng)求頭骏庸,如果頭部有緩存相關(guān)信息如if-none-match與if-modified-since毛甲,則驗(yàn)證緩存是否有效,若有效則返回狀態(tài)碼為304具被,若無(wú)效則重新返回資源玻募,狀態(tài)碼為200.
這里有發(fā)生的一個(gè)過(guò)程是HTTP緩存,是一個(gè)骋蛔耍考的考點(diǎn)七咧,大致過(guò)程如圖:
關(guān)閉TCP連接
第一次分手:主機(jī)1(可以使客戶(hù)端跃惫,也可以是服務(wù)器端),設(shè)置Sequence Number和Acknowledgment Number艾栋,向主機(jī)2發(fā)送一個(gè)FIN報(bào)文段爆存;此時(shí),主機(jī)1進(jìn)入FIN_WAIT_1狀態(tài)裹粤;這表示主機(jī)1沒(méi)有數(shù)據(jù)要發(fā)送給主機(jī)2了终蒂;
第二次分手:主機(jī)2收到了主機(jī)1發(fā)送的FIN報(bào)文段,向主機(jī)1回一個(gè)ACK報(bào)文段遥诉,Acknowledgment Number為Sequence Number加1拇泣;主機(jī)1進(jìn)入FIN_WAIT_2狀態(tài);主機(jī)2告訴主機(jī)1矮锈,我"同意"你的關(guān)閉請(qǐng)求霉翔;
第三次分手:主機(jī)2向主機(jī)1發(fā)送FIN報(bào)文段,請(qǐng)求關(guān)閉連接苞笨,同時(shí)主機(jī)2進(jìn)入LAST_ACK狀態(tài)债朵;
第四次分手:主機(jī)1收到主機(jī)2發(fā)送的FIN報(bào)文段,向主機(jī)2發(fā)送ACK報(bào)文段瀑凝,然后主機(jī)1進(jìn)入TIME_WAIT狀態(tài)序芦;主機(jī)2收到主機(jī)1的ACK報(bào)文段以后,就關(guān)閉連接粤咪;此時(shí)谚中,主機(jī)1等待2MSL后依然沒(méi)有收到回復(fù),則證明Server端已正常關(guān)閉寥枝,那好宪塔,主機(jī)1也可以關(guān)閉連接了。
瀏覽器渲染
按照渲染的時(shí)間順序囊拜,流水線(xiàn)可分為如下幾個(gè)子階段:構(gòu)建 DOM 樹(shù)某筐、樣式計(jì)算、布局階段冠跷、分層南誊、柵格化和顯示。如圖:
? 1. 渲染進(jìn)程將 HTML 內(nèi)容轉(zhuǎn)換為能夠讀懂DOM 樹(shù)結(jié)構(gòu)蜜托。
? 2.渲染引擎將 CSS 樣式表轉(zhuǎn)化為瀏覽器可以理解的styleSheets抄囚,計(jì)算出 DOM 節(jié)點(diǎn)的樣式。
? 3.創(chuàng)建布局樹(shù)盗冷,并計(jì)算元素的布局信息。
? 4.對(duì)布局樹(shù)進(jìn)行分層同廉,并生成分層樹(shù)仪糖。
? 5.為每個(gè)圖層生成繪制列表柑司,并將其提交到合成線(xiàn)程。合成線(xiàn)程將圖層分圖塊锅劝,并柵格化將圖塊轉(zhuǎn)換成位圖攒驰。
? 6.合成線(xiàn)程發(fā)送繪制圖塊命令給瀏覽器進(jìn)程。瀏覽器進(jìn)程根據(jù)指令生成頁(yè)面故爵,并顯示到顯示器上玻粪。
構(gòu)建 DOM 樹(shù)
瀏覽器從網(wǎng)絡(luò)或硬盤(pán)中獲得HTML字節(jié)數(shù)據(jù)后會(huì)經(jīng)過(guò)一個(gè)流程將字節(jié)解析為DOM樹(shù),先將HTML的原始字節(jié)數(shù)據(jù)轉(zhuǎn)換為文件指定編碼的字符,然后瀏覽器會(huì)根據(jù)HTML規(guī)范來(lái)將字符串轉(zhuǎn)換成各種令牌標(biāo)簽,如html诬垂、body等椅挣。最終解析成一個(gè)樹(shù)狀的對(duì)象模型卖氨,就是dom樹(shù)。
具體步驟:
??? 1.轉(zhuǎn)碼(Bytes -> Characters)—— 讀取接收到的 HTML 二進(jìn)制數(shù)據(jù),按指定編碼格式將字節(jié)轉(zhuǎn)換為 HTML 字符串
???? 2.Tokens 化(Characters -> Tokens)—— 解析 HTML类浪,將 HTML 字符串轉(zhuǎn)換為結(jié)構(gòu)清晰的 Tokens,每個(gè) Token 都有特殊的含義同時(shí)有自己的一套規(guī)則
構(gòu)建 Nodes(Tokens -> Nodes)—— 每個(gè) Node 都添加特定的屬性(或?qū)傩栽L(fǎng)問(wèn)器)纬乍,通過(guò)指針能夠確定
???? 3.Node 的父跋选、子、兄弟關(guān)系和所屬 treeScope(例如:iframe 的 treeScope 與外層頁(yè)面的 treeScope 不同)
???? 4.構(gòu)建 DOM 樹(shù)(Nodes -> DOM Tree)—— 最重要的工作是建立起每個(gè)結(jié)點(diǎn)的父子兄弟關(guān)系
樣式計(jì)算
???? 渲染引擎將 CSS 樣式表轉(zhuǎn)化為瀏覽器可以理解的 styleSheets官脓,計(jì)算出 DOM 節(jié)點(diǎn)的樣式协怒。
???? CSS 樣式來(lái)源主要有 3 種,分別是通過(guò) link 引用的外部 CSS 文件卑笨、style標(biāo)簽內(nèi)的 CSS孕暇、元素的 style 屬性?xún)?nèi)嵌的 CSS。,其樣式計(jì)算過(guò)程主要為:
???? CSS 文本中有很多屬性值湾趾,如 2em芭商、blue、bold搀缠,這些類(lèi)型數(shù)值不容易被渲染引擎理解铛楣,所以需要將所有值轉(zhuǎn)換為渲染引擎容易理解的、標(biāo)準(zhǔn)化的計(jì)算值艺普,這個(gè)過(guò)程就是屬性值標(biāo)準(zhǔn)化簸州。處理完成后再處理樣式的繼承和層疊,有些文章將這個(gè)過(guò)程稱(chēng)為CSSOM的構(gòu)建過(guò)程歧譬。
頁(yè)面布局
??? 布局過(guò)程岸浑,即排除 script、meta 等功能化瑰步、非視覺(jué)節(jié)點(diǎn)矢洲,排除 display: none 的節(jié)點(diǎn),計(jì)算元素的位置信息缩焦,確定元素的位置读虏,構(gòu)建一棵只包含可見(jiàn)元素布局樹(shù)责静。如圖:
?其中,這個(gè)過(guò)程需要注意的是回流和重繪盖桥,關(guān)于回流和重繪灾螃,詳細(xì)的可以看我另一篇文章《瀏覽器相關(guān)原理》,這里就不說(shuō)了~
生成分層樹(shù)
頁(yè)面中有很多復(fù)雜的效果揩徊,如一些復(fù)雜的 3D 變換腰鬼、頁(yè)面滾動(dòng),或者使用 z-indexing 做 z 軸排序等塑荒,為了更加方便地實(shí)現(xiàn)這些效果熄赡,渲染引擎還需要為特定的節(jié)點(diǎn)生成專(zhuān)用的圖層,并生成一棵對(duì)應(yīng)的圖層樹(shù)(LayerTree)袜炕,如圖:
如果你熟悉 PS本谜,相信你會(huì)很容易理解圖層的概念,正是這些圖層疊加在一起構(gòu)成了最終的頁(yè)面圖像偎窘。在瀏覽器中乌助,你可以打開(kāi) Chrome 的"開(kāi)發(fā)者工具",More tools選擇"Layers"標(biāo)簽陌知。渲染引擎給頁(yè)面分了很多圖層他托,這些圖層按照一定順序疊加在一起,就形成了最終的頁(yè)面仆葡。
柵格化
合成線(xiàn)程會(huì)按照視口附近的圖塊來(lái)優(yōu)先生成位圖赏参,實(shí)際生成位圖的操作是由柵格化來(lái)執(zhí)行的。所謂柵格化沿盅,是指將圖塊轉(zhuǎn)換為位圖把篓。如圖:
通常一個(gè)頁(yè)面可能很大,但是用戶(hù)只能看到其中的一部分腰涧,我們把用戶(hù)可以看到的這個(gè)部分叫做視口(viewport)韧掩。在有些情況下,有的圖層可以很大窖铡,比如有的頁(yè)面你使用滾動(dòng)條要滾動(dòng)好久才能滾動(dòng)到底部疗锐,但是通過(guò)視口,用戶(hù)只能看到頁(yè)面的很小一部分费彼,所以在這種情況下滑臊,要繪制出所有圖層內(nèi)容的話(huà),就會(huì)產(chǎn)生太大的開(kāi)銷(xiāo)箍铲,而且也沒(méi)有必要雇卷。
顯示
最后,合成線(xiàn)程發(fā)送繪制圖塊命令給瀏覽器進(jìn)程。瀏覽器進(jìn)程根據(jù)指令生成頁(yè)面关划,并顯示到顯示器上膘融,渲染過(guò)程完成。
轉(zhuǎn)自鏈接