现在Chrome浏览器打开"掘金首页"竟开启了六个进程?

1,574 阅读12分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

1、前言

查了掘金很多很多的文章,发现绝大部分文章告诉我的都是四个进程,都是比较久的文章了,没有我想要的答案,没办法硬着头皮深入学习一下,这一深入我就发现了浏览器更多的秘密。

直接看图,先来看一下开启的进程到底有哪些,这里我是win10下运行的Chrome浏览器,并开启了一个标签页(其实就是咱掘金的首页)

image.png

先说一个次要的插件进程(扩展程序),我win10电脑的Chrome浏览器中装了很多插件,所以这里才会有这么多的插件进程。这里本可以一个也没有。

如果不包含插件进程,如图所示我的电脑当时就真的是开启了六个进程。这六个进程的大致总结如下:
1、浏览器主进程
2、GPU进程
3、渲染进程
4、网络进程(Network Service)
5、存储进程(Storage Serverice)
6、备用渲染程序进程

如果你是来看结果的,那么结论已经有了,可以点个赞收藏做个笔记走人了。

那接下来我们就来聊聊:

  1. 进程是什么呢?

  2. 为什么会有这么多的进程呢?

  3. 这些进程又是怎么工作的呢?

  4. 又是如何演变的呢?

带着这几个疑问有兴趣的话,继续往下看看吧,也许你会有一些收获。

2、进程和线程

2.1、进程与线程

前言中已经提到的进程,对我来说有一点陌生。其实我对进程和线程的理解一直模模糊糊的,所以索性去认真学习了一下,发现大佬有文章在此。

如果有对进程和线程的理解不是很到位,或者想学习一下,可以看一下阮一峰大佬的精彩文章,终点就是看完你一定会懂,文章链接:[进程与线程的一个简单解释],(www.ruanyifeng.com/blog/2013/0…) ,这里我就不班门弄斧了。

2.2、 进程与线程的区别和联系

进程可以理解是应用程序的执行程序,线程则是存在于进程内部,并执行该进程程序的一部分功能。一个程序的运行可能至少包含一个进程,同时一个进程中至少包含一个线程,而线程是由进程开启和管理的。

进程可以通过操作系统,启动另一个进程来执行不同的任务。此时,系统将为新进程分配不同的内存。如果两个进程间需要通信,他们可以利用 IPC(Inter Process Communication)的方式进行通信。许多应用程序都是以这种方式执行的,因此如果某个工作进程(例如一个选项卡)无响应,重启它,并不会影响相同应用程序的其他进程。

  1. 进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位)

  2. 线程是cpu调度的最小单位(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)

  3. 进程中如果任一一个线程出错,都有可能导致整个进程的崩溃。

  4. 一个进程中的线程与线程之间是可以共享进程中的数据的。

  5. 进程与进程之间的内容是相互隔离的,如果一个进程崩溃或者挂起了,是不会影响其他进程的(某些特殊的场景除外)。

  6. 进程与进程之间的通讯是通过IPC(Inter Process Communication)机制。

  7. 当进程关闭后,操作系统会回收进程中所占用的内存。

  8. 想到最后一点,进程中的多个线程可以一起工作,也就是所谓的并行运行。

2.3、多线程与单线程的区别

假设现在有一个场景:现在页面有十个视频要上传

  1. 方案一:十个视频一个接着一个进行上传,直到十个视频上传完毕。也就是串行上传(通过一个线程一直上传),耗费时间较长(十个视频大小一致,每个上传1分钟,十个上传完毕需要十分钟

  2. 方案二:十个视频,相同时间可以有三个视频一起上传,然后其中一个上传完毕,便可以继续上传其他视频,直到所有十个视频全部上传完毕为止。这就是并行上传(开启三个线程分别开始同时上传)在配置和宽带允许的情况下,上传的时间会大大缩短(视频大小与方案一一致,每次1分钟后同时上传完三个视频,下一次同样,三次之后上传完九个视频,剩余的一个将会由三个线程中的随意一个进行上传,总计4分钟)。

总结:多线程的并行上传比单线程的串行上传优势非常明显。

JS 中其实是没有线程概念的,所谓的单线程也只是相对于多线程而言。JS 的设计初衷就没有考虑这些,针对 JS 这种不具备并行任务处理的特性,我们称之为 “单线程”。 —— 来自知乎 “如何证明 JavaScript 是单线程的?” @云澹的回答

3、浏览器多进程架构

3.1、浏览器运行进程架构图

回头看前言的截图,你便轻松可知浏览器的运行是多进程的,因为我就开启了一个浏览器,竟然有那么多的进程开始运行了。

浏览器进程.jpg

从上图可见有很多的进程,接下来我来说说每个进程都是干什么的:

  • 浏览器主进程:主要负责界面显示、用户交互、子进程管理。(无论开多少个标签页,只会有一个主进程)

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

对于前端来说最重要的一个进程:渲染进程。

  • 网络进程:主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。(无论开多少个标签页,只会有一个网络进程)

  • GPU 进程:GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程。(无论开多少个标签页,只会有一个GPU进程)

  • 插件进程:主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。(根据插件的数量,每个插件都拥有自己的插件进程)

  • 备用渲染进程:用于配合渲染进程的使用。

  • 基础服务进程(实用程序):
    存储进程:用于存储数据的,从原来浏览器主进程中分离出来的。
    Audio进程:用于音频文件的处理。
    网络进程:其实也属于基础服务进程,只是它实在太重要了,所以我上面单独拎出来了。\

    之前很多基础服务进程是包含在其他进程中的,现在正在做面向服务的未来架构,未来会将更多其他的模块服务,单独封装成独立的基础服务进程,更加方便于系统的调度和管理。

3.2、浏览器进程架构演变

简单总结一下浏览器进程架构的演变:

  1. 单进程架构的浏览器时代

    • 不稳定--单进程中的插件模块或渲染模块以及其他模块的的崩溃就会引擎整个浏览器的崩溃。

    • 不流畅--单进程中的单线程运行,这就意味着同一时刻只能运行一个模块。

    • 不安全--在同一个进程的同一个线程中,通过插件或者脚本就可以轻松获得访问权限,使的恶意插件、恶意脚本非常的流行。

  2. 早期的多进程架构的浏览器时代

    • 在浏览器进程的基础上,将插件模块和渲染模块单独封装为进程了,进程与进程之间通信就通过 IPC机制了,而渲染进程也是一个Tab页一个。

    • 解决不稳定--进程与进程之前是相互隔离、不可访问的,当一个页面或者插件崩溃时,并不会影响其他页面或插件。

    • 解决不流畅--JavaScript运行在渲染进程中,即使发生了阻塞,影响的也只是当前标签页。

    • 解决不安全--采用了多进程后,也可以很好的采用安全沙箱,相当于只能在沙箱中独自运行,并访问不到外部的资源和权限,这样恶意插件或恶意代码的影响就大大的降低。

  3. 后期的多进程架构浏览器时代

    • 在早期多进程架构的基础上,又进行了升级。又将网络模块单独提取到网络进程中,同时又新增加了GPU进程满足新的需求。

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

    • 渲染进程--负责HTML、CSS和JavaScript转换为用户可以与之交互的网页,排版引擎Blink和JavaScript引擎(V8)都是运行在该进程当中,默认情况下,Chrome会为每个标签页创建自己的渲染进程,渲染进程都是运行在烧香模式下。

    • GPU进程--同时由于新需要的不断涌现,添加了GPU进程,GPU的初衷是为了实现CSS的3D效果,但是后来的网页UI界面都采用了GPU来进行绘制。

    • 网络进程--负责页面网络资源的加载,之前一直作为一个网络模块运行在浏览器主进程中,现在单独封装为一个独立的进程,并且一个浏览器只会存在一个网络进程,甭管它有多少个标签页。

    • 插件进程--每一个插件都拥有一个插件进程。

  4. 现代面向服务架构的浏览器时代

    • 这个就是文章开头的最新版的多进程面向服务的架构,不过仍然在改造中,毕竟是一个庞大的过程,每隔一段时间有了新的进展,便会发布新的版本出来。

注意:我这里讲的是算是最新的面向服务的浏览器多进程架构,浏览器从最开始的单进程,慢慢演变至今的过程,我这里就不总结了,已经有很多的文章介绍过了。

3.3、详解最新进程架构过程

根据上图所示,从进程的角度来分析一下,输入juejin.cn 之后发生的过程

  1. 首先打开Chrome浏览器,浏览器会准备好浏览器主进程GPU进程网络进程存储进程等,如有插件则会准备插件进程,其实打开浏览器之后,会默认打开一个空白的标签页,此时其实也准备好了渲染进程

  2. 在URL中输入juejin.cn,浏览器进程接收到用户输入的 URL 请求,浏览器进程便将该 URL 转发给网络进程。

  3. 网络进程通过 IPC 机制接收到消息之后,在网络进程中发起真正的 URL 请求。

  4. 接着网络进程接收到了响应头数据,便解析响应头数据,并通过 IPC 机制将数据转发给浏览器主进程

  5. 浏览器主进程接收到网络进程的响应头数据之后,通过IPC机制发送“提交导航 (CommitNavigation)”消息到渲染进程

  6. 渲染进程接收到“提交导航”的消息之后,便开始准备接收 HTML 数据,接收数据的方式是直接和网络进程建立数据管道。

  7. 最后渲染进程会向浏览器主进程“确认提交”,这是告诉浏览器主进程:“已经准备好接受和解析页面数据了”。

  8. 浏览器主进程接收到渲染进程“提交文档”的消息之后,便开始移除之前旧的文档,然后更新浏览器进程中的页面状态。

  9. 渲染进程在渲染页面的时候,会与GPU进程打交道,用于UI界面的绘制。

好了,对浏览器打开掘金首页的一个进程运行过程,做了一个简单的梳理,现在清晰多了

4、总结

  • 理解了进程和线程的的概念和区别

  • 知道进程在浏览器中扮演的角色

  • 清晰了浏览器的架构演变过程

  • 以及详细了解了浏览器运行时的进程运行流程

  • 知道对于前端来说那个进程最重要,原来就是渲染进程,JavaScript的V8引擎就运行在此,所以很多之前学习的知识点,都是运行在这里的

  • 好了,不啰嗦了,有时间再去深入学习一下渲染进程中的那些事