Chrom架構:僅僅打開1個頁面,為什么有4個進程?
無論你是想要設計高能web應用,還是要優化現有的 Web 應用,你都需要了解瀏覽器中的網絡進程、頁面渲染過程,JavaScript執行流程,以及 Web 安全理論,而這些功能是分散在瀏覽器的各個功能組件中的,通過瀏覽器的多 進程架構的學習,就可以把這些分散的知識點串聯起來,本章內容基於Chrome瀏覽器。
在開始之前,我們先看一下,Chrome 打開一個頁面需要啟動多少進程?打開 Chrome瀏覽器 任務管理器的窗口,如下圖:

從圖中可以看到,Chrome啟動了4個進程,你也許會好奇,啟動了一個頁面,為什么啟動這么多進程呢?
在解答這個問題之前,我們需要了解一下進程的概念,不過由於好多人容易把進程和線程的概念混淆,從而影響后續其他概念的理解,所以在這里先講解一下這兩個概念
進程和線程
在介紹進程和線程之前,我需要先講解下什么是並行處理,因為理解了並行處理的概念,再理解進程和線程會輕松許多。
什么是並行處理?
計算機中的並行處理就是同意時刻處理多個任務,比如我們要計算下面三個表達式的值,並顯示出結果。
A = 1+2
B = 20/5
C = 7*9
在編寫代碼的時候,我們可以把這個過程拆分為四個任務
- 任務1是計算 A=1+2
- 任務2是計算20/5
- 任務3是計算C=7*8
- 任務4是顯示最后計算的結果
正常情況下程序可以使用單線程來處理,也就是分四步按照順序分別執行四個任務。
如果采用多線程,我們只需分“兩步”,
- 第一步:使用三個線程同時執行前三個任務
- 第二步:再執行第四個顯示任務
通過對比,你會發現用單線程執行需要四部,而使用多線程只需要兩步。因此使用多進程處理能大大提升性能
線程VS進程
多線程可以並行處理任務,但是線程是不能單獨存在的,它是由進程來啟動和管理的。那么什么優勢進程呢?
一個進程就是一個程序的運行實例。詳細解釋就是,啟動一個程序的時候,操作系統會為該程序創建一塊內存,用來存放代碼、運行中的數據和一個執行任務的主線程,我們把這這樣一個運行環境叫線程,線程是依附於進程的,而進程中使用多線程並行處理能提升運算效率。
總結來說,進程和線程有以下4個特點
- 進程中的任意一線程出錯,就會導致整個進程的崩潰。
- 線程之間共享進程中的數據,線程之間可以對進程讀寫與操作
- 當一個進程關閉后,操作系統會回收進程所占用的內存,當一個進程退出時,操作系統會回收該進程所申請的所有資源
- 進程之間的內容相互隔離,進程隔離是為保護操作系統中進程互不干擾的技術,每一個進程只能訪問自己占有的數據,正因進程是隔離的餓,所以一個進程如果崩潰了,是不會影響其他進程的,如果進程之間需要通信,就需要使用用於進程間通信(IPC)的機制
單進程瀏覽器時代
單進程瀏覽器是指瀏覽器的所有功能模塊都是運行在同一個進程里,包含了 網絡、插件、JavaScript運行環境、渲染引擎和頁面等。
早在2007年之前,市面上瀏覽器都是單進程的

如下次多的功能模塊運行在一個進程里,是導致單進程瀏覽器不穩定、不流暢和不安全的一個主要因素
- 不穩定:早期瀏覽器借助插件來實現web視頻、web游戲等各種強大的功能,插件最容易出現問題的模塊,一個插件意外崩潰會引起整個瀏覽器的崩潰,除插件之外,渲染引擎也不穩定,通常復雜的js代碼有可能引起渲染引擎模塊的崩潰,也會導致整個瀏覽器的崩潰。
- 不流暢:從上圖可以看出所有的渲染模塊、JS執行環境以及插件都運行在一個線程,意味着同一時刻只能有一個模塊可以執行,假如有個無限循環的腳本 while(true){console.log('log')},因為這個腳本是無限循環的,所以當其執行時,會獨占整個線程,因為瀏覽器重所有頁面都在該線程,所以這些頁面沒有機會執行任務,就會導致整個瀏覽器失去響應卡頓,除了腳本和插件會讓單進程變得卡頓,頁面的內存泄漏也是一個重要原因。通常內存的瀏覽器的內核是非常復雜的,運行一個復雜的頁面在關閉會存在內存不能完全回收,這樣導致的問題使用時間越長,內存占用越高,瀏覽器越慢
- 不安全:插件可以使用C/C++等代碼編寫,通過插件可以獲取操作系統任意資源,如果是個惡意插件就可以釋放病毒,引發安全性問題;頁面腳本可以通過瀏覽器獲取系統權限也可以對你的電腦做惡意的事情,引發安全問題。
多進程瀏覽器時代
現代瀏覽器已經解決了這些問題
2008年 Chrome 發布時的進程架構

從圖中可以看出,Chrome 的頁面是運行在單獨的渲染進程中的,同時頁面里的插件也是運行在單獨的插件進程之中,進程間通過 IPC 機制進行通信
先看看如何解決不穩定的問題。
- 解決不穩定:由於進程是隔離的,所以一個頁面或者插件崩潰,影響到的僅僅是當前的頁面進程或者插件進程,並不會影響到其他瀏覽器和頁面
- 解決不流暢:Js也是運行在渲染進程中的,所以即使Js阻塞了渲染進程,影響到的也只是 當前的渲染頁面,因為其他的頁面腳本運行在他們自己的渲染進行中
- 解決不安全:采用多進程架構的額外好處是可以使用安全沙箱,你可以把沙箱看成是操作系統給進程上了一把鎖,沙箱里面的程序是可以運行,但是不能在你的硬盤上寫入任何數據,也不能在敏感位置讀取任何數據,例如文檔和桌面,Chrome把插件和渲染進程鎖在安全沙箱,這樣即使執行了惡意程序,也無法突破沙箱獲取系統權限
目前多進程架構
看看最新的Chrome進程架構

從圖中可以看出,最新的 Chrome 瀏覽器包括: 1個瀏覽器(主進程)、一個GPU進程、一個網絡進程(NetWork)、多個渲染進程和多個插件進程
下面逐漸分析幾個進程的功能
- 瀏覽器進程:主要負責界面顯示、用戶交互、子進程管理,同時提供存儲等功能
- 渲染進程:核心任務是將 HTML、CSS、JS轉換為用戶可以與之交互的網頁,排版引擎Blink 和 JS引擎 V8 都是運行在該進程,默認情況 Chrome 會為每個Tab創建一個渲染引擎
- GPU進程:Chrome剛開始發布是沒有GPU進程的,而GPU使用初衷是為了實現3D CSS的效果,隨后網頁、Chrome的UI界面都選擇采用GPU來繪制
- 網絡進程:負責網絡資源的加載,之前作為模塊運行在瀏覽器進程,現在獨立一個單獨的進程
- 插件進程:主要是負責插件的運行,因為插件易崩潰,所以通過插件進程來隔離,以保證插件進程不會對瀏覽器造成影響。
講到這里,現在你應該可以回答文章開頭提到的問題,打開一個頁面為什么會有四個進程了。
不過凡事都有兩面性,看看帶來的弊 吧:
- 更高的資源占用:每個進程都會包含公共基礎結構的副本(如Js運行環境),這就意味着會消耗更多的內存資源
- 更復雜的體系架構:瀏覽器各模塊之間耦合性高、擴展性差等問題,會導致現在的架構已經很難適應新的需求了
