浏览器如何工作(一)进程架构
浏览器的工作过程复杂而高效,其核心在于其进程架构的设计。以下是对浏览器进程架构的详细解析:
一、浏览器的主要进程
现代浏览器大多采用多进程多线程的架构,以Chrome浏览器为例,其主要进程包括:
- 浏览器进程(Browser Process):
- 功能:作为浏览器的主进程,负责浏览器的整体控制和资源协调,包括用户界面的展示(如地址栏、书签栏等)、网络请求的管理、以及与其他进程的通信等。
- 关键线程:
- UI线程:控制浏览器上的按钮及基础界面的展示。
- 网络线程(Network Thread):主要用于处理网络请求,如DNS解析、建立TLS连接等。
- 存储线程(Storage Thread):用于控制文件访问。
- IO线程:主要用于进程间通信。
- 渲染进程(Renderer Process):
- 功能:负责页面的渲染工作,包括HTML、CSS的解析,JavaScript的执行,以及页面的布局和绘制等。
- 数量:通常每个标签页对应一个渲染进程,但也可能根据浏览器的优化策略有所不同(如Process-per-site-instance、Process-per-site等模式)。
- 关键线程:
- GUI渲染线程:负责页面的渲染工作,如解析HTML和CSS、构建DOM树、CSSOM树、Render树,以及绘制页面等。
- JavaScript引擎线程:负责解析和执行JavaScript代码,与GUI渲染线程互斥。
- 定时器线程:处理
setInterval
和setTimeout
等定时器任务,计时完毕后将任务添加到事件队列中等待JavaScript引擎线程执行。 - 异步HTTP请求线程:当发起网络请求时,浏览器会新开一个线程来处理这些请求,并在请求状态变化时将回调放入事件队列中。
- 事件触发线程:用于控制事件循环,将任务添加到事件队列中,并在适当的时候将其分发给JavaScript引擎线程执行。
- GPU进程(GPU Process):
- 功能:负责处理与图形渲染相关的任务,如将渲染进程计算出的图像帧绘制在屏幕上。
- 插件进程(Plugin Process):
- 功能:负责运行浏览器插件,如Flash插件等。这些插件通常运行在独立的进程中,以提高安全性和稳定性。
二、浏览器的工作流程
从用户输入URL到页面展示的过程大致如下:
-
处理输入:用户在地址栏输入URL并按下回车后,UI线程会判断输入内容是否为URL,并交给网络线程处理。
-
网络请求:网络线程进行DNS解析、建立TLS连接等网络操作来请求对应资源。如果收到服务器重定向头部,则与UI线程沟通并发起新的请求。
-
读取响应:网络线程收到服务器响应后,解析HTTP报文并根据响应头Content-Type确定响应主体类型。如果是HTML文件,则交给渲染进程处理;如果是其他文件,则交给下载管理器或相应处理模块。
-
页面渲染:渲染进程接收到HTML数据后,开始解析HTML内容并构建DOM树和Render树。随后进行页面布局和绘制,并将图像帧交给GPU进程绘制在屏幕上。
-
事件处理:在渲染过程中,如果遇到JavaScript代码或用户交互事件(如点击、滚动等),则会将这些事件添加到事件队列中等待JavaScript引擎线程处理。
-
页面更新:当JavaScript引擎线程空闲时,会从事件队列中取出任务执行,并可能导致DOM树的更新和页面的重新渲染。
通过以上进程和线程的协同工作,浏览器能够高效地处理用户的网络请求并展示丰富的网页内容。
下面搬运自前端大佬(偶像cos02)©归cos02,若有侵权,立即删除
浏览器的核心功能
浏览器,“浏览” 是这个产品的核心,浏览无非分为两步:
- 获取想浏览的资源
- 展示得到的资源
现代浏览器还增加了交互功能,这涉及到脚本运行。因此,理解浏览器的核心就是理解其三大引擎如何工作:
- 网络引擎
- 渲染引擎
- 脚本引擎
浏览器架构的选择:单进程 vs 多进程
在设计浏览器这样复杂的程序时,我们面临两种基本结构的选择:
- 单进程 + 多线程:所有功能集中在一个进程中,通过多线程实现各个功能。
- 多进程 + 每个进程少量线程 + IPC 通信:核心服务被抽离成独立进程,进程间通过 IPC 通信。
选择哪种结构,这是一个值得考虑的问题。我们可以想想各自的优缺点:
单进程结构:
优点:
- 内存效率高,多个线程共享一个进程的内存开销
- 通信效率高,线程之间由于可以访问公共内存,通信开销较小
缺点:
- 稳定性差,一个线程挂掉可能引起整个进程挂掉(对于浏览器而言,这是致命的,比如一个页面挂掉,可能导致整个浏览器挂掉)
- 安全性差,进程之间可以访问公共内存,页面之间难以实现有效的沙箱隔离
- 可拓展性差,功能越多,意味着一个进程越来越大庞大,耦合难以避免的变多
多进程结构:
优点:
多进程程序解决了单进程的一些缺点
- 稳定性:一个进程挂了不会引起其他进程(一个页面挂了不会影响其他页面)
- 安全性:进程之间天然隔离,可以实现更严格的沙箱
- 利用现代 CPU:多进程可以更好的使用现代多核 CPU
- 拓展性:将各个模块抽离成一些独立的进程,实现解藕,单独维护
缺点:
- 更多的资源(内存,I/O,CPU时钟)消耗
- 更多的进程通信(IPC)开销
浏览器架构的历史演变
在回看一个产品时,不要脱离其历史背景。
早期的浏览器,功能简单,且计算机内存资源昂贵,此时单进程的设计也许更合理。
但随着人类社会的发展,计算资源相对宽裕,计算能力大幅度提升,且用户的复杂了很多,此时,多进程的结构更加合理。
1990年代单进程架构内存资源昂贵简单的网页内容2000年代初单进程多线程网页开始复杂化多核处理器出现2008年Chrome发布多进程架构硬件性能提升内存成本下降2010年代多进程架构普及移动设备兴起网页应用复杂度大增现在持续优化的多进程架构智能资源管理云计算和边缘计算的影响浏览器架构的演变
浏览器架构的选择与其所处的时代背景密切相关:
- 早期:功能简单,计算机资源昂贵,单进程设计更合理。
- 现代:计算资源丰富,用户需求复杂,多进程结构更加适合。
现代多进程浏览器架构
前面提到,现代浏览器使用多进程的架构模式。
以我的 Chrome 浏览器举例:
- 浏览器主进程:
- 程序 UI(地址栏,书签栏,前进后退按钮)
- 管理标签和窗口
- 协调其他进程
- 网络请求相关
- GPU 进程:
- 处理 GPU 任务,加速渲染
- 处理 OpenGL 和 2D 绘图操作
- 将渲染进程的绘制命令转为 GPU 命令
- 实用工具进程:
- 浏览器将一些特定的任务封装为了独立的进程,比如音频处理,文件解压,存储
- 渲染进程
- 浏览器会尽力为每个标签页提供一个独立的渲染进程
- 解析和渲染网页资源
- 拓展进程
- 现代浏览器通过插件扩展功能,为了安全性,每个插件运行在一个独立的进程中
Chrome架构进化的目标是将整个浏览器程序的不同部分服务化,便于分割或合并。
前面提到,多进程架构会引起更多的内存和计算开销,所以 chrome 选择了更灵活的方式:
基本思路是:
- 在高配设备中,每个服务独立开进程,保证稳定;
- 在低配设备中,多个服务合并为一个进程,节约资源。同样的思路也应用到了Android上。
结语
一个应用的设计与其时代背景有关,技术的推进本质是用户需求的推进。而 Chrome 架构设计也充分体现了一个灵活的架构的优势。