預(yù)備知識
要想了解瀏覽器架構(gòu)的發(fā)展歷史,我們首先需要了解一下進(jìn)程及線程的特性
基礎(chǔ)知識
進(jìn)程可以理解為一個運行中的程序,線程則存在于進(jìn)程中。
進(jìn)程是系統(tǒng)進(jìn)行資源分配的最小單元,也就是說,線程無法單獨的獲取系統(tǒng)的資源,需要使用其所在的進(jìn)程的資源。
線程由進(jìn)程創(chuàng)建而存在,當(dāng)進(jìn)程銷毀時,正在運行的線程也會自動銷毀
單線程 vs 多線程
一個進(jìn)程處理任務(wù)時,可以采用單線程也可以采用多線程,對于多核屬于標(biāo)配的時代,使用多線程處理程序,可以極大的提升處理性能。
比如,我們要計算下面三個表達(dá)式的值,并顯示出結(jié)果來
A = 1 + 2
B = 20 / 5
C = 7 + 8
console.log(A, B, C)
使用單線程處理時,我們可以把這個過程拆分為四個任務(wù):
- 任務(wù)1 計算 A = 1 + 2
- 任務(wù)2 計算 B = 20 / 5
- 任務(wù)3 計算 C = 7 + 8
- 任務(wù)4 顯示最后的結(jié)果
如果采用多線程,經(jīng)過分析,我們發(fā)現(xiàn)這四個步驟中,前三個任務(wù)之間是獨立的,可以并行執(zhí)行,第四個任務(wù)則需要等待前三個任務(wù)結(jié)束后,方能執(zhí)行。因此我們可以將其分成三個線程來處理。
三個線程分別處理前三個任務(wù)中的一個,然后選擇一個線程來處理最后一個任務(wù)就好。
但是有一點需要注意,只要有一個線程奔潰了,那么整個進(jìn)程都會奔潰。
通信
線程間通信
同一個進(jìn)程的線程之間可以共享進(jìn)程的公共數(shù)據(jù),以便于進(jìn)行讀寫操作。
進(jìn)程通信
對于進(jìn)程間通信,則略為復(fù)雜一些,需要使用IPC進(jìn)行通信(圖中黑色虛線)。

要點總結(jié)
從以上的知識點中,提取出對下文有直接影響的幾個點。
1. 進(jìn)程中的任意一個線程出錯,都會導(dǎo)致整個進(jìn)程的奔潰
2. 線程之間共享進(jìn)程中的數(shù)據(jù)
?3. 當(dāng)一個進(jìn)程關(guān)閉后,操作系統(tǒng)會回首進(jìn)程占用的內(nèi)存
進(jìn)程關(guān)閉后,系統(tǒng)會回收所有的資源,哪怕是由于操作不當(dāng),引起的內(nèi)存泄露問題,內(nèi)存也會被正確回收。
比如早期的ie瀏覽器,支持很多插件,而這些插件很容易造成內(nèi)存泄露,這意味著只要瀏覽器開著,內(nèi)存 占用就會越來越多,所以需要關(guān)閉瀏覽器,重新打開,從而讓這些內(nèi)存被回收掉
4. 進(jìn)程之間互相隔離
由于進(jìn)程之間是互相隔離的,從而保證了進(jìn)程的獨立性。當(dāng)一個進(jìn)程發(fā)生奔潰時,不至于影響其他進(jìn)程。進(jìn)程之間需要通信的話,可以使用IPC技術(shù)
瀏覽器架構(gòu)進(jìn)化史
由于chrome擁有著極大的市場占有率,在多進(jìn)程時代我們將以chrome為案例進(jìn)行解析。
單進(jìn)程時代
故名思義,單進(jìn)程瀏覽器就是將所有功能都放在一個進(jìn)程中來實現(xiàn)。
在該瀏覽器進(jìn)程中,采用多線程技術(shù),將不同的功能使用不同的線程來實現(xiàn),比如網(wǎng)絡(luò)線程、頁面線程等。

如何多的功能運行在同一個進(jìn)程中,會導(dǎo)致瀏覽器不穩(wěn)定、不流暢、不安全等問題。
問題1:不穩(wěn)定
瀏覽器中的許多強(qiáng)大功能需要借助于插件來實現(xiàn),但是插件是第三方提供的,非常容易出現(xiàn)問題。
同時,除去插件容易出現(xiàn)問題,頁面線程中的javascript也非常容易出現(xiàn)問題。
從線程和進(jìn)程之間的描述中,可以知道,一個線程的奔潰,會導(dǎo)致整個進(jìn)程的奔潰。
問題2: 不流暢
這個不流暢所指的不僅僅是當(dāng)前頁面的不流暢,還有整個瀏覽器的不流暢。
從上圖中,我們得知,所有頁面的渲染模塊,js的執(zhí)行模塊、插件都運行在同一個線程中,這也就是說,同一個時刻只能有一個模塊在執(zhí)行。
比如,下面這個無限循環(huán)的腳本:
function freeze() {
while(true) {
console.log('freeze');
}
}
freeze();
當(dāng)這個腳本執(zhí)行在一個單進(jìn)程的頁面的時候,由于其是無限循環(huán)的,所以會一直執(zhí)行,從而導(dǎo)致其他模塊沒有機(jī)會執(zhí)行代碼。又因為所有頁面都運行在這個線程中,所以其他頁面也無法執(zhí)行任務(wù),從而導(dǎo)致整個瀏覽器失去相應(yīng),變卡頓。
問題3:不安全
由于是單進(jìn)程,同時瀏覽器需要系統(tǒng)資源的支持,比如讀寫cookie等,所以我們無法使用沙箱技術(shù)來進(jìn)行隔離,那么如果是惡意插件和js代碼的話,會引發(fā)安全問題。
插件可以使用C/C++等語言來書寫,通過插件可以獲取到系統(tǒng)的任意資源,也就意味著該插件可以完全操控電腦。如果是一個惡意插件,那么它就可以窺探隱私,釋放病毒等,從而引發(fā)安全性問題。
以上這些就是當(dāng)時瀏覽器的特點,不穩(wěn)定,不流暢,而且不安全。這是一段不堪回首的過去,也許你沒有經(jīng)歷過,不過你可以想象一下這樣的場景:當(dāng)你正在用瀏覽器打開多個頁面時,突然某個頁面崩潰了或者失去響應(yīng),隨之而來的是整個瀏覽器的崩潰或者無響應(yīng),然后你發(fā)現(xiàn)你給老板寫的郵件頁面也隨之消失了,這時你的心情會不會和頁面一樣崩潰呢?
多進(jìn)程-早期時代
這是2008年chrome發(fā)布時的進(jìn)程架構(gòu)。

從圖中,我們可以發(fā)現(xiàn),chrome將渲染模塊和插件模塊單獨封裝到了進(jìn)程中,進(jìn)程之間通過IPC進(jìn)行通信。
我們來一一分析一下,它是如何解決單進(jìn)程瀏覽器的三大問題的。
-
不穩(wěn)定問題
插件、渲染模塊被單獨封裝到了進(jìn)程中,那么當(dāng)一個插件或者一個tab頁面奔潰的時候,不會影響到其他插件模塊、渲染模塊,也不會將這個瀏覽器搞到奔潰,從而解決了不穩(wěn)定的問題
-
不流暢問題
同理,由于插件、渲染模塊在主進(jìn)程中的剝離,那么當(dāng)某一個插件、頁面發(fā)生阻塞的時候,不會影響到瀏覽器,也不會影響到其他的插件和頁面
-
不安全問題
采用多進(jìn)程后,我們可以使用沙箱技術(shù)對插件進(jìn)程和渲染進(jìn)程進(jìn)行隔離,這樣即使渲染進(jìn)程或者插件進(jìn)程執(zhí)行了惡意程序,其也無法獲得系統(tǒng)權(quán)限。
多進(jìn)程-現(xiàn)狀
隨著chrome的發(fā)展,架構(gòu)又有了新的變化。
chrome進(jìn)一步的將主進(jìn)程中一些服務(wù)進(jìn)行了剝離,比如網(wǎng)絡(luò)、GPU、AUDIO等。

這里簡單的對這幾個進(jìn)程進(jìn)行一下介紹
-
瀏覽器主進(jìn)程
- 負(fù)責(zé)界面展示,與用戶交互。如前進(jìn)、后退、書簽等
- 負(fù)責(zé)各個頁面的管理,協(xié)調(diào)各個進(jìn)程
- 。。。
-
渲染進(jìn)程
負(fù)責(zé)將HTML,CSS,JS轉(zhuǎn)換為網(wǎng)頁。
排版引擎blink,js引擎V8都是運行在該線程中。
不過凡事都有兩面性,雖然多進(jìn)程提升了瀏覽器的穩(wěn)定性、安全性、流暢性,但是同樣也帶來了一些問題:
更高的資源占用
更復(fù)雜的體系架構(gòu)
瀏覽器各模塊之間耦合性高、擴(kuò)展性差等問題,會導(dǎo)致現(xiàn)在的架構(gòu)已經(jīng)很難適應(yīng)新的需求了
對于這兩個問題,chrome團(tuán)隊已經(jīng)著手進(jìn)行解決了,那就是面向服務(wù)架構(gòu)
未來面向服務(wù)的架構(gòu)
chrome整體架構(gòu)采用現(xiàn)代操作系統(tǒng)所采用的面向服務(wù)的架構(gòu)方向發(fā)展,將原來的各種模塊,抽取、重構(gòu)成獨立的服務(wù),每個服務(wù)都可以在獨立的進(jìn)程中運行,每個服務(wù)都會提供訪問接口,通過IPC來通信,從而構(gòu)建高內(nèi)聚,低耦合,易于維護(hù)和擴(kuò)展的系統(tǒng)。
chrome最終要把UI,數(shù)據(jù)庫,文件,設(shè)備,網(wǎng)絡(luò)等模塊重構(gòu)為基礎(chǔ)服務(wù),類似于操作系統(tǒng)的底層服務(wù)。

目前chrome正處于老的架構(gòu)向服務(wù)化架構(gòu)過度階段,這將是一個漫長的過程。
chrome要做的事情,類似于操作系統(tǒng)正在做的事情,我們甚至可以認(rèn)為chrome是一個便攜式操作系統(tǒng)
chrome還提供了彈性方案,當(dāng)運行于資源受限的設(shè)備上的時候,會自動將服務(wù)整合到一個進(jìn)程中,從而減輕設(shè)備的壓力。
總結(jié)
本文主要從chrome的角度對瀏覽器的架構(gòu)進(jìn)行了分析。
最初的瀏覽器是單進(jìn)程的,他們不穩(wěn)定,不流暢,不安全,之后出現(xiàn)了chrome,創(chuàng)造性的引入了多進(jìn)程架構(gòu)。隨著chrome應(yīng)用到越來越多的場景,功能也越來越復(fù)雜,原有的架構(gòu)已經(jīng)不能滿足于場景的快速變化,chrome團(tuán)隊采用了面向服務(wù)架構(gòu)(SOA)進(jìn)行逐步重構(gòu),目前仍然在進(jìn)行中。