從輸入url到頁面展示到底發生了什麼

這篇文章很多都是參考別人的,然後進行總結,並提供相應知識點的學習資料
從輸入url到頁面展示總共經過如下幾個過程:

  1. 域名解析(獲得IP地址)
  2. 向WEB服務器發送HTTP請求
  3. 服務器處理請求
  4. 服務器返回HTTP響應
  5. 瀏覽器顯示頁面信息

一、輸入地址

當輸入url地址後,瀏覽器已經在智能匹配地址了,會從歷史記錄、書籤或緩存中查找,如果找到了,會從緩存中調出頁面顯示出來,在你還沒有按“enter”之前


image

二、瀏覽器查找域名的IP地址

瀏覽器查找域名的IP地址按照以下幾個步驟進行(這是你輸入url,按了enter之後):

  1. 首先會在瀏覽器的緩存中查找是否有該域名對應的IP地址,如果有,則直接返回該IP地址;如果沒有,則查找本地硬盤上的hosts文件中是否有,如果有,則返回對應的IP地址;如果沒有,則查找路由器緩存中是否有對應的IP地址,如果有,則返回;
  2. 如果在瀏覽器緩存中、hosts文件中、路由器緩存中都沒有找到ip地址,則瀏覽器會發起一個DNS請求到本地DNS服務器,本地DNS服務器一般是由你的網絡接入服務器商提供,如:電信、移動;
  3. DNS請求到達本地DNS服務器後,本地DNS服務器會先在自己的緩存中查找,如果找到了就返回找到的IP,這個過程是以遞歸的方式進行的;如果沒有,則本地DNS服務器繼續向根DNS服務器發起請求;
  4. 根DNS服務器並沒有記錄域名與IP的對應關係,而是告訴本地DNS服務器,可以到哪個頂級域名服務器上查詢,並給出該頂級域名服務器的地址,此過程是以迭代的方式進行的;
  5. 本地DNS繼續向頂級域名服務器發出查詢請求,頂級域名服務器接收到請求後,會告訴本地DNS到權限域名服務器上去查詢;
  6. 本地DNS繼續向權限域名服務器發出查詢請求,權限域名服務器查詢到域名對應的IP後,將IP地址返回給本地DNS,本地DNS接收後將其保存到自己的緩存中,以備下次查詢,提高查詢速度;至此,一個IP地址的查詢就此結束;
    DNS解析是一個遞歸查詢的過程


    注意DNS域名解析是以遞歸的方式進行的

知識拓展

1. 什麼是DNS
DNS(domain name system,域名系統):因特網上域名和IP地址相互映射的分佈式數據庫;簡單理解就是域名與IP地址的對照表,因爲域名(如:www.google.com)對於我們而言,更便於記憶,但是機器卻不擅長這種表達方式,因此需要將域名轉換爲IP地址,以便於機器識別, 這便有了DNS。
2. 根域名服務器
根服務器是架設互聯網的必須設施,管理互聯網的主目錄,全球共有13套根域名服務器
3. 遞歸查詢
客戶端主機向本地域名服務器的查詢是遞歸查詢;所謂遞歸查詢:客戶端主機查詢的域名地址無法在本地域名服務器中找到,因此本地域名服務器就以DNS客戶端的身份向其他根域名服務器發起請求,進行查詢,而不是讓客戶端主機去一直查詢;
遞歸查詢的結果要麼是返回的IP地址,要麼是報錯,表示無法查詢到地址
4. 迭代查詢
本地域名服務器向根服務器、頂級域名服務器和主機域名服務器發起的查詢請求就是迭代的過程,如:本地域名服務器向根服務器發起查詢請求,根服務器中會告訴本地域名服務器:”我這裏沒有你要找的內容,你去頂級域名服務器上找吧“,並將頂級域名服務器的地址返回給本地域名服務器,本地域名服務器接收到後,繼續向頂級域名服務器發送請求;頂級域名服務器要麼返回ip地址,要麼告訴本地域名服務器下一步要向哪個權限域名服務器發送請求,直到找到ip地址或找不到ip返回報錯信息,然後信息返回給客戶端主機;
下圖給出了這兩種查詢的差別



遞歸過程:主機→本地DNS服務器→其他DNS服務器(如:我要找一個蘋果吃,找到了A,問A有沒有,A說我幫你去找B,B可能有,果真B有,然後B將蘋果給了A,A再將蘋果給我,這就是遞歸)
迭代過程:本地DNS服務器→根服務器,本地DNS服務器→頂級域名服務器,本地DNS服務器→權限域名服務器;(如:我要找一個蘋果,找到了A,A說我也沒有,B可能有,你去找B吧;我又找B,B說我也沒有,你去找C吧,我又去找C,終於找到了蘋果,這就是迭代的過程)
整體圖:


Paste_Image.png

域名服務器的劃分:

1. 根域名服務器
全球總共有13套根服務器設備;它是最重要的域名服務器,它知道所有頂級域名服務器的域名和IP地址,如果本地域名服務器無法對域名進行解析,那麼都必須求助於它來進行解析
2. 頂級域名服務器
負責管理在該頂級域名服務器註冊的所有二級域名
。當收到DNS請求後,就給出相應的回答(可能是最後的結果,也可能是下一步應當找的域名服務器的IP地址)
3. 權限域名服務器
假設一個公司有abc.com和y.abc.com這麼兩個網址,那麼該網址對應的權限域名服務器中包含有這兩個網址映射的IP地址,權限服務器就是這樣的存在,可能理解不正確;理解如下幾個圖吧
4. 本地域名服務器
每個因特網服務提供商ISP,或大學,甚至大學裏的一個系,都可以擁有本地域名服務器
5. DNS域名稱空間的組織方式
我們在前面有說到根DNS服務器,域DNS服務器,這些都是DNS域名稱空間的組織方式。按其功能命名空間中用來描述 DNS 域名稱的五個類別的介紹詳見下表中,以及與每個名稱類型的示例



6. DNS負載均衡
當用戶訪問量巨大時,同時訪問主機將會使主機崩掉,因此使用DNS負載均衡技術解決這個問題,
原理:在DNS服務器中爲同一個主機分配多個IP地址(也就是多個服務器),當進行DNS解析時,通過算法根據主機的負載情況,返回IP地址,這裏面涉及到一個主機記錄(也叫A記錄),它主要用於將特定的主機名映射到特定的IP地址上;可查看DNS負載均衡資料


域名服務器結構圖

因特網的域名空間

三 、瀏覽器向WEB服務器發送Http請求

拿到域名對應的IP地址之後,瀏覽器會以一個隨機的端口(1024~65535)向服務器(Niginx, Apache等)的WEB程序80端口/8080端口(HTTP協議使用80端口/8080端口,HTTPS使用443端口)發起TCP連接請求。連接請求到達服務器端後,通過網卡,進入到內核的TCP/IP協議棧,還有可能要經過防火牆,進入WEB程序,最終建立TCP/IP連接。

TCP連接如圖所示:



建立連接後,會發送一個HTTP請求,HTTP請求包含的信息可以分成如下三部分:

  • 請求行(包含請求的方法、URL地址和協議版本)
  • 請求頭(Request Header)
  • 請求正文
請求行

請求行的格式如下:
Method Request-URL HTTP-Version CRLF
如: GET index.html HTTP/1.1

  • 請求的方法:GET或POST(這兩個是常用的),不常用的有:PUT 和 DELETE 、HEAD、OPTION以及 TRACE 方法,一般的瀏覽器只能發起 GET 或者 POST 請求。
  • URL地址: 可以理解爲我們要訪問的服務器上的文件地址
  • 協議版本:常用的是HTTP1.1
請求頭

作用:請求頭允許客戶端向服務器端傳請求的附加信息和客戶端信息
PS: 客戶端不一定指瀏覽器,有時也指Linux下的CURL命令行以及HTTP測試工具

常見的請求頭有:Accept、Accept-Language、Accept-Encoding、Accept-Charset、connection、Content-Type、Authorizaion、Cookie、User-Agent等


百度的HTTP請求


上圖是截獲的百度HTTP請求,Accept用於指定客戶端接收哪些類型的信息,Accept-Encoding指定接受的編碼格式,Connection指定爲Keep-alive,表示本次HTTP請求結束後,不要斷口TCP連接,這樣當下次HTTP請求使用相同的TCP通道時,可以不需要重新連接,節省TCP連接時間

請求正文

當使用POST或PUT方式時,表示客戶端需要向服務器端傳輸數據,傳輸的數據存放在請求正文中,同時,請求頭中也會包含一些與請求正文相關的數據;例如:當請求的數據採用json的數據格式時,需要設置請求頭的Content-Type:Application/json。

注意:請求頭和請求正文之間有一個空行,這個空行很重要,表示請求頭的結束。

如下是完整的HTTP請求:


HTTP請求.png

知識拓展

  1. 發送HTTP請求使用的隨機端口:
    這裏指的端口均是邏輯端口,也就是TCP/IP協議中的端口,端口範圍爲:0~65535,比如用於瀏覽網頁服務的80端口,用於FTP服務的21端口等等。一般 0 ~ 1023端口是固定分配給一些服務的,所以我們使用1024~65535的端口,關於端口的介紹可以查看計算機網絡端口的定義這篇文章
  2. 關於TCP的三次握手和四次揮手可以查看這兩篇文章:socket編程三次握手socket編程-四次握手斷開連接
  3. 爲什麼握手需要三次,而揮手要四次呢?
    在建立連接時,服務器端接收到客戶端的SYN後,將ACK和Seq打包發給了客戶端;而斷開連接時,服務器端正處於LISTEN監聽狀態, 接收到客戶端的FIN請求後,服務器端發送ACK給客戶端作爲響應,相當於就是告訴客戶端:"
    我知道你要斷開連接了(這隻表示客戶端不再發送數據,但是還可以接收數據),但是我還有些數據沒有發送完成",等服務器發送完成數據後,會發送FIN給客戶端,告訴它:“數據已經發送完成了,我們可以徹底斷開連接了“,客戶端接收到FIN後,再發送ACK給服務器,至此,兩者斷開連接

四、瀏覽器的永久重定向響應

拿訪問google爲例說明
我輸入的網址是 http://google.com服務器接收到請求後,給瀏覽器響應301永久重定向,瀏覽器轉而訪問http://www.google.com而不是http://google.com

  1. 什麼是重定向?
    簡單理解就是將我輸入的網址引向另一個網址;
  2. 爲什麼產生重定向?
    • 如果一個網站有兩個網址,那麼分配到每個網址上的搜索鏈接數就會減少,不利於排名
    • 緩存友好型變差;因爲要將同一個網站的多個地址均保存到緩存中。
  3. 301和302的區別
    • 共同點:都表示重定向,也就是瀏覽器拿到這個狀態碼之後,均會跳轉到新的URL地址,這個地址從服務器響應的Location中獲得
    • 不同點:301表示永久重定向,也就是原網址資源不可用了,搜索引擎在抓取新內容的同時,也會將舊網址重定向到新網址。
      302表示舊地址A的資源還在(仍然可以訪問),這個重定向只是暫時的從地址A跳轉到地址B,搜索引擎在抓取新內容而保存舊的網址
      這裏面涉及到搜索引擎的原理,可以參考如下資料:
      搜索引擎原理
      301和302跳轉的區別
      一個很不錯的關於SEO優化的個人網站
      《這就是搜索引擎:核心技術詳解》瞭解基本的搜索引起原理
  4. 重定向的原因
    • 網站調整(如改變目錄結構)
    • 網頁被移到另一個網址
    • 網頁的擴展名改變(如需要把.php改爲html)
      如果存在上述原因,而不進行重定向,那麼訪問者訪問的是舊的網址,要麼不能得到網站的最新信息,要麼出現404找不到主頁的錯誤,訪問量就被白白浪費掉了;再者,當一個網站申請了多個網址時,它們都需要導向主站點,這時候也需要用到重定向
  5. 什麼時候進行301或302的跳轉
    當網站只是臨時的移到另一個新的位置,可以使用302;當使用301時,說明原來的網址已經被移除不存在了。

五、服務器處理請求

經過以上層層步驟之後,我們的請求最終到了服務器,服務器是如何處理請求?

後端服務器從固定的端口接收到TCP報文後,開始對TCP報文進行處理,對HTTP協議進行解析,然後將相應的數據封裝爲HTTP Request對象,供上層使用。

對於大型的網站,爲了防止訪問量過大對應用服務器的衝擊,使得應用服務器掛掉,所以一般都會設置反向代理服務器(如:Nginx),用戶發送的請求並不是直接進入到應用服務器,而是會先到達反向代理服務器,然後由反向代理服務器根據實際情況將用戶請求傳遞給某個應用服務器,然後再將結果返回給客戶端;這樣也可以防止一臺服務器掛掉了,而不會影響到網站的正常使用。

如圖所示:


通過Nginx反向代理服務器,我們的請求到達WEB服務器,服務器端腳本處理我們的請求,訪問數據庫,獲取需要獲取的內容等,這裏涉及到服務器後端很多的複雜處理。

知識拓展

  1. 什麼是反向代理服務器
    客戶端的本來可以直接通過HTTP協議訪問應用服務器,但是網站管理員在中間添加了一個Nginx,這樣客戶端會先將請求發送到Nginx,Nginx請求應用服務器,然後將結果返回給客戶端,Nginx就扮演着反向代理服務器器的角色。

Paste_Image.png

六、服務器返回一個HTTP響應

  經過上面的幾個步驟,服務器收到客戶端請求,並已經處理,這時候需要把處理結果返回,也就是返回一個HTTP響應。
HTTP響應與HTTP請求類似,也包括如下三個部分:

  • 狀態行
  • 響應頭
  • 響應正文

一個HTTP響應
狀態行:

狀態行由:協議版本代表狀態的數字碼以及狀態描述,各元素之間以空格隔開
狀態行由協議版本、數字形式的狀態代碼、及相應的狀態描述,各元素之間以空格分隔。
格式: HTTP-Version Status-Code Reason-Phrase CRLF
例如: HTTP/1.1 200 OK \r\n
| -協議版本:是用http1.0還是其他版本
| -狀態描述:狀態描述給出了關於狀態代碼的簡短的文字描述。比如狀態代碼爲200時的描述爲 ok
| -狀態代碼:狀態代碼由三位數字組成,第一個數字定義了響應的類別,且有五種可能取值。如下:

1xx:信息性狀態碼,表示服務器已接收了客戶端請求,客戶端可繼續發送請求。

  • 100 Continue
  • 101 Switching Protocols

2xx:成功狀態碼,表示服務器已成功接收到請求並進行處理。

  • 200 OK 表示客戶端請求成功
  • 204 No Content 成功,但不返回任何實體的主體部分
  • 206 Partial Content 成功執行了一個範圍(Range)請求

3xx: 重定向狀態碼,表示服務器要求客戶端重定向。

  • 301 Moved Permanently 永久性重定向,響應報文的Location首部應該有該資源的新URL
  • 302 Found 臨時性重定向,響應報文的Location首部給出的URL用來臨時定位資源
  • 303 See Other 請求的資源存在着另一個URI,客戶端應使用GET方法定向獲取請求的資源
  • 304 Not Modified 服務器內容沒有更新,可以直接讀取瀏覽器緩存
  • 307 Temporary Redirect 臨時重定向。與302 Found含義一樣。302禁止POST變換爲GET,但實際使用時並不一定,307則更多瀏覽器可能會遵循這一標準,但也依賴於瀏覽器具體實現

4xx:客戶端錯誤狀態碼,表示客戶端的請求有非法內容。

  • 400 Bad Request 表示客戶端請求有語法錯誤,不能被服務器所理解
  • 401 Unauthonzed 表示請求未經授權,該狀態代碼必須與 WWW-Authenticate 報頭域一起使用
  • 403 Forbidden 表示服務器收到請求,但是拒絕提供服務,通常會在響應正文中給出不提供服務的原因
  • 404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL

5xx:服務器錯誤狀態碼,表示服務器未能正常處理客戶端的請求而出現意外錯誤。

  • 500 Internel Server Error 表示服務器發生不可預期的錯誤,導致無法完成客戶端的請求
  • 503 Service Unavailable 表示服務器當前不能夠處理客戶端的請求,在一段時間之後,服務器可能會恢復正常
響應頭:

  響應頭部:由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號”:”分隔,典型的響應頭有:


響應頭部
響應正文

包含着我們需要的一些具體信息,比如cookie,html,image,後端返回的請求數據等等。這裏需要注意,響應正文和響應頭之間有一行空格,表示響應頭的信息到空格爲止,下圖是fiddler抓到的請求正文,紅色框中的:響應正文:


響應正文

知識拓展

  1. TCP/IP、HTTP協議
    簡單的說就是TCP/IP、HTTP位於OSI模型的不同層,TCP位於傳輸層,IP位於網絡層,而HTTP位於應用層;
    具體可查看:TCP/IP、HTTP協議的區別

七、瀏覽器顯示HTML

在瀏覽器還沒有完整的接受HTML文檔時,它就已經開始顯示頁面了,不同瀏覽器解析的流程不同,以webkit的渲染過程爲例:

用戶請求的HTML文本(text/html)通過瀏覽器的網絡層到達渲染引擎後,渲染工作開始。


渲染過程

詳細流程圖
  


渲染詳細流程圖

主要分爲以下四個部分:

  1. 瀏覽器把獲取到的HTML代碼解析成1個DOM樹,HTML中的每個tag都是DOM樹中的1個節點,根節點就是我們常用的document對象。DOM樹裏包含了所有HTML標籤,包括display:none隱藏,還有用JS動態添加的元素等。

  2. 瀏覽器把所有樣式(用戶定義的CSS和用戶代理)解析成樣式結構體,在解析的過程中會去掉瀏覽器不能識別的樣式,比如IE會去掉-moz開頭的樣式,而FF會去掉_開頭的樣式。

  3. DOM Tree 和樣式結構體組合後構建render tree, render tree類似於DOM tree,但區別很大,render tree能識別樣式,render tree中每個NODE都有自己的style,而且 render tree不包含隱藏的節點 (比如display:none的節點,還有head節點),因爲這些節點不會用於呈現,而且不會影響呈現的,所以就不會包含到 render tree中。注意 visibility:hidden隱藏的元素還是會包含到 render tree中的,因爲visibility:hidden 會影響佈局(layout),會佔有空間。根據CSS2的標準,render tree中的每個節點都稱爲Box (Box dimensions),理解頁面元素爲一個具有填充、邊距、邊框和位置的盒子。

  4. 一旦render tree構建完畢後,瀏覽器就可以根據render tree來繪製頁面了。

迴流與重繪
  1. 當render tree中的一部分(或全部)因爲元素的規模尺寸,佈局,隱藏等改變而需要重新構建。這就稱爲迴流(reflow)。每個頁面至少需要一次迴流,就是在頁面第一次加載的時候。在迴流的時候,瀏覽器會使渲染樹中受到影響的部分失效,並重新構造這部分渲染樹,完成迴流後,瀏覽器會重新繪製受影響的部分到屏幕中,該過程成爲重繪。

  2. 當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響佈局的,比如background-color。則就叫稱爲重繪。

注意:迴流必將引起重繪,而重繪不一定會引起迴流。迴流可以理解爲render樹的結構發生了變化,需要重新構建;而重繪就是結構沒有變化,只是一些對結構佈局沒有產生影響的元素髮生了變化(如:字體顏色)

渲染過程中的JS處理

  瀏覽器在構造頁面時,當瀏覽器從服務器端接收到HTML文檔時,會從上到下依次解析HTML文檔,轉換爲DOM樹,在轉換過程中,如果發現某個Node(節點)引用了CSS、IMG,則會發起一個request(不知道這個是不是指HTTP請求?)去請求CSS或IMG,繼續執行下面的HTML轉換,而不需要等待request的返回,當request返回後,只需要把相應的內容放到對應的Node上即可。但是當引用了JS的時候,瀏覽器發起一個JS的request請求後,會一直等待該請求的返回;因爲瀏覽器需要構建一個穩定的DOM樹,而JS代碼很有可能會改變DOM結構,如使用document.write或appendChild,甚至直接使用location.href進行跳轉,瀏覽器爲了防止出現這種情況, 所以會阻塞後續資源的下載。

  JS的解析是由瀏覽器中的JS解析引擎完成的,比如谷歌的是V8。JS是單線程運行,也就是說,在同一個時間內只能做一件事,所有的任務都需要排隊,前一個任務結束,後一個任務才能開始。但是又存在某些任務比較耗時,如IO讀寫等,所以需要一種機制可以先執行排在後面的任務,這就是:同步任務(synchronous)和異步任務(asynchronous)
  JS的執行機制就可以看做是一個主線程加上一個任務隊列(task queue)。同步任務就是放在主線程上執行的任務,異步任務是放在任務隊列中的任務。所有的同步任務在主線程上執行,形成一個執行棧;異步任務有了運行結果就會在任務隊列中放置一個事件;腳本運行時先依次運行執行棧,然後會從任務隊列裏提取事件,運行任務隊列中的任務,這個過程是不斷重複的,所以又叫做事件循環(Event loop)。

知識拓展

  1. 關於頁面迴流與重繪可以參考這篇文章:
    頁面重繪和迴流以及優化
  2. 關於JS的加載解析,參考:
    如何加載JS,JS應該放在什麼位置?
  3. WEB前端底層知識--瀏覽器是如何工作的

參考資料:
計算機網絡第5版——謝希仁
what-really-happens-when-you-navigate-to-a-ur
從輸入URL到頁面加載發生了什麼
老生常談-從輸入url到頁面展示到底發生了什麼
淺談一個網頁打開的全過程(涉及DNS、CDN、Nginx負載均衡等)



作者:放風箏的小小馬
鏈接:http://www.jianshu.com/p/23b388f8e5aa

發佈了15 篇原創文章 · 獲贊 13 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章