一個頁面從輸入URL到加載顯示完成,發生了什麼?

面試經典題——URL加載

1、涉及基本知識點:

1. 計算機網絡前端

  1. 五層因特爾協議棧:面試

    • 應用層(dns、http):DNS解析成IP並完成http請求發送;
    • 傳輸層(tcp、udp):三次握手四次揮手模式創建tcp鏈接;
    • 網絡層(IP、ARP):IP尋址;
    • 數據鏈路層(PPP):將請求數據封裝成幀;
    • 物理層:利用物理介質傳輸比特流(傳輸的時候經過雙絞線、電磁波等)
    • OIS七層框架:多了兩層即,會話層(處理兩個通訊系統中交換信息的表示方式)和表示層(管理不一樣用戶和進程之間的對話)。
  2. get和post的區別數據庫

    • get產生一個tcp數據包,post產生兩個
    • get請求時會把headers和data數據一塊兒發送出去;
    • post請求時,瀏覽器先發送headers,服務器100繼續,瀏覽器再發送data。
  3. DNS查詢獲得IP跨域

    1. 請求信息:首先查看域名的本地DNS緩存,該緩存存儲計算機最近檢索到的信息,若是計算機不知道答案,那麼就須要執行一個DNS查詢來查找答案;
    2. 詢問遞歸式DNS服務器:瀏覽器

      • 若是信息不存儲在本地,計算機會聯繫您的ISP(網絡提供商)的遞歸DNS服務器;
      • 這些專用計算機會爲你執行一個DNS查詢工做;
      • 遞歸服務器有本身的緩存,因此這個查詢過程一般在這裏完成,並將信息還回給用戶;
    3. 詢問根域名服務器緩存

      • 若是遞歸服務器沒有答案,他們會查詢根域名服務器;
      • 根域名服務器是一種計算機,它扮演着一種DNS的電話接線員的角色,他們不知道答案,但能夠將咱們的疑問指向知道在哪裏能夠找到答案的人。
    4. 詢問TLD域名服務器:安全

      • 根域名服務器將查看請求的第一部分,按從右到左的順序,從www.dyn.com中找到.com,並將請求指向.com對應的頂級域名服務器(TLD).com;
      • 每一個TLD,如(.com,.org,.us)都有本身的頂級域名服務器,
      • 這些服務器沒有咱們須要的信息,但他們能夠直接將咱們引導到有信息的服務器。
    5. 詢問權威的DNS服務器服務器

      • TLD域名服務器會繼續檢查請求的下一部分(dyn)www.dyn.com,並將查詢指向負責此特定域名的服務器;
      • 這些權威的服務器將負責瞭解關於特定域的全部信息,並將信息存儲在DNS記錄。
    6. 找回記錄:
      -遞歸服務器從權威服務器中檢索dyn.com的記錄,並將記錄存儲在本地緩存;網絡

      • 若是其餘任何人請求dyn.com的主機記錄,遞歸服務器已經有答案了,並不須要再次進行查找;
      • 全部記錄都有一個期限,一段時間後,遞歸服務器將須要要求一個新的記錄副本,以確保信息不回過期。
    7. 接收答案:數據結構

      • 有了答案,遞歸服務器將記錄返回到計算機,
      • 您的計算機將記錄存儲在緩存中,從記錄中讀取IP地址,而後將這些信息傳遞給瀏覽器;
      • 而後瀏覽器就能夠根據IP地址和服務器進行鏈接創建。
  4. TCPIP請求

    • http的本質就是TCPIP請求;
    • 須要經歷3次握手創建鏈接,4次揮手斷開鏈接;
    • TCP將http長報文劃分爲短報文,經過三次握手與服務器端創建鏈接,進行可靠傳輸。
    • 三次握手:

      • 客戶端:你是XXX服務端嗎?
      • 服務端: 我是XXX服務端,你是客戶端嗎?
      • 客服端: 是的,我是客戶端
      • 創建鏈接成功後,接下來就能夠進行正式的傳輸數據。
    • 四次揮手斷開鏈接

      • 主動方:我已經關閉了向你那邊的信息發送通道,只能被動接受信息了;
      • 被動方: 收到通道關閉的信息;
      • 被動方: 我如今也關閉了向你那邊發送信息的通道
      • 主動方: 左後收到信息,鏈接斷開,以後雙方沒法通訊
  5. TCP/IP的併發限制:

    • 瀏覽器對同一個域名下併發的TCP鏈接是有限制的(2-10個不等)
    • 並且在http1.0中每每一個資源的下載就須要一個tcp/ip請求

2. 瀏覽器機制

(1)進程和線程的概念

  1. 進程是CPU資源分配的最小單位,是能擁有資源和獨立運行的最小單位;
  2. 線程是CPU調度的最小單位,線程是創建在進程的基礎上的一次程序運行單位,一個進程能夠擁有多個線程;
  3. 通俗的講:進程是一個工廠,工廠有它獨立的資源,工廠之間相互獨立->進程之間相互獨立,線程是工廠中的工人,多個工人之間能夠協做完成任務,工廠內有一個或多個工人,工人之間共享空間。

(2)多進程的瀏覽器

瀏覽器是多進程的,有一個主控進程,以及每個tab頁面都會開一個進程(某些狀況下多個tab因爲優化策略會合並)
  • 瀏覽器主要進程:
  1. Browser進程:瀏覽器的主進程,負責協調、主控,只有一個,做用:

    • 負責瀏覽器界面的顯示、與用戶交互(如前進、後退等)
    • 負責各個頁面的管理,建立和銷燬其餘進程;
    • 將Renderer進程獲得的內存中的Bitmap繪製到用戶界面上
    • 網絡資源的管理和下載等
  2. 第三方插件進程: 每種類型的插件對應一個進程,僅當該插件使用時才建立;
  3. GPU進程: 最多一個,用於3D繪製等;
  4. 瀏覽器渲染進程(Renderer進程、瀏覽器內核、內部是多線程)

    • 默認沒打開一個tab頁面,就會啓動一個Renderer進程;
    • 負責頁面的渲染,腳本的執行,事件的處理。
  • 瀏覽器多進程的優點

    1. 避免單個page crash影響整個瀏覽器;
    2. 避免第三方插件crash影響整個瀏覽器
    3. 多進程充分利用多核優點;
    4. 方便使用沙盒模型隔離插件等進程,提升瀏覽器穩定性
簡單點理解:若是瀏覽器是單進程,那麼某個tab頁或第三方插件崩潰了,就會致使整個瀏覽器崩潰,體驗度極差,不過多進程內存消耗會更大,有點用空間換時間。

瀏覽器內核(渲染進程)

  • 瀏覽器渲染進程內部是多線程,包含主要線程有:

1.GUI渲染線程:

  • (1)負責瀏覽器界面的渲染,解析HTML、CSS,構建DOM樹和RenderObject樹,佈局和繪製等;
  • (2) 當界面須要重繪(Repaint)或因爲某種操做引起迴流(reflow)時該線程會執行;
  • 注意:GUI渲染線程和JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起,GUI更新會保存在一個隊列中等JS引擎空閒時當即執行。

2.JS引擎線程:

  • JS內核,負責處理JavaScript腳本程序(V8引擎)
  • 負責解析JavaScript腳本,運行代碼;
  • JS引擎一直等待着任務隊列中的任務到來,而後加以處理,一個tab頁面(renderer進程)中不管何時都只有一個JS線程在運行JS程序;
  • 注意:因爲GUI渲染線程和JS引擎線程是互斥的,因此若是JS程序運行時間過長,這樣會致使頁面渲染不連貫,致使頁面渲染加載阻塞;

3.事件觸發線程:

  • 歸屬於瀏覽器,而不是JS引擎,用來控制事件循環;
  • 當JS引擎執行代碼塊如setTimeOut時(也能夠來自瀏覽器內核的其餘線程,如鼠標單擊事件、AJAX異步請求等),會將對應的任務添加到事件線程中;
  • 當對應的事件符合觸發條件被觸發時,該線程就會把事件添加到JS的待處理隊列的隊尾,等待JS引擎的處理;
  • 注意:因爲JS的單線程的關係因此這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閒時纔會去執行)。

4.定時觸發器線程:

  • setTimeOut與setInterval所在的線程;
  • 瀏覽器的定時計數器並非由JavaScript引擎計數的,(由於JavaScript是單線程,若是處於阻塞狀態就會影響計時的準確)所以經過單獨的線程來計時並觸發定時(計時完畢後,添加到事件隊列,等待JS引擎空閒時執行)

5.異步http請求線程:

  • 在XMLHttpRequest在鏈接後是經過瀏覽器新開一個線程請求的
  • 將檢測到狀態變動時,若是設置有回調函數,異步線程就將產生狀態變動事件,將這個回調在放到事件隊列中,再由JavaScript引擎執行。

1、 一個頁面從輸入URL到加載顯示完成,這個過程發生了什麼?

  • 簡潔版:

    • 瀏覽器根據請求的URL交給DNS域名解析,找到真實的IP,向服務器發起請求;
    • 服務器交給後臺處理完成後返回數據,瀏覽器接收文件(HTML、CSS、JavaScript等);
    • 瀏覽器對加載到的資源(HTML、CSS、JavaScript等)進行語法解析,構建相應的內部數據結構(DOM樹、CSS樹、render樹等);
    • 載入解析到的資源文件、渲染頁面、完成。
  • 詳細版:

    1. 首先瀏覽器開啓一個線程來處理這個請求,對URL分析判斷,若是是http協議就按照Web方式來處理;
    2. 其次瀏覽器會對URL進行解析,通常包括(協議頭、主機域名或IP地址、端口號、請求路徑、查詢參數、hash等),而後開啓網絡線程發出一個完整到http請求;
    3. 固然通常咱們輸入的URL是服務器域名,這時就須要DNS經過域名查詢獲得對應的IP;
    4. DNS首先會查看瀏覽器DNS緩存,沒有就查詢計算機本地DNS緩存,尚未就詢問遞歸式DNS服務器(即網絡提供商,通常這個服務器都會有本身的緩存,因此IP查詢通常在這裏完成),若是沒有緩存,那就須要經過根域名和TLD域名服務器指到對應的權威DNS服務器找回記錄,並緩存到遞歸式服務器,而後遞歸服務器在將記錄返回給本地。
    5. 有了IP地址,此時網絡層便會經過IP地址尋的對應服務器的物理地址
    6. 尋得服務器地址,客戶端在網絡傳輸層即可以和服務器經過三次握手創建tcpip鏈接
    7. 鏈接創建後網絡數據鏈路層將數據包裝成幀;
    8. 最後物理層利用物理介質進行傳輸;
    9. 到了服務器,就會經過相反的方式將數據一層一層的還原回去;
    10. 請求到了後臺服務器,通常會有統一的驗證,如安全驗證、跨域驗證等,驗證未經過就直接返回相應的http報文
    11. 驗證經過後,就會進入後臺代碼,此時程序收到請求,而後執行對應的操做(如查詢數據庫等);
    12. 若是瀏覽器訪問過,且緩存上有對應的資源,便會與服務器最後修改時間對比,一致便返回304,告訴瀏覽器可以使用本地緩存;
    13. 前端瀏覽器接收到響應成功的報文後便開始下載網頁
    14. 下載完的網頁將被交給瀏覽器內核(渲染進程)進行處理:

      1. 根據頂部定義的DTD類型進行對應的解析方式;
      2. 渲染進程內部是多線程的,網頁的解析將會被交給內部的GUI渲染線程處理;
      3. 首先渲染線程中的HTML解釋器,將HTML網頁和資源從字節流解釋轉換成字符流;
      4. 再經過詞法分析器將字符流解釋成詞語;
      5. 以後通過語法分析器根據詞語構建成節點;最後經過這些節點組建一個DOM樹;
      6. 這個過程當中,若是遇到的DOM節點是JavaScript代碼,就會調用JavaScript引擎對JavaScript代碼進行解釋執行,此時由JavaScript引擎和GUI渲染線程的互斥,GUI渲染線程就會被掛起,渲染過程中止;若是JavaScript代碼的運行中對DOM樹進行了修改,那麼DOM的構建須要重新開始;
      7. 若是節點須要依賴其餘資源,如(圖片,CSS等),便會調用網絡模塊的資源加載器來加載它們,但它們是異步的,不會阻塞當前DOM樹的構建;
      8. 若是遇到的是JavaScript資源URL(沒有標記異步),則須要中止當前DOM的構建,直到JavaScript的資源加載並被JavaScript引擎執行後才繼續構建DOM;
      9. 對於CSS,CSS解釋器會將CSS文件解釋成內部表示結構,生成CSS規則樹;
      10. 而後合併CSS規則樹和DOM樹,生成render渲染樹;
      11. 最後對render樹進行佈局和繪製,並將結果經過IO線程傳遞給Browser控制進程進行顯示。
相關文章
相關標籤/搜索