从IE到chrome-浏览器架构演变史

1,555 阅读9分钟

进程和线程

什么是线程

一个例子:

A = 1+1
B = 1+2
C = 1+3
D = A+B+C

我们现在需要计算上面的代码,需要运行4次任务:

  1. 任务A 计算1+1
  2. 任务B 计算1+2
  3. 任务C 计算1+3
  4. 任务D 计算A+B+C

正常情况下,在单线程程序中,是按照顺序计算,已知CPU计算是非常迅速的,主要耗时发生在IO上,那么我们能不能提高计算效率呢?

同一个进程只能通同时运行一个线程,只是因为单个线程CPU运行时间短,可以看上去是同时运行。在多线程程序中,计算方式是同时计算任务A、任务B、任务C。等三个任务都完成了再计算任务D。从时间来看,只需要两次任务就可以完成计算。

什么是进程

进程就是一个程序的运行实例。

启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。

线程不能单独存在于程序中,需要通过进程来进行启动和管理。一个进程可以是单线程的,也可以是多线程的。

单线程VS多线程
单线程VS多线程

线程是进程的子集,一个进程可以通过提升线程数量来提升执行效率。

进程和线程的特点

  1. 多线程能提升效率,那么代价是什么?

​ 通过使用多线程,提升运行效率,会出现一个问题。单个线程出错,会导致整个进程崩溃。以上面的四个任务为例,若任务1意外出错,会导致任务4无法进行,最终导致整个进程出错。

  1. 线程的数据共享

​ 因为所有线程都是在进程的内存空间中,所以每个线程都可以共享主进程的所有数据。

线程的数据共享
线程的数据共享
  1. 进程GC后,所有线程也会GC

​ 操作系统赋予内存空间的对象是进程,当进程GC,线程即使造成内存泄漏也会被正确的GC。

  1. 进程之间的数据相互隔离

​ 因为每个进程只有权限操作分配给自己的内存空间,所以每个进程的数据之前是相互独立的,如果一个进程崩溃了,其他进程是不会受到影响。进程间如果需要通信,则可以使用IPC(进程间通信)机制。

总结

  1. 单个线程出错,会导致整个进程崩溃。
  2. 线程的数据共享
  3. 进程GC后,线程也会GC
  4. 进程之间的数据相互隔离

开拓的单进程浏览器

在远古蛮荒的千禧年,包括IE在内的所有浏览器都是单进程,即浏览器的网络、渲染、js环境等都是运行在同一个浏览器进程里面。

单进程浏览器架构
单进程浏览器架构

单线程浏览器的问题

1.不稳定

从上面进程和线程知识点,我们知道,单个线程出错,会导致整个进程崩溃,所以在远古的单进程浏览器中,就会出现特别不稳定的情况:当某一个线程崩溃。特别是第三方插件和运行js代码js环境,整个浏览器就会崩溃。

2.不安全

上面我们知道,线程的数据共享,所以第三方插件能访问到整个浏览器的隐私数据,就会造成页面数据从浏览器层面造成信息安全,而这种高维度的入侵,是也防止不了。

3.不流畅

同一个进程只能通同时运行一个线程,只是因为单个线程CPU运行时间短,可以看上去是同时运行。但是在单进程浏览器中,若出现js线程死循环等长时间占据运行的时候,整个浏览器就会出现假死状态。

以上就是单线程浏览器的缺点,不稳定、不流畅、不安全。

那是一段不堪回首的历史,单线程浏览器只解决了能用好用只能留给下一个时代。

革新的多进程浏览器

chrome王者降临

我们知道,自从chrome发布后,IE就被扫进了垃圾堆。那么原因是什么?能让消费者用脚投票让谷歌干翻微软,甚至Edge也直接使用chromium内核。

这是一张早期chrome架构

早期chrome架构
早期chrome架构

可以看到,chrome将最令人担忧即需要运行开发者代码的两个模块,放进了单独的进程中。

让插件和渲染进程相互隔离,所以当一个页面渲染或者插件崩溃时,影响到的仅仅是当前的页面进程或者插件进程,并不会影响到浏览器和其他页面,这就从架构层面解决了页面或者插件的崩溃会导致整个浏览器崩溃,解决了不稳定问题

我们知道进程之间的数据相互隔离,通过沙箱,也从架构层面防止恶意插件可以拿到浏览器的用户数据。解决了不安全的问题。

同样,因为运行js的渲染进程也被独立出来,所以 JavaScript 阻塞渲染进程,只会影响当前渲染页面,而并不会影响浏览器主进程和其他页面的渲染进程,所以在 多进程的浏览器中运行上面诸如死循环代码,仅仅只会影响是前页面。解决了单线程浏览器时代留下的不稳定的问题。

不断发展的多线程架构

现阶段多进程架构
现阶段多进程架构

更新后的Chrome 浏览器进程包括:1 个浏览器主进程、1 个 GPU 进程、1 个网络进程、多个渲染进程(根据打开的tab数量而定)和多个插件进程。

  1. 主进程

    主要负责界面显示、用户交互、子进程IPC管理,同时提供数据存储等功能。

  2. GPU 进程

    负责页面部分可以使用GPU渲染的绘制工作。诸如CSS3的3D动画渲染。

  3. 网络进程

    负责页面网络资源的加载。

  4. 渲染进程

    负责将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中。默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。

  5. 插件进程

    主要是负责插件的运行。

那么问题来了

如果仅仅打开一个tab,浏览器会启用多少进程?

可以通过点击chrome任务管理器查看答案。

答案是至少4个。一个主进程、一个GPU进程、一个网络进程、一个渲染进程。为什么说是四个呢?可能浏览器会有插件进程。

多进程架构提升了浏览器的稳定性、流畅性和安全性,作为代价不可避免地带来了一些问题:

1.更高的资源占用

​ 因为每个进程都会包含公共基础结构的副本(如 JavaScript 运行环境),这就意味着浏览器会消耗更多的内存资源。(这就是chrome越来越吃内存的原因)

2.更复杂的体系架构

​ 浏览器各模块之间耦合性高、扩展性差等问题,会导致现在的架构已经很难适应新的需求了。

对于上面这两个问题,Chrome 团队一直在寻求一种弹性方案,既可以解决资源占用高的问题,也可以解决复杂的体系架构的问题。

未来已来的船新架构

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

面向服务架构
面向服务架构

为什么说未来已来。可以打开一个能播放音频的页面,通过任务管理器查看,会发现有一个单独的audio进程。说明chrome已经开始向SOA改造了,处于向SOA长期迭代过渡阶段。

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

低性能设备
低性能设备

总结

  1. 进程和线程有四个特点

    1. 单个线程出错,会导致整个进程崩溃。
    2. 线程的数据共享
    3. 进程GC后,线程也会GC
    4. 进程之间的数据相互隔离
  2. 远古单进程浏览器不稳定不流畅不安全

  3. chrome通过引入多进程架构,解决了单进程浏览器不稳定不流畅不安全问题。但也留下了许多问题,更高的资源占用更复杂的体系架构

  4. 2016年引入SOA(面向服务的架构),希望构建一个更内聚、松耦合、易于维护和扩展的系统。并已缓慢的实现了。

- END -