# 深入理解现代浏览器 - 架构

浏览器的架构可以有两种实现方式：

1. 使用一个进程，并在进程里开启多个线程来处理不同的任务。
2. 使用多个进程，在每个进程里开启少量线程来处理不同任务，进程间通过 IPC 进行通信。

但浏览器的实现并无标准可遵循，浏览器产商们可以选择他们喜欢的方式来实现，所以浏览器和浏览器之间可能会完全不一样。

## 浏览器架构详解

我们以新版 Chrome 为例，它主要由以下几个进程组成：浏览器进程、渲染器进程、插件进程、GPU 进程

### 浏览器进程(browser process)

Chrome 的最上层就是浏览器进程，它负责协调其他进程(下面会提到，这些进程分别承担 Chrome 应用的各项工作任务)。

浏览器进程还负责浏览器的地址栏、书签、前进/后退按钮的管理，还有一些高权限的任务(如网络请求和文件访问)。

### 渲染器进程(renderer process)

渲染器进程负责在一个标签页中显示网站和处理一切相关事务。每打开一个新标签页，Chrome 就会新建一个渲染器进程来负责管理这个标签页。

不仅如此，现在 Chrome 还会尽量给每个站点分配不同的渲染器进程，也就是说，如果在一个网页中内嵌了两个 iframe，Chrome 不仅会给最外层的网站分配一个渲染器进程，还会分别给两个 iframe 各分配一个独立的渲染器进程。

### 插件进程(plugin process)

插件进程负责管理在网站中运行的插件，比如 flash。

### GPU 进程(GPU process)

GPU 进程负责 GPU 任务，之所以分出一个独立的进程来负责 GPU，是因为 GPU 要处理来自多个网页应用的请求并在同一个界面上绘制图形。

## Chrome 多进程架构的优点

优点一，可以想象以下两个场景：

* 场景 A: 浏览器是单进程的，打开 3 个标签页，浏览器在同一个进程中管理这些标签页，如果其中一个标签页奔溃了，另外两个标签也会无法响应。
* 场景 B: 浏览器是多进程的，打开 3 个标签页，浏览器创建了 3 个渲染器进程，如果其中一个标签页奔溃了无法响应，剩余的两个标签不会受到任何影响。

优点二：安全和隔离。因为操作系统提供了限制进程权限的方式，如果浏览器是多进程的，那它就可以根据进程的不同来隔离一些权限操作，比如禁止渲染器进程随意访问文件。

由于进程拥有独立的内存空间，导致一些本可以共用的基础设施(如 V8 引擎)会在每个进程的内存空间里都有一个副本，这就比单进程的浏览器占了更多的内存。为了节省内存，Chrome 会限制打开进程的数量上限(具体数字由设备的内存和 CPU 决定)，当进程达到上限时，Chrome 会把同站点的不同标签页放到一个进程中去管理。

## Chrome 的服务化

Chrome 的浏览器进程也用到了上面说的那种方法。Chrome 把浏览器程序中的不同部分看作一个个不同的服务，每个服务可以在不同的进程中运行，也可以在同一个进程中运行。

在硬件条件允许的情况下，Chrome 会把各个服务放在不同的进程中运行，以保证程序的稳定性。如果设备硬件条件有限，Chrome 就把各个服务放在一个进程中来节省内存消耗。

## 站点隔离

站点隔离是 Chrome 新引进的特性，在此之前，虽然 Chrome 给每一个标签页新开一个渲染器进程，但如果一个网站中内嵌了一个跨站的 iframe，那这两个站点是在运行在同一个渲染器进程中，分享同一块内存的。

虽然有同源策略来保证一个站点不能未经同意就从另一个站点获取数据，不过有人发现在现代 CPU 中，进程有可能读取任意内存，所以最有效的隔离站点的方式还是进程隔离。自桌面版 Chrome 67 起，Chrome 都默认采用站点隔离，也就是在同一个标签页中的不同站点都会有各自独立的渲染器进程。

实现站点隔离可不是易事，不仅需要彻底改变 iframe 之间的通信方式，还要实现 devtool 的无缝切换，还有 `Ctrl+F` 网页搜索功能也要实现成在多个进程中搜索，所以这称得上是一个里程碑式的特性了。

## 小结

本节以 Chrome 浏览器为例，详解了浏览器的架构，深入了解了 Chrome 的多进程架构及其优点，还有 Chrome 在多进程架构上实现的服务化和站点隔离。
