当前位置: 首页 > 科技观察

Chrome架构:为什么只有1个页面打开时有4个进程?

时间:2023-03-17 19:23:44 科技观察

无论是要设计高性能的Web应用,还是要优化现有的Web应用,都需要了解浏览器中的网络流程、页面渲染流程、JavaScript执行流程、Web安全理论,而这些功能则分散在浏览器的各种功能组件。多而散。如何学习掌握它?通过学习浏览器的多进程架构,可以把这些分散的知识点串起来,形成一个网络,让自己站在更高的维度去理解Web应用。因此,学习浏览器的多进程架构是很有必要的。需要说明的是,我所有的分析都是基于Chrome浏览器。浏览器那么多,为什么选择Chrome浏览器?因为Chrome、MicrosoftEdge,以及国内大部分主流浏览器都是基于Chromium进行二次开发的;而Chrome是Google的官方发布版,其功能与Chromium基本相同,仅存在一些产品层面的差异;加上Chrome是目前世界上使用最多的浏览器,所以Chrome最具代表性。在开始之前,我们先来看看Chrome打开一个页面需要启动多少个进程?您可以点击Chrome浏览器右上角的“选项”菜单,选择“更多工具”子菜单,点击“任务管理器”,即可打开Chrome任务管理器窗口,如下图:Chrome任务管理器窗口与Windows任务管理器相同,Chrome任务管理器也用于显示Chrome在运行过程中使用的进程信息。从图中可以看出,Chrome启动了4个进程。您可能很好奇,但只打开了1页。为什么要启动这么多进程?在回答这个问题之前,我们需要了解一下进程的概念,但是由于很多人容易混淆进程和线程的概念,影响了后续其他概念的理解,所以这里我先解释一下这两个概念以及它们之间的关系他们给你。进程和线程不过,在介绍进程和线程之前,我需要解释一下什么是并行处理,因为如果理解了并行处理的概念,那么理解进程和线程的关系就会容易很多。什么是并行处理?计算机中的并行处理就是同时处理多个任务。例如,我们要计算以下三个表达式的值并显示结果。A=1+2B=20/5C=7*8复制代码在写代码的时候,我们可以把这个过程分成四个任务:任务1是计算A=1+2;任务2是计算B=20/5;任务3是计算C=7*8;任务4是显示最终的计算结果。一般情况下,程序可以使用单线程处理,即四个任务分四步依次执行。如果使用多线程会怎样?我们只需要把它分成“两步”:第一步是用三个线程同时执行前三个任务;第二步,执行第四个显示任务。通过对比分析,你会发现用单线程执行需要四步,而使用多线程只需要两步。因此,使用并行处理可以大大提高性能。ThreadVSProcess多线程可以并行处理任务,但是一个线程不能单独存在,它是由一个进程启动和管理的。那么什么是进程呢?进程是程序的运行实例。详细解释就是当一个程序启动时,操作系统会为程序创建一块内存,用于存放代码、运行数据,以及一个执行任务的主线程。我们称这样的运行环境为进程。为了让大家更好的理解上面的计算过程,我画了下面的对比图:单线程和多线程进程对比图从图中可以看出,线程依附于进程,使用的是多线程并行在进程中处理可以提高计算效率。概括起来,进程与线程的关系有以下四个特点。1、进程中任何一个线程执行错误都会导致整个进程崩溃。我们可以模拟如下场景:A=1+2B=20/0C=7*8复制代码上面三个表达式我稍微修改了一下,在计算B的值的时候,我把表达式的分母改成了0,当线程执行到B=20/0,由于分母为0,线程会执行错误,导致整个进程崩溃,当然其他两个线程的结果也就没了。2、进程中的数据在线程间共享。如下图所示,线程可以读写进程的公共数据。线程间共享进程中的数据示意图从上图可以看出,线程1、线程2、线程3分别将执行结果写入A、B、C,然后线程2继续从中读取A、B、C取数据显示执行结果。3、当一个进程关闭时,操作系统会回收该进程占用的内存。当一个进程退出时,操作系统会回收该进程申请的所有资源;即使其中的任何线程由于操作不当导致内存泄漏,当进程退出时,内存也会被正确回收。比如之前的IE浏览器支持很多插件,而这些插件很容易造成内存泄漏,也就是说只要浏览器打开,内存占用就可能会增加,但是当浏览器进程关闭时,这些内存泄漏会被系统回收。4、进程之间的内容相互隔离。进程隔离是一种保护操作系统中的进程不相互干扰的技术。每个进程只能访问自己拥有的数据,防止了进程A向进程B写入数据的情况。正是因为进程之间的数据是严格隔离的,所以如果一个进程崩溃或者挂掉,不会影响到其他进程。如果进程之间需要进行数据通信,这时候就需要使用进程间通信(IPC)的机制。单进程浏览器时代,了解了进程和线程之后,我们再来看看单进程浏览器的架构。顾名思义,单进程浏览器是指浏览器的所有功能模块都运行在同一个进程中,包括网络、插件、JavaScript运行环境、渲染引擎和页面。其实早在2007年,市面上的浏览器都是单进程的。单进程浏览器的架构如下图所示:单进程浏览器架构示意图这么多的功能模块运行在一个进程中,这是导致单进程浏览器不稳定的一大因素,不顺畅,不安全。下面我来一一分析出现这些问题的原因。问题一:不稳定早期的浏览器需要插件来实现网页视频、网页游戏等各种强大的功能,但是插件是问题最多的模块,而且它还运行在浏览器进程中,所以一个插件意外崩溃浏览器崩溃整个浏览器。除了插件之外,渲染引擎模块也不稳定,通常一些复杂的JavaScript代码可能会导致渲染引擎模块崩溃。与插件一样,渲染引擎崩溃可能导致整个浏览器崩溃。问题二:不流畅从上面的“单进程浏览器架构图”可以看出,所有的页面渲染模块、JavaScript执行环境、插件都在同一个线程中运行,也就是说只能执行一个模块.例如,以下无限循环脚本:functionfreeze(){while(1){console.log("freeze");}}freeze();复制代码如果让这个脚本运行在单进程的浏览器页面中,你认为会发生什么?因为这个脚本是死循环的,当它执行的时候,会独占整个线程,这样运行在这个线程中的其他模块就没有机会被执行。因为浏览器中的所有页面都运行在这个线程中,这些页面没有机会执行任务,就会导致整个浏览器失去响应而卡死。如果要继续深入讲这个内容,就要到页面的事件循环系统了。具体的相关内容我会在后面的模块中为大家讲解。除了上述脚本或插件会导致单进程浏览器卡顿外,页面内存泄漏也是导致单进程变慢的重要原因。通常浏览器的内核非常复杂。如果运行一个复杂的页面,然后关闭该页面,内存就无法完全回收。这样造成的问题是使用时间越长,内存占用越高,浏览器就会变慢。问题三:不安全原因还是可以从插件和页面脚本两个方面来解释。可以用C/C++等代码编写插件,通过插件可以获取操作系统的任何资源。当您在页面上运行插件时,意味着该插件可以完全运行您的计算机。如果是恶意插件,可以释放病毒,窃取您的账号密码,造成安全问题。至于页面脚本,可以通过浏览器漏洞获取系统权限。这些脚本在获得系统权限后,还可以对你的电脑做一些恶意的事情,同样会造成安全问题。这些都是当时浏览器的特点,不稳定,不流畅,不安全。这是一段不堪回首的往事,也许你没有经历过,但你可以想象这样一个场景:当你正在使用浏览器打开多个页面时,突然某个页面崩溃或失去响应,随之而来的是整个浏览器崩溃还是没有反应,然后你发现你写给老板的邮件页面也不见了。这时候,你的心情会不会像翻页一样崩溃?多进程浏览器时代幸运的是现代浏览器已经解决了这些问题,怎么解决呢?这就不得不说到我们的“多进程浏览器时代”了。对于早期的多进程架构,可以先看下图,这是2008年Chrome发布时的进程架构。早期的Chrome进程架构图从图中可以看出,Chrome页面运行在一个单独的渲染进程中,而页面中的插件也是运行在一个单独的插件进程中,进程间通过IPC机制进行通信(图中虚线)。我们先来看看如何解决不稳定问题。由于进程之间相互隔离,当某个页面或插件崩溃时,只影响当前页面进程或插件进程,不影响浏览器和其他页面,完美解决了页面或插件的问题-崩溃。崩溃会导致整个浏览器崩溃,也就是不稳定问题。接下来我们看看怎么解决不流畅的问题。同样,JavaScript也是运行在渲染进程中的,所以即使JavaScript阻塞了渲染进程,也只是影响当前渲染页面,不会影响浏览器和其他页面,因为其他页面的脚本都运行在自己的渲染过程。所以当我们在Chrome中运行上面的无限循环脚本时,只有当前页面没有响应。内存泄漏的解决方法就更简单了,因为当一个页面关闭时,整个渲染进程也会关闭,然后进程占用的内存会被系统回收,这样就轻松解决了浏览器页面的内存泄漏问题.最后,我们来看看如何解决以上两个安全问题。使用多进程架构的额外优势是您可以使用安全沙箱。您可以将沙箱视为操作系统对进程的锁定。沙盒中的程序可以运行,但不能在硬盘上写入任何文件。数据,也不能在敏感位置读取任何数据,例如您的文档和桌面。Chrome将插件进程和渲染进程锁定在沙箱中,这样即使在渲染进程或插件进程中执行了恶意程序,恶意程序也无法突破沙箱获取系统权限。好了,分析完早期的Chrome浏览器,相信你已经明白浏览器采用多进程架构的必要性了。目前的多进程架构,不过Chrome的发展是滚滚向前的。与之前相比,现在的架构有很多新的变化。我们来看看最新的Chrome进程架构,可以参考下图:最新的Chrome进程架构图从图中可以看出,最新的Chrome浏览器包括:1个主浏览器进程和1个GPU进程,1个网络(NetWork)进程、多个渲染进程和多个插件进程。下面我们一一分析这些进程的作用。浏览器进程。主要负责界面展示、用户交互、子进程管理,并提供存储等功能。渲染过程。核心任务是将HTML、CSS和JavaScript转换成用户可以与之交互的网页。排版引擎Blink和JavaScript引擎V8都运行在这个过程中。默认情况下,Chrome会为每个Tab标签创建一个渲染进程。出于安全原因,渲染过程以沙盒模式运行。显卡进程。事实上,在Chrome刚发布的时候,并没有GPU进程。使用GPU的初衷是为了实现3DCSS的效果,但随后网页和Chrome的UI界面选择使用GPU进行绘制,这使得GPU成为了浏览器的共同需求。最后,Chrome还在其多进程架构之上引入了GPU进程。网络过程。主要负责加载页面的网络资源。它曾经作为一个模块运行在浏览器进程中,但直到最近才独立出来,成为一个单独的进程。插件进程。主要负责插件的运行。因为插件很容易崩溃,所以需要通过插件进程进行隔离,保证插件进程的崩溃不会对浏览器和页面造成影响。说到这里,现在你应该可以回答文章开头提到的问题了:为什么只打开1页时有4个进程?因为打开1个页面至少需要1个网络进程、1个浏览器进程、1个GPU进程和1个渲染进程共计;如果打开的页面有插件在运行,则需要再添加一个插件进程。但是任何事情都有两个方面。多进程模型虽然提高了浏览器的稳定性、流畅性和安全性,但也不可避免地带来了一些问题:资源占用较高。因为每个进程都会包含一份公共基础设施(比如JavaScript运行时环境),这意味着浏览器会消耗更多的内存资源。更复杂的架构。浏览器模块之间的耦合度高、扩展性差等问题将导致现有架构难以适应新的需求。针对以上两个问题,Chrome团队一直在寻找一种灵活的解决方案,既能解决资源占用高的问题,又能解决架构复杂的问题。未来面向服务的架构为了解决这些问题,2016年,Chrome官方团队采用“面向服务的架构”(SOA)的思想设计了全新的Chrome架构。也就是说,Chrome的整体架构将向现代操作系统所采用的“面向服务的架构”发展。运行在进程中,接入服务(Service)必须使用定义的接口通过IPC进行通信,从而构建一个更内聚、松耦合、易于维护和扩展的系统,更好地实现简单、稳定、高-ChromeTarget的速度和安全性。如果大家对面向服务的架构感兴趣,可以上网搜索资料,这里就不做过多介绍了。Chrome最终会将UI、数据库、文件、设备、网络等模块重构为基础服务,类似于操作系统的底层服务。以下是Chrome“面向服务架构”的流程模型图:迭代过程。Chrome正在逐步构建Chrome基础服务(ChromeFoundationService),如果你把Chrome看成是一个“便携式操作系统”,那么ChromeFoundationService就可以看作是操作系统的“基础”系统服务层。同时,Chrome还提供了灵活弹性的架构。在功能强大的设备上,基本服务将以多进程方式运行。但是,在资源有限的设备上(如下图),Chrome会将很多服务集成到一个进程中,从而节省内存使用量。在资源不足的设备上,将服务合并到浏览器进程中。今天就到此为止。让我简单梳理总结一下今天的内容。在这篇文章中,我主要从Chrome进程架构的角度分析浏览器的进化史。原来的浏览器都是单进程的,不稳定,不流畅,不安全,后来Chrome出现了,创造性地引入了多进程架构,解决了这些遗留问题。后来,Chrome尝试应用于更多的业务场景,比如移动设备、VR、视频等,为了支持这些场景,Chrome的架构体系变得越来越复杂。这种架构的复杂性迫使Chrome开发团队进行了架构重构,Chrome团队最终选择了面向服务的架构(SOA)形式,这也是Chrome团队现阶段的一项重大工作。鉴于目前架构的复杂性,估计需要数年时间才能完成向面向服务架构的完全过渡。不过,Chrome的发展是一个循序渐进的过程,新的功能会一点一点地加入进来,这意味着我们随时都能看到Chrome的新变化。总的来说,Chrome的发展速度非常快,越来越多的业务和应用逐渐转移到浏览器上进行开发。作为开发者,我们不应该坐视不理,而应该跟上它的步伐,收获这一波技术红利。思考时间的最后,留给大家一个思考的问题:回顾浏览器的进化历程,您认为推动浏览器发展的主要驱动力是什么?