從發(fā)出http請求到服務(wù)器響應(yīng)過程

從發(fā)出http請求到服務(wù)器響應(yīng)過程
?

?
瀏覽器輸入url經(jīng)歷圖
分析過程:
1.用戶輸入url,瀏覽器內(nèi)部代碼將url進(jìn)行拆分解析
?

url解析圖
舉個例子:
?
https://xxx.xxxxxx.xxx/article/123456.htm
?
其中 “xxx.xxxxxx.xxx” 表示這臺服務(wù)器,后面的/article/123456.htm
表示我們請求的文件路徑。但是這個路徑是相對路徑,是以web服務(wù)器根目錄為起始目錄的。
?

?
所以一個 URL 實際上對應(yīng)Web服務(wù)器里的一個文件資源。如果沒有輸入路徑名,例如只輸入 “xxx.xxxxxx.xxx” ,表示訪問事先設(shè)置的默認(rèn)文件,常見的有 /index.html 、 /default.html 等等。
?
對 URL 進(jìn)行解析后,瀏覽器確定了 Web 服務(wù)器和文件名,接下來就是根據(jù)這些信息來構(gòu)造 HTTP 請求報文。HTTP消息格式如圖:
?

?
?域名解析過程
瀏覽器解析 URL 并生成 HTTP 數(shù)據(jù)結(jié)構(gòu)后,在發(fā)給服務(wù)器之前,還需要查詢域名對應(yīng)的 IP 地址,因為操作系統(tǒng)發(fā)送消息時,必須提供通信對象的 IP 地址。
?
DNS 服務(wù)器就是專門保存 域名與 IP 的對應(yīng)關(guān)系,負(fù)責(zé)解析域名的服務(wù)器 。注意:很多教材都說IP地址不方便記憶,所以才有了域名。其實域名不僅僅是方便記憶,他還有更重要的作用,比如用域名就可以實現(xiàn)一臺服務(wù)器同時搭建多個網(wǎng)站而共用一個IP。
?
域名是用句點來分隔的,比如 www.xxxxxx.com,這里的句點代表了不同層級的劃分。在域名中,越靠右的位置表示其層級越高。
?
可能因為域名是外國人定義的,所以思維和中國人相反。比如表示一個地點,外國喜歡按照從小到大的順序說(如 XX 街道 XX 區(qū) XX 市 XX ?。袊矚g按從大到小的順序(如 XX 省 XX 市 XX 區(qū) XX 街道)。
?
最右邊的是頂級域名,例如上面的 “.com” 。再下面是二級域名 xxxxxx.com。所以域名的層級關(guān)系是一個樹狀結(jié)構(gòu)(域名和域名服務(wù)器是兩個概念):
?
根 DNS 服務(wù)器
頂級域 DNS 服務(wù)器(com)
權(quán)威 DNS 服務(wù)器(xxxxxx.com)
?

所有的 DNS 服務(wù)器都有根域DNS 服務(wù)器的信息。這樣一來,任何 DNS 服務(wù)器都可以找到根域 DNS 。因此,客戶端只要能夠找到任意一臺 DNS 服務(wù)器,就可以通過它找到根域 DNS 服務(wù)器,然后再一步步找到位于下層的某臺目標(biāo) DNS 服務(wù)器。
?
域名解析過程:
?
首先查找電腦上的DNS緩存,如果有則解析完畢。否則進(jìn)入第2步;
客戶端向本地DNS服務(wù)器(可以在網(wǎng)絡(luò)屬性看到,一般是路由器自動設(shè)置,也可也手動設(shè)置)發(fā)送一個DNS請求,詢問 xxx.xxxxxx.com的IP地址。本地DNS收到后,如果緩存里有,則直接返回對應(yīng)的IP地址。否則第3步;
本地DNS向根DNS發(fā)送請求,詢問 xxx.xxxxxx.com 的IP地址。根DNS收到后,發(fā)現(xiàn)是.com結(jié)尾的,便返回.com頂級DNS的地址給本地DNS。本地DNS收到后,向.com頂級DNS發(fā)起請求,詢問xxx.xxxxxx.com的地址。頂級DNS返回負(fù)責(zé)xxx.xxxxxx域名的權(quán)威DNS地址。本地DNS于是向權(quán)威DNS請求,權(quán)威DNS查詢后返回對應(yīng)的IP地址。
本地DNS收到后,把結(jié)果返回給客戶端,再緩存起來。
我們再看下解析過程圖解:
?

3.瀏覽器費了一頓周折終于拿到了服務(wù)器IP,接下來就是網(wǎng)絡(luò)通信(過程如下圖),分層由高到低分別為:應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層。發(fā)送端從應(yīng)用層往下走,接收端從數(shù)據(jù)鏈路層往上走
?

首先:應(yīng)用層客戶端發(fā)送HTTP請求
HTTP請求包括請求報頭和請求主體兩個部分,其中請求報頭包含了至關(guān)重要的信息,包括請求的方法(GET / POST)、目標(biāo)url、遵循的協(xié)議(http / https / ftp…),返回的信息是否需要緩存,以及客戶端是否發(fā)送cookie等。
?

請求報文
?
然后:傳輸層TCP傳輸報文
?? 位于傳輸層的TCP協(xié)議為傳輸報文提供可靠的字節(jié)流服務(wù)。它為了方便傳輸,將大塊的數(shù)據(jù)分割成以報文段為單位的數(shù)據(jù)包進(jìn)行管理,并為它們編號,方便服務(wù)器接收時能準(zhǔn)確地還原報文信息。TCP協(xié)議通過“三次握手”等方法保證傳輸?shù)陌踩煽俊?/p>
客戶端發(fā)送一個帶有SYN標(biāo)志的數(shù)據(jù)包給服務(wù)端,在一定的延遲時間內(nèi)等待接收的回復(fù)。服務(wù)端收到后,回傳一個帶有SYN/ACK標(biāo)志的數(shù)據(jù)包以示傳達(dá)確認(rèn)信息,最后客戶端再回傳一個帶ACK標(biāo)志的數(shù)據(jù)包,代表握手結(jié)束,連接成功。
?
SYN (Synchronize Sequence Numbers)同步序列編號
ACK? (Acknowledgement)確認(rèn)字符
?
下圖也可以這么理解:
客戶端:“你好,在家不,有你信件?!?--SYN
服務(wù)端:“在的?!?----SYN/ACK
客戶端:“好嘞?!?----ACK
?

?
接著:網(wǎng)絡(luò)層IP協(xié)議查詢MAC地址
?? IP協(xié)議的作用是把TCP分割好的各種數(shù)據(jù)包傳送給接收方。而要保證確實能傳到接收方還需要接收方的MAC地址,也就是物理地址。IP地址和MAC地址是一一對應(yīng)的關(guān)系,一個網(wǎng)絡(luò)設(shè)備的IP地址可以更換,但是MAC地址一般是固定不變的。ARP協(xié)議可以將IP地址解析成對應(yīng)的MAC地址。當(dāng)通信的雙方不在同一個局域網(wǎng)時,需要多次中轉(zhuǎn)才能到達(dá)最終的目標(biāo),在中轉(zhuǎn)的過程中需要通過下一個中轉(zhuǎn)站的MAC地址來搜索下一個中轉(zhuǎn)目標(biāo)。
數(shù)據(jù)到達(dá)數(shù)據(jù)鏈路層
?? 在找到對方的MAC地址后,就將數(shù)據(jù)發(fā)送到數(shù)據(jù)鏈路層傳輸。這時,客戶端發(fā)送請求的階段結(jié)束
?
再次:服務(wù)器接收數(shù)據(jù)
?? 接收端的服務(wù)器在鏈路層接收到數(shù)據(jù)包,再層層向上直到應(yīng)用層。這過程中包括在運輸層通過TCP協(xié)議將分段的數(shù)據(jù)包重新組成原來的HTTP請求報文。
服務(wù)器響應(yīng)請求
?? 服務(wù)接收到客戶端發(fā)送的HTTP請求后,查找客戶端請求的資源,并返回響應(yīng)報文,響應(yīng)報文中包括一個重要的信息——狀態(tài)碼。狀態(tài)碼由三位數(shù)字組成,
其中比較常見的是200 OK表示請求成功。
301表示永久重定向,即請求的資源已經(jīng)永久轉(zhuǎn)移到新的位置。在返回301狀態(tài)碼的同時,響應(yīng)報文也會附帶重定向的url,客戶端接收到后將http請求的url做相應(yīng)的改變再重新發(fā)送。
404 not found 表示客戶端請求的資源找不到。
?
最后: 服務(wù)器返回相應(yīng)文件
??? 服務(wù)器端收到請求后的由web服務(wù)器(準(zhǔn)確說應(yīng)該是http服務(wù)器)處理請求,諸如Apache、Ngnix、IIS等。web服務(wù)器解析用戶請求,知道了需要調(diào)度哪些資源文件,再通過相應(yīng)的這些資源文件處理用戶請求和參數(shù),并調(diào)用數(shù)據(jù)庫信息,最后將結(jié)果通過web服務(wù)器返回給瀏覽器客戶端。
服務(wù)器有自己的MVC 結(jié)構(gòu)(如下圖)
?


?
?
關(guān)閉TCP連接
為了避免服務(wù)器與客戶端雙方的資源占用和損耗,當(dāng)雙方?jīng)]有請求或響應(yīng)傳遞時,任意一方都可以發(fā)起關(guān)閉請求。與創(chuàng)建TCP連接的3次握手類似,關(guān)閉TCP連接,需要4次握手。
?

?
4次握手
上圖可以這么理解:
客戶端:“兄弟,我這邊沒數(shù)據(jù)要傳了,咱關(guān)閉連接吧?!?---FIN
服務(wù)端:“收到,我看看我這邊有木有數(shù)據(jù)了?!?---ACK
服務(wù)端:“兄弟,我這邊也沒數(shù)據(jù)要傳你了,咱可以關(guān)閉連接了?!?---FIN
客戶端:“好嘞。”----ACK
?
4.頁面的渲染階段
流程:
解析HTML生成DOM樹。
解析CSS生成CSSOM規(guī)則樹。
將DOM樹與CSSOM規(guī)則樹合并在一起生成渲染樹。
遍歷渲染樹開始布局,計算每個節(jié)點的位置大小信息。
將渲染樹每個節(jié)點繪制到屏幕。
?

?
?
webkit渲染引擎流程
?
過程的重點:
?
渲染阻塞
當(dāng)瀏覽器遇到一個 script 標(biāo)記時,DOM 構(gòu)建將暫停,直至腳本完成執(zhí)行,然后繼續(xù)構(gòu)建DOM。每次去執(zhí)行JavaScript腳本都會嚴(yán)重地阻塞DOM樹的構(gòu)建,如果JavaScript腳本還操作了CSSOM,而正好這個CSSOM還沒有下載和構(gòu)建,瀏覽器甚至?xí)舆t腳本執(zhí)行和構(gòu)建DOM,直至完成其CSSOM的下載和構(gòu)建。
所以,script 標(biāo)簽的位置很重要。實際使用時,可以遵循下面兩個原則:
CSS 優(yōu)先:引入順序上,CSS 資源先于 JavaScript 資源。
JS置后:我們通常把JS代碼放到頁面底部,且JavaScript 應(yīng)盡量少影響 DOM 的構(gòu)建。
當(dāng)解析html的時候,會把新來的元素插入dom樹里面,同時去查找css,然后把對應(yīng)的樣式規(guī)則應(yīng)用到元素上,查找樣式表是按照從右到左的順序去匹配的。
例如: div p {font-size: 16px},會先尋找所有p標(biāo)簽并判斷它的父標(biāo)簽是否為div之后才會決定要不要采用這個樣式進(jìn)行渲染)。
所以,我們平時寫CSS時,盡量用id和class,千萬不要過渡層疊。
?
渲染樹繪制
在繪制階段,遍歷渲染樹,調(diào)用渲染器的paint()方法在屏幕上顯示其內(nèi)容。渲染樹的繪制工作是由瀏覽器的UI后端組件完成的。
reflow與repaint:
根據(jù)渲染樹布局,計算CSS樣式,即每個節(jié)點在頁面中的大小和位置等幾何信息。HTML默認(rèn)是流式布局的,CSS和js會打破這種布局,改變DOM的外觀樣式以及大小和位置。這時就要提到兩個重要概念:replaint和reflow。
replaint:屏幕的一部分重畫,不影響整體布局,比如某個CSS的背景色變了,但元素的幾何尺寸和位置不變。
reflow: 意味著元件的幾何尺寸變了,我們需要重新驗證并計算渲染樹。是渲染樹的一部分或全部發(fā)生了變化。這就是Reflow,或是Layout。
所以我們應(yīng)該盡量減少reflow和replaint,我想這也是為什么現(xiàn)在很少有用table布局的原因之一。
display:none 會觸發(fā) reflow,visibility: hidden屬性并不算是不可見屬性,它的語義是隱藏元素,但元素仍然占據(jù)著布局空間,它會被渲染成一個空框,所以visibility:hidden 只會觸發(fā) repaint,因為沒有發(fā)生位置變化。
有些情況下,比如修改了元素的樣式,瀏覽器并不會立刻 reflow 或 repaint 一次,而是會把這樣的操作積攢一批,然后做一次 reflow,這又叫異步 reflow 或增量異步 reflow。
有些情況下,比如 resize 窗口,改變了頁面默認(rèn)的字體等。對于這些操作,瀏覽器會馬上進(jìn)行 reflow。
?