1. 浏览器的架构演进

1. 浏览器的架构演进

浏览器的架构经历了早期的单进程浏览器(2007) --> 多进程浏览器(现在) --> 面向服务的架构SOA(未来)。这里我们暂不讨论未来的SOA架构,仅分析单进程到多进程浏览器的演进历史。

在分析单进程与多进程之前,我们需要先知道线程与进程。

进程和线程

在讨论单进程与多进程之前,我们需要一些前置知识,什么是并行处理。

并行处理

计算机中的并行处理就是同一时刻处理多个任务,比如我们要计算下面这三个表达式的值,并显示出结果。

A = 1+2
B = 20/5
C = 7*8

在编写代码的时候,我们可以把这个过程拆分为4个任务:

任务 1:计算 A=1+2;

任务 2:计算 B=20/5;

任务 3:计算 C=7*8;

任务 4:显示最后计算的结果。

正常情况下程序可以使用单线程来处理,也就是分四步按照顺序分别执行这四个任务。

如果采用多线程(3),会怎么样呢?我们只需分“两步走”:第一步,使用三个线程同时执行前三个任务;第二步,再执行第四个显示任务。

通过对比分析,你会发现用单线程执行需要四步,而使用多线程只需要两步。因此,使用并行处理能大大提升性能。

image-20200822153129121.png

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

总结来说,进程和线程之间的关系有以下 4 个特点。

  1. 进程中的任意一线程执行出错,都会导致整个进程的崩溃

  2. 线程之间共享进程中的数据

    image-20200822153551207.png

    从上图可以看出,线程 1、线程 2、线程 3 分别把执行的结果写入 A、B、C 中,然后线程 2 继续从 A、B、C 中读取数据,用来显示执行结果。

  3. 当一个进程关闭后,操作系统会回收进程所占用的内容。

  1. 进程之间的内容相互隔离

    进程隔离是为保护操作系统中进程互不干扰的技术,每一个进程只能访问自己占有的数据,也就避免出现进程 A 写入数据到进程 B 的情况。正是因为进程之间的数据是严格隔离的,所以一个进程如果崩溃了,或者挂起了,是不会影响到其他进程的。如果进程之间需要进行数据的通信,这时候,就需要使用用于进程间通信(IPC)的机制了。

总结

  1. 所谓进程就是启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程的一个运行环境

  2. 线程是由进程创造的,且一个线程,同一时刻只能执行一个任务。

  3. 一个进程可以包含多个线程,且线程之间可以共享进程中的数据(进程存在一个数据池)

  4. 进程之间不能直接进行数据通信,需要通过进程间通信IPC(InterProcess communication)

单进程浏览器时代

顾名思义,单进程浏览器是指浏览器的所有功能模块都是运行在同一个进程里,这些模块包含了网络、插件、JavaScript 运行环境、渲染引擎和页面等。其实早在 2007 年之前,市面上浏览器都是单进程的。单进程浏览器的架构如下图所示:

image-20200822154046799.png

如此多的功能模块运行在一个进程里,是导致单进程浏览器不稳定、不流畅和不安全的一个主要因素。下面我就来一一分析下出现这些问题的原因。

缺点

不稳定

早期浏览器需要借助于插件来实现诸如 Web 视频、Web 游戏等各种强大的功能,比如Flash,但是插件是最容易出问题的模块,并且还运行在浏览器进程之中,所以一个插件的意外崩溃会引起整个浏览器的崩溃。

除了插件之外,渲染引擎模块也是不稳定的,通常一些复杂的 JavaScript 代码就有可能引起渲染引擎模块的崩溃。和插件一样,渲染引擎的崩溃也会导致整个浏览器的崩溃。

不流畅

前面说过,一个线程,在同一时刻只能执行一个任务。在上图的页面线程中,页面的渲染模块、JavaScript 执行环境以及插件都是运行在同一个线程中的,这就意味着同一时刻只能有一个模块可以执行。

而如果让一个无限循环的脚本运行在一个单进程的浏览器的页面里。会发生什么?

function freeze(){
    while(1){
        console.log('freeze')
    }
}
freeze()

因为这个脚本是无限循环的,所以当其执行时,它会独占整个线程,这样导致其他运行在该线程中的其他模块就没有机会被执行。而浏览器中所有的页面都运行在该线程中,所以这些页面都没有机会去执行任务,这样就会导致整个浏览器失去响应,变卡顿。

除了上述脚本或者插件会让单进程浏览器变卡顿外,页面的内存泄漏也是单进程变慢的一个重要原因。通常浏览器的内核都是非常复杂的,运行一个复杂点的页面再关闭页面,会存在内存不能完全回收的情况,这样导致的问题是使用时间越长,内存占用越高,浏览器会变得越慢。

不安全

这里依然可以从 插件和页面脚本的两个方面来解释该原因。

插件可以使用C/C++等代码编写,通过插件可以获取到操作系统的任意资源,当你在页面运行一个插件也就意味着这个插件能完全操作你的电脑,如果是个恶意插件,那么它就可以释放病毒,窃取你的帐号密码,引发安全性问题。

至于页面脚本,它可以通过浏览器的漏洞来获取系统权限,这些脚本获取系统权限之后也可以对你电脑做一些恶意的事情,同样也会 引发安全性问题。

多进程浏览器时代

早期多进程架构

你可以先看看下面这张图,这是 2008 年 Chrome 发布时的进程架构。

image-20200822155914608.png

从图中可以看出,Chrome 的页面是运行在单独的渲染进程中的,同时页面里的插件也是运行在单独的插件进程之中,而进程之间是通过 IPC 机制进行通信(如图中虚线部分)。

我们先看看如何解决不稳定的问题。

由于进程是隔离的,所有当一个页面或者插件崩溃,影响到的仅仅是当前的页面进程或者插件进程,并不会影响到浏览器和其他页面 。这就完美解决里页面或插件的崩溃会导致浏览器崩溃,也就是不稳定的原因。

接下来再来看看不流畅的问题是如何解决的。

同样,JS代码也是运行在渲染进程中,即便是JS阻塞里显然进程,影响的也只是当前的渲染页面,而不会影响浏览器和其他页面,因为其他页面的脚本是运行在它们自己的渲染进程中

最后我们再来看看上面的两个安全问题是怎么解决的。

采用多进程架构的额外好处是可以使用安全沙箱,你可以把沙箱看出是操作系统给进程上了一把锁,沙箱里面的程序可以运行,,但是不能在你的硬盘上写入任何数据,也不能再敏感位置读取任何数据。

chrome把插件进程渲染进程锁在了沙箱里,这样即使在渲染进程或者插件进程里面执行了恶意程序,恶意程序也无法突破沙箱去获取系统权限。

目前多进程架构

image-20200822160932997.png

从图中可以看出,最新的chrome浏览器包括:一个浏览器 主进程、一个GPU 进程、一个网络 进程

多个渲染 进程和多个插件 进程

下面我们来逐个分析下这几个进程的功能

浏览器进程:主要负责界面显示、用户交互、子进程管理、同时提供存储等功能

渲染进程:主要负责将HTML、CSS、JS转换为用户可以与之交互的网页,排版引擎Blink和JS的V8引擎都运行在该进程中,默认情况下,chrome会为每个页面创建一个渲染进程,处于安全考虑,渲染进程都运行在沙箱模式下

GPU进程:主要负责实现3D CSS效果

网络进程:主要负责页面的网络资源加载。

插件进程:主要负责插件的运行,因插件易奔溃,所有需要通过插件进程来隔离。

缺点
  • 更高的资源占用:因为每个进程都会包含公共基础结构的副本(如JS运行环境),这就意味着浏览器会消耗更多的内存资源

  • 更复杂的体系架构:浏览器个模块之间耦合性高,扩展性差等问题,会导致现在的架构已经很难适应新的需求。

未来面向服务的架构(SOA)

为了解决这些问题,在 2016 年,Chrome 官方团队使用“面向服务的架构”(Services Oriented Architecture,简称 SOA)的思想设计了新的 Chrome 架构。也就是说 Chrome 整体架构会朝向现代操作系统所采用的“面向服务的架构” 方向发展,原来的各种模块会被重构成独立的服务(Service),每个服务(Service)都可以在独立的进程中运行,访问服务(Service)必须使用定义好的接口,通过 IPC 来通信,从而构建一个更内聚、松耦合、易于维护和扩展的系统,更好实现 Chrome 简单、稳定、高速、安全的目标。

image-20200822162557315.png

总结

  • 最初的浏览器都是单进程的,它们不稳定、不流畅且不安全,之后出现了 Chrome,创造性地引入了多进程架构,并解决了这些遗留问题。但随着Chrome 的架构体系变得愈发复杂,最终 Chrome 团队选择了面向服务架构(SOA)形式。

  • 在单进程浏览器中,所有的页面都共享着同一套JavaScript运行环境,同样,对于存储Cookie也都是在一个线程里面操作的。

  • 在多进程浏览器中、默认情况下,chrome会为每个页面创建一个渲染进程,但如果该页面是同源的,新页面就会复用父页面的渲染进程。官方把这个默认策略叫process-per-site-instance。

  • 早期多进程架构:主进程、渲染进程、插件进程

  • 现代多进程架构:主进程、渲染进程、插件进程、GPU进程、网络进程


评论 抢沙发

表情
首页上一页12下一页尾页