浏览器架构
写在面前
从浏览器的发展轨迹上看,最开始的浏览器是单进程的(猜测是因为硬件问题),它们不稳定、不流畅且不安全(单线程的问题),后来有了 Chrome,创造性地引入了多进程架构,并解决了这些遗留问题,开创了多进程浏览器架构。Chrome 正在尝试应用更多的业务场景,比如移动设备, VR,视频等等,为了支持它们, Chrome 的体系结构变得越来越复杂,最终他们选择了面向服务(SOA)的体系结构
一句话解释
现代浏览器是由什么组成的?
看是什么版本的。在 18 年,是由 1 个浏览器主进程、1 个 GPU 进程、多个渲染进程、多个插件进程组成,19 年的 Chrome 多了网络进程,目前又多了音频进程、存储进程等等
早期的浏览器
进程就是应用程序创建的实例,而线程依托于进程。他们的关系:
- 进程中的任意一线程执行出错,会导致整个进程的奔溃
- 线程之间共享进程中的数据
- 当一个进程关闭之后,操作系统会回收进程所占用的内存
- 进程之间的内容相互隔离(很好地设计模型)
在早年,浏览器的架构是单进程的。顾名思义,单进程浏览器是指浏览器的所有功能模块都是运行在同一个进程里,这些模块包含了网络、插件、JavaScript 运行环境、渲染引擎和页面等
所有的模块都在一个进程中,只要一个进程出错,整个进程就会奔溃。
总之,单进程的浏览器存在着不稳定(插件开多了,容易奔溃)、不流畅(JavaScript 是单线程,执行会导致页面“卡”住)、不安全(插件使用 C/C++编写,意味着可以被插件控制)
多进程架构
为了解决单进程的缺点,Chrome 浏览器采用了多进程架构。
最终 Chrome 浏览器包括:1 个浏览器(Browser)主进程、1 个 GPU 进程、网络(NetWork)进程、多个渲染进程和多个插件进程
下面我们来逐个分析下这几个进程的功能。
- 浏览器进程。主要负责界面显示、用户交互、子进程管理,同时提供存储等功能
- 渲染进程。核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下
- GPU 进程。其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程
- 网络进程。主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程
- 插件进程。主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响
先说屁话,懂的都懂,字面意思
多进程架构怎么就解决了单进程架构的缺点呢?
解决不稳定:我打开一个页面,就是开启一个渲染进程,这个页面奔溃了,只要把它关掉即可,不会影响其他页面
解决不流畅:同理,打开一个页面,就是开启一个渲染进程,无论这个页面多卡(再说一次,JavaScript 是单线程语言,就是指一次只能完成一件任务,要是执行过程中阻塞住就会影响到页面),卡的是这个页面,不会影响其他页面
顺便一说,对于内存泄漏的解决方法也就更简单了,因为当关闭一个页面时,整个渲染进程页会被关闭,之后该进程所占用的内容都会被系统回收,也就解决了浏览器的内容泄漏问题
解决不安全:渲染进程和插件进程都使用了沙箱,沙箱里面的程序可以运行,但不能再你的硬盘上写入任何数据,也不能在敏感位置读取任何数据。说白了,沙箱就是你可以使用,但并不能修改
虽然多进程架构提高了浏览器的稳定性、流畅性和安全性,但同样不可避免地带来了一些问题
- 更高的资源占用。因为每个进程都会包含公共基础结构的副本(如 JavaScript 运行环境),这就意味着浏览器会消耗更多的内存资源。
- 更复杂的体系架构。浏览器各模块之间耦合性高、扩展性差等问题,会导致现在的架构已经很难适应新的需求了
未来的面向服务的架构
现代浏览器的问题是资源占用高、体系架构又复杂。为了解决这些问题,在 2016 年,Chrome 官方团队使用“面向服务的架构”(Services Oriented Architecture,简称 SOA)的思想设计了新的 Chrome 架构。简单来说,是想构建一个更内聚、松耦合、易于维护和扩展的系统
Chrome 最终要把 UI、数据库、文件、设备、网络等模块重构为基础服务,类似操作系统底层服务,下面是 Chrome“面向服务的架构”的进程模型图
即一个模块就是一个服务,而这些服务,未来如果采用这种架构,那么开启一个 Chrome 后,要开启十几个进程,当然,这些进程占用的内存会更小
如何查看进程
你可以点击 Chrome 浏览器右上角的“选项”菜单,选择“更多工具”子菜单,点击“任务管理器”,这将打开 Chrome 的任务管理器的窗口,如下图:
俺的 Chrome 版本是 89.0.4389.90,并且下了不少插件,不太直观。我们也可以看看 Edge 的:
可以看出,无论是 Chrome 还是 Edge,在 2021 年都比以前多了 Storage Service 。Chrome 还有 Audio Service ,V8 代理解析工具,备用渲染程序
总结
现代浏览器是由什么组成的?
看是什么版本的,在 18 年是是由 1 个浏览器主进程、1 个 GPU 进程、多个渲染进程、多个插件进程组成,19 年的 Chrome 多了网络进程,目前又多了音频进程、存储进程等等
考虑到”进程就是应用程序创建的实例“,所以你打开 Chrome ,就意味着开启至少 5 个进程,而进程中的线程一旦出错,进程就崩溃
一个渲染进程是由多个线程组成,而这些线程又如何影响到进程的呢?关于这个知识点我们后续会谈一下
顺便一说:渲染进程中包括 JS 引擎线程、事件触发线程、网络异步线程、定时器线程
Q&A
Q:如果打开了 2 个页面,会有几个进程呢?是 1 个网络进程、1 个浏览器进程、1 个 GPU 进程以及 2 个渲染进程,共 5 个吗?这些进程是可以在浏览器开发者中被实际观察到的吗?
A:通常情况下会是五个,但是有很多其他情况:
1. 如果页面里有 iframe 的话,iframe 也会运行在单独的进程中!
2. 如果页面里有插件,同样插件也需要开启一个单独的进程!
3. 如果你装了扩展的话,扩展也会占用进程
4. 如果 2 个页面属于同一站点的话,并且从 a 页面中打开的 b 页面,那么他们会公用一个渲染进程
这些进程都可以通过 chrome 的任务管理器来查看
Q:老师,渲染进程中有哪些线程呢?查了好多资料,感觉前后冲突。有说渲染进程中有网络线程,不知道这个网络线程和网络进程是不是一个东西呢?
A: Chrome 的渲染线程中没有网络线程!
估计看的是老的浏览器资料吧,在单进程浏览器架构中:渲染引擎,网络加载,等都是运行在同一个进程中!
不过现代浏览器已经将网络模块剥离出来了,有的以线程形式运行在浏览器主进程中的,有的像最新版本 Chrome 已经将网络功能单独独立出来一个进程来执行了!