01 chrome 的架构-为什么打开一个浏览器会有多个进程?

501 阅读10分钟

无论您是想设计一个高性能的web应用,还是想开发一个web应用,您都需要对浏览器的核心有一些了解, 比如说 网络、页面的渲染、js的执行、以及web的安全,然而这些内容被散列在不同的浏览器模块里面。

因此我们需要深入的去学习浏览器的整体架构。

在本专栏中,我所有的分析都是基于 Chrome 浏览器的

我们先来看打开一个新的页面,浏览器默认起了多少个进程。

截屏2021-09-09 下午5.34.39的副本.png

我们通过截图可以看到,启动了四个进程 分别是 网络进程 GPU进程 渲染进程 浏览器 本身的kernel 主进程 我会在后面详细讲解这几个进程目前了解。

在这里先不着急了解进程的作用 我想解释一下什么是进程、线程、以及协程序。

进程: 进程可以理解是一个操作系统启动的实例,这个实例有独立的系统分配的资源,进程和进程不同直接访问,天然的内存隔离保证了数据的安全可靠,如果需要通信可以通过IPC来进行通信。

线程: 线程是不能独立存在于系统中的。他是寄生在进程中的。在同一个进程中可以共享操作系统分配给进程的资源。

单线程和多线程上个图解释下

WechatIMG43.jpeg

从图中可以看到,线程是依附于进程的,而进程中使用多线程并行处理能提升运算效率。

当程序关闭操作系统操作系统将回收资源。 当一个进程退出时,操作系统会回收该进程所申请的所有资源;即使其中任意线程因为操作不当导致内存泄漏,当进程退出时,这些内存也会被正确回收。

协程: 从概念上理解,协程是一个轻量级的线程,但是它的切换远比线程消耗资源少的多。 众所周知切换线程是需要操作系统切换上下文的,然后切换协程只需要程序。

并行: 并行是同一时刻同时进行着多个任务的执行,一定区分并发。 举个例子吧 假设cpu也有4个core 要并行的执行下面的任务 A = 2+3;B = 20/4;C = 78; 在编写代码的时候,我们可以把这个过程拆分为四个任务:分别送4个cpu核心 每个核心执行一个任务 cpu1: A = 2+3; cpu2: B = 20/4; cpu3: C = 78; cpu4: 处理 A B C 三者的结果。

并发: 并发是什么鬼?解释一下,如果只有一个cpu的core我开了4个线程,这个时候,这四个任务表面也是在一起执行但是这个时候,这四个线程是在抢占cpu的执行权,因为cpu的切换速度非常快所以看起是一起执行,本质不是同时切记!。

进程和线程的关系 1、线程是跑在进程里面的,如果有一个线程挂了,会导致整个进程崩溃。 2、进程中的数据线程是可以共享的。 3、如果进程被杀死使用的内存是被回收的即便线程存在内存泄漏。 4、进程之间是相互隔离的如果需要做通信需要ICP机制。

在了解了,进程线程和协程之后,来看看最初的浏览器但进程的设计。 单进程浏览器时代

截屏2023-05-08 上午9.04.10.png

可以清晰的看到早期的浏览器 页面渲染、 页面展示、 网络、 插件、 JS的运行环境..., 通通的以线程的方式都运行在了主进程当中了。

这么多功能都运行在一个线程当中会造成 1.不安全 2.不稳定 3.不流畅

不稳定: 早期的浏览器为了实现一些强悍的功能比如视频、游戏他们是以插件的形式跑在浏览器上的,因为是单进程而且不稳定,所以他们崩溃了导致浏览器直接崩溃。 渲染引擎,由于js是跑在这里的,执行一些庞大的js导致渲染引擎崩溃也会导致浏览器的崩溃。

不流畅: 对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。 从上面的“单进程浏览器架构示意图”可以看出,所有⻚面的渲染模块、JavaScript执行环境以及插件都是
运行在同一个线程中的,这就意味着同一时刻只能有一个模块可以执行。

function loop() {  
    while (1) {  
        console.log("loop");  
    }  
}  
loop();

如果让这个脚本运行在一个单进程浏览器的⻚面里,你感觉会发生什么? 因为这个脚本是无限循环的,所以当其执行时,它会独占整个线程,这样导致其他运行在该线程中的模块就
没有机会被执行。因为浏览器中所有的⻚面都运行在该线程中,所以这些⻚面都没有机会去执行任务,这样
就会导致整个浏览器失去响应,变卡顿。这块内容要继续往深的地方讲就到⻚面的事件循环系统了,具体相
关内容我会在后面的模块中为你深入讲解。 除此之外内存泄漏也是一个导致不流畅的问题、运行一个比较复杂的程序导致内存无法被回收久而久之就卡了。

不安全: 插件是C++写他可以访问操作系统、页面也可以通过浏览器漏洞来获取权限等等。

多进程浏览器时代

截屏2023-05-08 上午9.56.52.png

Chrome 页面是单独运行在沙箱的进程【渲染进程】中的,插件也是运行在单独的进程中他们的通信是用IPC来通信的。

我们先看看如何解决不稳定的问题。由于进程是相互隔离的,所以当一个⻚面或者插件崩溃时,影响到的仅
仅是当前的⻚面进程或者插件进程,并不会影响到浏览器和其他⻚面,这就完美地解决了⻚面或者插件的崩
溃会导致整个浏览器崩溃,也就是不稳定的问题。

接下来再来看看不流畅的问题是如何解决的。同样,JavaScript也是运行在渲染进程中的,所以即使
JavaScript阻塞了渲染进程,影响到的也只是当前的渲染⻚面,而并不会影响浏览器和其他⻚面,因为其他
⻚面的脚本是运行在它们自己的渲染进程中的。所以当我们再在Chrome中运行上面那个死循环的脚本时,
没有响应的仅仅是当前的⻚面。

对于内存泄漏的解决方法那就更简单了,因为当关闭一个⻚面时,整个渲染进程也会被关闭,之后该进程所
占用的内存都会被系统回收,这样就轻松解决了浏览器⻚面的内存泄漏问题。

最后我们再来看看上面的两个安全问题是怎么解决的。采用多进程架构的额外好处是可以使用安全沙箱安全沙箱,你
可以把沙箱看成是操作系统给进程上了一把锁,沙箱里面的程序可以运行,但是不能在你的硬盘上写入任何
数据,也不能在敏感位置读取任何数据,例如你的文档和桌面。Chrome把插件进程和渲染进程锁在沙箱里
面,这样即使在渲染进程或者插件进程里面执行了恶意程序,恶意程序也无法突破沙箱去获取系统权限。
好了,分析完早期的Chrome浏览器后,相信你已经了解了浏览器采用多进程架构的必要性。

目前多进程架构

截屏2023-05-08 上午10.09.10.png

浏览器进程 负责界面的展示、用户的交互、存储、子进程的管理。

渲染进程 负责把html css js 变成用户可见的页面、Blink排版引擎和v8都是运行在这个进程当中的,每一个chrome 的tab都是一个进程 为了安全都运行在沙箱中。

GPU进程 网页 chrome的UI 是由GPU所绘制的。

网络进程 用来加载一些网络资源

插件进程 因为插件容易崩溃单独拿出放着带崩整个浏览器。

这就回答了 为什么页面一启动就4个进程了。

未来面向服务的架构 为了解决这些问题,在2016年,Chrome官方团队使用“面向服务的架构面向服务的架构”(ServicesOriented
Architecture,简称SOASOA)的思想设计了新的Chrome架构。也就是说Chrome整体架构会朝向现代操作系
统所采用的“面向服务的架构”方向发展,原来的各种模块会被重构成独立的服务(Service),每个服务
(Service)都可以在独立的进程中运行,访问服务(Service)必须使用定义好的接口,通过IPC来通信,
从而构建一个更内聚、松耦合、易于维护和扩展的系统构建一个更内聚、松耦合、易于维护和扩展的系统,更好实现Chrome简单、稳定、高速、安全的目
标。如果你对面向服务的架构感兴趣,你可以去网上搜索下资料,这里就不过多介绍了。
Chrome最终要把UI、数据库、文件、设备、网络等模块重构为基础服务,类似操作系统底层服务,下面是
Chrome“面向服务的架构”的进程模型图:

截屏2023-05-08 上午10.27.38.png

Chrome还提供灵活的弹性架构,在强大性能设备上会以多进程的方式运行基础服务,但是如果在资源
受限的设备上(如下图),Chrome会将很多服务整合到一个进程中,从而节省内存占用。

截屏2023-05-08 上午10.30.34.png 在系统资源不够的情况会自动的变为线程、动态扩展。 充分利用系统资源

总结 Chrome是以一个非常快速的速度在进化,越来越多的业务和应用都逐渐转至浏览器来开发,身
为开发人员,我们不能坐视不管,而应该紧跟其步伐,收获这波技术红利为开发人员,我们不能坐视不管,而应该紧跟其步伐,收获这波技术红利。 最初的浏览器都是单进程的,它们不稳定、不流畅且不安全,之后出现了Chrome,创造性地引入了多进程
架构,并解决了这些遗留问题。随后Chrome试图应用到更多业务场景,如移动设备、VR、视频等,为了支
持这些场景,Chrome的架构体系变得越来越复杂,这种架构的复杂性倒逼Chrome开发团队必须进行架构
的重构,最终Chrome团队选择了面向服务架构(SOA)形式,这也是Chrome团队现阶段的一个主要任
务。
鉴于目前架构的复杂性,要完整过渡到面向服务架构,估计还需要好几年时间才能完成。不过Chrome开发
是一个渐进的过程,新的特性会一点点加入进来,这也意味着我们随时能看到Chrome新的变化。