瀏覽器相關原理(面試題)詳細總結一

来源:https://www.cnblogs.com/LuckyWinty/archive/2019/10/16/11685723.html
-Advertisement-
Play Games

1. Chrome 打開一個頁面需要啟動多少進程?分別有哪些進程? 瀏覽器從關閉狀態進行啟動,然後新開 1 個頁面至少需要 1 個網路進程、1 個瀏覽器進程、1 個 GPU 進程以及 1 個渲染進程,共 4 個進程;後續再新開標簽頁,瀏覽器、網路進程、GPU進程是共用的,不會重新啟動,如果2個頁面屬 ...


1. Chrome 打開一個頁面需要啟動多少進程?分別有哪些進程?

瀏覽器從關閉狀態進行啟動,然後新開 1 個頁面至少需要 1 個網路進程、1 個瀏覽器進程、1 個 GPU 進程以及 1 個渲染進程,共 4 個進程;後續再新開標簽頁,瀏覽器、網路進程、GPU進程是共用的,不會重新啟動,如果2個頁面屬於同一站點的話,並且從a頁面中打開的b頁面,那麼他們也會共用一個渲染進程,否則新開一個渲染進程。

最新的 Chrome 瀏覽器包括:1 個瀏覽器(Browser)主進程、1 個 GPU 進程、1 個網路(NetWork)進程、多個渲染進程和多個插件進程。

  • 瀏覽器進程:主要負責界面顯示、用戶交互、子進程管理,同時提供存儲等功能。
  • 渲染進程:核心任務是將 HTML、CSS 和 JavaScript 轉換為用戶可以與之交互的網頁,排版引擎 Blink 和 JavaScript 引擎 V8 都是運行在該進程中,預設情況下,Chrome 會為每個 Tab 標簽創建一個渲染進程。出於安全考慮,渲染進程都是運行在沙箱模式下。
  • GPU 進程:其實,Chrome 剛開始發佈的時候是沒有 GPU 進程的。而 GPU 的使用初衷是為了實現 3D CSS 的效果,只是隨後網頁、Chrome 的 UI 界面都選擇採用 GPU 來繪製,這使得 GPU 成為瀏覽器普遍的需求。最後,Chrome 在其多進程架構上也引入了 GPU 進程。
  • 網路進程:主要負責頁面的網路資源載入,之前是作為一個模塊運行在瀏覽器進程裡面的,直至最近才獨立出來,成為一個單獨的進程。
  • 插件進程:主要是負責插件的運行,因插件易崩潰,所以需要通過插件進程來隔離,以保證插件進程崩潰不會對瀏覽器和頁面造成影響。

2. 如何保證頁面文件能被完整送達瀏覽器?

互聯網中的數據是通過數據包來傳輸的。數據包要在互聯網上進行傳輸,就要符合網際協議(IP),互聯網上不同的線上設備都有唯一的地址,地址只是一個數字,只要知道這個具體的地址,就可以往這裡發送信息。

如果要想把一個數據包從主機 A 發送給主機 B,那麼在傳輸之前,數據包上會被附加上主機 B 的 IP 地址信息,這樣在傳輸過程中才能正確定址。額外地,數據包上還會附加上主機 A 本身的 IP 地址,有了這些信息主機 B 才可以回覆信息給主機 A。這些附加的信息會被裝進一個叫 IP 頭的數據結構里。IP 頭是 IP 數據包開頭的信息,包含 IP 版本、源 IP 地址、目標 IP 地址、生存時間等信息。

IP 是非常底層的協議,只負責把數據包傳送到對方電腦,但是對方電腦並不知道把數據包交給哪個程式,是交給瀏覽器還是交給王者榮耀?因此,需要基於 IP 之上開發能和應用打交道的協議,最常見的是用戶數據包協議(User Datagram Protocol),簡稱UDP傳輸控制協議(Transmission Control Protocol),簡稱TCP.

基本傳輸過程為:

  1. 上層將數據包交給傳輸層
  2. 傳輸層會在數據包前面附加上UDP 頭,組成新的 UDP 數據包,再將新的 UDP 數據包交給網路層
  3. 網路層再將 IP 頭附加到數據包上,組成新的 IP 數據包,並交給底層
  4. 數據包被傳輸到主機 B 的網路層,在這裡主機 B 拆開 IP 頭信息,並將拆開來的數據部分交給傳輸層
  5. 在傳輸層,數據包中的 UDP 頭會被拆開,並根據 UDP 中所提供的埠號,把數據部分交給上層的應用程式
  6. 最終,數據包就發送到了主機 B 上層應用程式這裡。

3. UDP和TCP有什麼區別?

  • TCP協議在傳送數據段的時候要給段標號;UDP協議不
  • TCP協議可靠;UDP協議不可靠
  • TCP協議是面向連接;UDP協議採用無連接
  • TCP協議負載較高,採用虛電路;UDP採用無連接
  • TCP協議的發送方要確認接收方是否收到數據段(3次握手協議)
  • TCP協議採用視窗技術和流控制
特性 TCP UDP
是否連接 面向連接 面向非連接
傳輸可靠性 可靠 不可靠
應用場合 傳輸大量數據 傳輸少量數據
速度

4. TCP傳輸的詳細過程是怎樣的?

進行三次握手,建立TCP連接。
  • 第一次握手:建立連接。客戶端發送連接請求報文段,將SYN位置為1,Sequence Number為x;然後,客戶端進入SYN_SEND狀態,等待伺服器的確認;
  • 第二次握手:伺服器收到SYN報文段。伺服器收到客戶端的SYN報文段,需要對這個SYN報文段進行確認,設置Acknowledgment Number為x+1(Sequence Number+1);同時,自己自己還要發送SYN請求信息,將SYN位置為1,Sequence Number為y;伺服器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中,一併發送給客戶端,此時伺服器進入SYN_RECV狀態;
  • 第三次握手:客戶端收到伺服器的SYN+ACK報文段。然後將Acknowledgment Number設置為y+1,向伺服器發送ACK報文段,這個報文段發送完畢以後,客戶端和伺服器端都進入ESTABLISHED狀態,完成TCP三次握手。
    完成了三次握手,客戶端和伺服器端就可以開始傳送數據。

ACK:此標誌表示應答域有效,就是說前面所說的TCP應答號將會包含在TCP數據包中;有兩個取值:0和1,為1的時候表示應答域有效,反之為0。
TCP協議規定,只有ACK=1時有效,也規定連接建立後所有發送的報文的ACK必須為1。
SYN(SYNchronization) : 在連接建立時用來同步序號。當SYN=1而ACK=0時,表明這是一個連接請求報文。對方若同意建立連接,則應在響應報文中使SYN=1和ACK=1. 因此, SYN置1就表示這是一個連接請求或連接接受報文。
FIN (finis)即完,終結的意思, 用來釋放一個連接。當 FIN = 1 時,表明此報文段的發送方的數據已經發送完畢,並要求釋放連接。

發送HTTP請求,伺服器處理請求,返迴響應結果

TCP連接建立後,瀏覽器就可以利用HTTP/HTTPS協議向伺服器發送請求了。伺服器接受到請求,就解析請求頭,如果頭部有緩存相關信息如if-none-match與if-modified-since,則驗證緩存是否有效,若有效則返回狀態碼為304,若無效則重新返回資源,狀態碼為200.

關閉TCP連接
  • 第一次分手:主機1(可以使客戶端,也可以是伺服器端),設置Sequence Number和Acknowledgment Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有數據要發送給主機2了;
  • 第二次分手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我“同意”你的關閉請求;
  • 第三次分手:主機2向主機1發送FIN報文段,請求關閉連接,同時主機2進入LAST_ACK狀態;
  • 第四次分手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,然後主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段以後,就關閉連接;此時,主機1等待2MSL後依然沒有收到回覆,則證明Server端已正常關閉,那好,主機1也可以關閉連接了。

5. 為什麼很多站點第二次打開速度會很快?

主要原因是第一次載入頁面過程中,緩存了一些耗時的數據。
那麼,哪些數據會被緩存呢?

DNS緩存

主要就是在瀏覽器本地把對應的 IP 和功能變數名稱關聯起來,這樣在進行DNS解析的時候就很快。

MemoryCache

是指存在記憶體中的緩存。從優先順序上來說,它是瀏覽器最先嘗試去命中的一種緩存。從效率上來說,它是響應速度最快的一種緩存。
記憶體緩存是快的,也是“短命”的。它和渲染進程“生死相依”,當進程結束後,也就是 tab 關閉以後,記憶體里的數據也將不復存在。

瀏覽器緩存

先看一張經典的流程圖,結合理解
GitHub
瀏覽器緩存,也稱Http緩存,分為強緩存和協商緩存。優先順序較高的是強緩存,在命中強緩存失敗的情況下,才會走協商緩存。

強緩存

強緩存是利用 http 頭中的 ExpiresCache-Control 兩個欄位來控制的。強緩存中,當請求再次發出時,瀏覽器會根據其中的 expires 和 cache-control 判斷目標資源是否“命中”強緩存,若命中則直接從緩存中獲取資源,不會再與服務端發生通信。

實現強緩存,過去我們一直用expires。當伺服器返迴響應時,在 Response Headers 中將過期時間寫入 expires 欄位。像這樣

expires: Wed, 12 Sep 2019 06:12:18 GMT

可以看到,expires 是一個時間戳,接下來如果我們試圖再次向伺服器請求資源,瀏覽器就會先對比本地時間和 expires 的時間戳,如果本地時間小於 expires 設定的過期時間,那麼就直接去緩存中取這個資源。

從這樣的描述中大家也不難猜測,expires 是有問題的,它最大的問題在於對“本地時間”的依賴。如果服務端和客戶端的時間設置可能不同,或者我直接手動去把客戶端的時間改掉,那麼 expires 將無法達到我們的預期。

考慮到 expires 的局限性,HTTP1.1 新增了Cache-Control欄位來完成 expires 的任務。expires 能做的事情,Cache-Control 都能做;expires 完成不了的事情,Cache-Control 也能做。因此,Cache-Control 可以視作是 expires 的完全替代方案。在當下的前端實踐里,我們繼續使用 expires 的唯一目的就是向下相容。

cache-control: max-age=31536000

在 Cache-Control 中,我們通過max-age來控制資源的有效期。max-age 不是一個時間戳,而是一個時間長度。在本例中,max-age 是 31536000 秒,它意味著該資源在 31536000 秒以內都是有效的,完美地規避了時間戳帶來的潛在問題。

Cache-Control 相對於 expires 更加準確,它的優先順序也更高。當 Cache-Control 與 expires 同時出現時,我們以 Cache-Control 為準。

協商緩存

協商緩存依賴於服務端與瀏覽器之間的通信。協商緩存機制下,瀏覽器需要向伺服器去詢問緩存的相關信息,進而判斷是重新發起請求、下載完整的響應,還是從本地獲取緩存的資源。如果服務端提示緩存資源未改動(Not Modified),資源會被重定向到瀏覽器緩存,這種情況下網路請求對應的狀態碼是 304。

協商緩存的實現,從 Last-ModifiedEtag,Last-Modified 是一個時間戳,如果我們啟用了協商緩存,它會在首次請求時隨著 Response Headers 返回:

Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT

隨後我們每次請求時,會帶上一個叫 If-Modified-Since 的時間戳欄位,它的值正是上一次 response 返回給它的 last-modified 值:

If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT

伺服器接收到這個時間戳後,會比對該時間戳和資源在伺服器上的最後修改時間是否一致,從而判斷資源是否發生了變化。如果發生了變化,就會返回一個完整的響應內容,併在 Response Headers 中添加新的 Last-Modified 值;否則,返回如上圖的 304 響應,Response Headers 不會再添加 Last-Modified 欄位。

使用 Last-Modified 存在一些弊端,這其中最常見的就是這樣兩個場景:

  • 我們編輯了文件,但文件的內容沒有改變。服務端並不清楚我們是否真正改變了文件,它仍然通過最後編輯時間進行判斷。因此這個資源在再次被請求時,會被當做新資源,進而引發一次完整的響應——不該重新請求的時候,也會重新請求。
  • 當我們修改文件的速度過快時(比如花了 100ms 完成了改動),由於 If-Modified-Since 只能檢查到以秒為最小計量單位的時間差,所以它是感知不到這個改動的——該重新請求的時候,反而沒有重新請求了。

這兩個場景其實指向了同一個 bug——伺服器並沒有正確感知文件的變化。為瞭解決這樣的問題,Etag 作為 Last-Modified 的補充出現了。

Etag 是由伺服器為每個資源生成的唯一的標識字元串,這個標識字元串可以是基於文件內容編碼的,只要文件內容不同,它們對應的 Etag 就是不同的,反之亦然。因此 Etag 能夠精準地感知文件的變化。

Etag 的生成過程需要伺服器額外付出開銷,會影響服務端的性能,這是它的弊端。因此啟用 Etag 需要我們審時度勢。正如我們剛剛所提到的——Etag 並不能替代 Last-Modified,它只能作為 Last-Modified 的補充和強化存在。

Etag 在感知文件變化上比 Last-Modified 更加準確,優先順序也更高。當 Etag 和 Last-Modified 同時存在時,以 Etag 為準。

Service Worker Cache

Service Worker 是一種獨立於主線程之外的 Javascript 線程。它脫離於瀏覽器窗體,因此無法直接訪問 DOM。這樣獨立的個性使得 Service Worker 的“個人行為”無法干擾頁面的性能,這個“幕後工作者”可以幫我們實現離線緩存、消息推送和網路代理等功能。我們藉助 Service worker 實現的離線緩存就稱為 Service Worker Cache。

Service Worker 的生命周期包括 install、active、working 三個階段。一旦 Service Worker 被 install,它將始終存在,只會在 active 與 working 之間切換,除非我們主動終止它。這是它可以用來實現離線存儲的重要先決條件.

Push Cache

Push Cache 是指 HTTP2 在 server push 階段存在的緩存。這塊的知識比較新,應用也還處於萌芽階段,應用範圍有限不代表不重要——HTTP2 是趨勢、是未來。在它還未被推而廣之的此時此刻,我仍希望大家能對 Push Cache 的關鍵特性有所瞭解:

  • Push Cache 是緩存的最後一道防線。瀏覽器只有在 Memory Cache、HTTP Cache 和 Service Worker Cache 均未命中的情況下才會去詢問 Push Cache。
  • Push Cache 是一種存在於會話階段的緩存,當 session 終止時,緩存也隨之釋放。
  • 不同的頁面只要共用了同一個 HTTP2 連接,那麼它們就可以共用同一個 Push Cache。

參考資料

  • 極客時間《瀏覽器工作原理與實踐》
  • 掘金小冊子《前端性能優化原理與實踐》

最後

  • 歡迎加我微信(winty230),拉你進技術群,長期交流學習...
  • 歡迎關註「前端Q」,認真學前端,做個有態度的技術人...
    GitHub

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天在工作的時候,遇到了一個需求,就是需要一鍵展開或者關閉樹形結構。關於樹形結構的不是很熟悉,然後去百度,結果也不是很準確。最後經過Google才找到。下麵分享給大家 直接看代碼: 上面的是摺疊,下麵的是展開。有一個標誌位,每次執行不同的代碼。然後把找到的表格貼在下麵,方便大家查閱(侵刪) 常用的配 ...
  • 資料庫的五個概念 1. 資料庫伺服器 2. 資料庫 3. 數據表 4. 數據欄位 5. 數據行 那麼這裡下麵既是對上面幾個概念進行基本的日常操作。 資料庫引擎使用 這裡僅僅只介紹常用的兩種引擎,而InnoDB是從MySQL 5.6.版本以後InnoDB就是作為預設啟動使用的存儲引擎。 既然知道了這倆 ...
  • https://www.cnblogs.com/jimmyshan-study/p/11229373.html https://www.cnblogs.com/cailijuan/p/10150918.html https://www.jb51.net/article/97956.htm https ...
  • 字元串(String)去除空格 https://www.cnblogs.com/jun-qi/p/11057421.html ...
  • 刪除數組中連續的元素時,可以使用slice或者splice方法,splice時需要註意會修改原數組。 1.slice(start,end):方法可從已有數組中返回選定的元素,返回一個新數組,包含從start到end(不包含該元素)的數組元素。(不改變原數組) start參數:如果不指定,那麼從0開始 ...
  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ... ...
  • 背景 最近在一臺龍芯電腦(系統是中興新支點,Linux)上開發electron應用。 PS:龍芯是國產的cpu,採用是mips架構,類似x86、arm。 安裝NodeJS 安裝步驟請查看:https://www.cnblogs.com/lovesong/p/11589813.html 安裝依賴 如果 ...
  • //用戶名正則,4到16位(字母,數字,下劃線,減號) let uPattern = /^[a-zA-Z0-9_-]{4,16}$/; //密碼強度正則,最少6位,包括至少1個大寫字母,1個小寫字母,1個數字,1個特殊字元 let pPattern = /^.*(?=.{6,})(?=.*\d)(?... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...