对我来说,浏览器是一个黑盒。它会吃掉我的 HTML、CSS 和 JavaScript 文件,并显示一个页面。不知何故,但它有效。
直到有一天,我决定坐下来找出原因。
在网上搜索时,我找不到太多信息。 Tali Garsiel 在 2011 年编写了一篇写得很好的文章。从那时起,浏览器架构发生了变化。 Chrome 凭借其 2013 年从 WebKit 分叉出来的 Blink 引擎占据了约 65% 的市场份额。在接下来的 6 年里,Chrome 演变成了一种不同的架构。
然而,浏览器的本质部分并没有太大变化。它们都是基于进程和线程的。
使用 Chrome 打开一个网站,然后查看其任务管理器。您可以看到当前正在运行的进程列表。
为什么它有这么多进程而只打开一个选项卡?这就是要破解黑盒的原因。
进程和线程
线程与数据、代码和文件一起存在于进程中。 在单线程进程中,只有一个线程。它也是该进程的主线程。线程是一个队列,一个接一个地处理任务。下一个任务必须等待前面的任务完成。
有什么风险?如果一个任务出现问题崩溃了,整个线程就会停止,从而导致整个进程的终止。
在多线程进程中,任务可以在多个线程中同时处理得更快。所有线程共享内存中的数据。
如果其中一个线程停止,则进程终止并存在。
早期的浏览器
在现代浏览器出现之前,我们使用单进程浏览器。 IE6 是最受欢迎的一种。
IE6 中没有选项卡。由于单进程的限制,每个网页都分配了一个窗口。
在单进程浏览器中,进程需要处理所有事情,包括页面渲染、JavaScript 执行等等。
这种架构带来了三个问题:不稳定、性能低、不安全。
不稳定
当线程崩溃时,进程就会停止,整个浏览器就会冻结。
JavaScript 和 Flash 插件因导致页面线程崩溃而闻名。发生这种情况时,强制浏览器退出是唯一的解决方案。这就是我们的 IE6 体验所发生的事情。
性能低
有些 JavaScript 需要一段时间才能完成。执行脚本时,它会阻塞页面渲染线程。浏览器必须等待脚本完成执行,然后才能继续显示页面。最糟糕的情况是 JavaScript 中的无限循环。
此外,内存泄漏还会导致性能问题。浏览器内核很复杂。垃圾收集有时无法正常工作。您使用浏览器的时间越长,从系统中占用的内存就越多,您会感觉浏览器的响应时间越来越长。
不安全
邪恶的插件可以通过单进程浏览器轻松访问具有管理员权限的操作系统。此外,当您与浏览器交互时,JavaScript 可以读取敏感信息,例如输入密码时读取输入内容。
解决办法有哪些?开发人员制作了多进程浏览器,也称为现代浏览器。
多进程浏览器
在多进程浏览器中,我们有多个进程。进程之间通过进程间通信(IPC)进行通信。每个进程运行不同的线程。
如今,我们在浏览器中运行以下进程:
- 浏览器进程
- 渲染器进程
- 插件流程
- GPU进程
- 网络进程
- 设备流程
- 视频进程(实用进程之一)
- 音频进程(实用程序进程之一)
看起来很多,但我们先看一下三个必不可少的:浏览器进程、渲染器进程和插件进程。
这是进程及其在浏览器上的“区域”的图示。
多进程架构有两个重大变化。
- 将渲染器和插件进程与浏览器进程分开。
- 将渲染器和插件进程放置在沙箱中。
让我们看看这些改变是如何解决单进程浏览器中的问题的。
与不稳定作斗争
现代浏览器将渲染器和插件进程与浏览器进程分开。
渲染器进程负责页面渲染和 JavaScript 执行。当它崩溃时,只有相应的浏览器选项卡停止。您仍然可以浏览其他选项卡,因为浏览器进程保持不变。
这种分离处理也适用于插件。每个插件都有一个单独的进程。例如,如果 Flash 插件崩溃,它不会再影响您的浏览体验。
改善低性能
每个选项卡都有一个单独的渲染器进程。当我们打开多个选项卡时,浏览器会创建多个渲染器进程。
不同页面的 JavaScript 运行在各自的渲染器进程中。如果其中一个页面存在阻止其进程的 JavaScript 问题,则该问题会阻止其他选项卡中的页面呈现。多个插件进程以同样的方式提供帮助。
内存泄漏怎么办?关闭选项卡会触发垃圾收集。所有占用的内存都会被系统释放。
沙箱安全
所有高风险组件都移至渲染器进程并在沙箱中运行,包括 HTML 解析、JavaScript 虚拟机和文档对象模型 (DOM)。
同时,系统功能被放置在浏览器进程中,包括持久存储、用户交互和网络。
渲染器和插件进程中的恶意代码很难触及您的操作系统。
例如,渲染器进程或插件进程无法直接在沙箱中向网络和文件系统请求资源。浏览器进程将处理该请求,并确保以安全的方式继续进行。
以下是《Chromium 浏览器安全架构》中渲染器进程和浏览器进程执行的操作的完整列表。 渲染器进程负责
- HTML解析
- CSS解析
- 图像解码
- JavaScript 解释器
- 常用表达
- 布局
- 文档对象模型
- 渲染
- SVG
- XML解析
- XSLT
浏览器进程负责
- Cookie 数据库
- 历史数据库
- 密码数据库
- 窗口管理
- 位置栏
- 安全浏览黑名单
- 网络堆栈
- SSL/TLS
- 磁盘缓存
- 下载管理器
- 剪贴板
浏览器架构的最新改进
站点隔离
2018年,Chrome发布了站点隔离链接功能,以保护用户免受安全漏洞的影响。
跨站点 iframe 用于在页面上共享相同的渲染器进程,这意味着它可以访问相同的内存空间。通过 Meltdown 和 Spectre,跨站点 iframe 可以绕过同源策略。
自 Chrome 67 起,所有跨站点 iframe 都获得独立的渲染器进程。 2019年,Firefox启动了Project Fission,这是一个与集成站点隔离功能相关的项目。
同站点共享渲染器进程
多个渲染器进程需要计算机提供更多资源,因为每个渲染器进程都在内存中保存共享基础结构的副本。 在某种程度上,这些副本在内存中是多余的。同时,它们是安全性和性能的权衡。当您在浏览器中打开 1,000 个选项卡时,1,000 个渲染器进程可能会导致性能问题。
为了最大限度地减少性能影响,当您访问具有相同域的网站时,浏览器会尝试重用现有的渲染器进程。 例如,当您访问 Medium 网站时,您的浏览器会为其创建一个渲染器进程。然后,您单击网站上打开新选项卡的链接,浏览器将重用相同的渲染器进程。
当您手动打开新选项卡并输入来自同一域的 URL 时,此规则不适用。在这种情况下,浏览器会为其创建一个新的渲染器进程。
2021年和未来的架构
Chrome 现在有更多单独运行的进程。
除了浏览器、渲染器和插件进程之外,团队还将 GPU、网络和实用程序进程与浏览器进程分开。这就是我们看到许多进程只需打开一个选项卡即可运行的原因。
通过解耦进程,我们制作了更快、更安全的浏览器。 Chrome 团队决定在这条道路上走得更远。
面向服务架构 ( Service-Oriented Architecture, SOA ) 是由Chrome团队初始化的,在架构中引入了Chrome Foundation Service。它是一种模块化架构。
我们在这个架构中有更多的进程,沙箱适用于其中的大多数。更多渲染器进程意味着从计算机中占用更多资源。当笔记本电脑没有足够的资源时,该团队还引入了优雅的降级。
SOA 是一个大胆的举措,团队需要数年时间才能完成变革。目前,该团队正在逐步改进浏览器以实现 SOA。
要点
浏览器由进程和线程组成。复杂的浏览器机制是建立在它们之上的。