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

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

瀏覽器從關閉狀態進行啓動,而後新開 1 個頁面至少須要 1 個網絡進程、1 個瀏覽器進程、1 個 GPU 進程以及 1 個渲染進程,共 4 個進程;後續再新開標籤頁,瀏覽器、網絡進程、GPU進程是共享的,不會從新啓動,若是2個頁面屬於同一站點的話,而且從a頁面中打開的b頁面,那麼他們也會共用一個渲染進程,不然新開一個渲染進程。前端

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

  • 瀏覽器進程:主要負責界面顯示、用戶交互、子進程管理,同時提供存儲等功能。
  • 渲染進程:核心任務是將 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解析的時候就很快。session

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
相關文章
相關標籤/搜索