01 | Chrome架构:仅仅打开了1个页面,为什么有4个进程?


一、操作

在Chrome浏览器中,我们点击右上角三个点–更多工具–任务管理器。
会看到打开一个页面,启动了多个进程。
在进行每个进程分析前,先明确下线程与进程之间的关系。

二、线程 VS 进程

  • 进程:一个进程就是一个运行实例–启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,这样的一个运行环境就叫做进程。
  • 线程:线程不能单独存在,需要由进程来启动和管理。
    线程与进程的关系:
  1. 进程中任一线程执行出错,整个进程都会崩溃。
  2. 线程之间共享进程中的数据。
  3. 当一个进程关闭之后,操作系统会回收进程所占用的内存。
  4. 进程之间的内容相互隔离。

三、单进程浏览器时代

单进程浏览器是指所有功能模块(网路、插件、JS运行环境、渲染引擎等)都是运行在同一个进程里,2007年以前,市面上浏览器都是单进程架构。
这种结构模式:不稳定、不流畅、不安全。

四、多进程浏览器时代

  • 进程之间通过IPC机制进行通信
  • 不稳定问题解决:由于进程的隔离性,当一个页面或插件崩溃时,不会影响到浏览器的其他页面
  • 不流畅问题解决:即使JS的执行阻塞了渲染进程,也只是影响当前页面
  • 不安全问题解决:安全沙箱
    最新的Chrome浏览器包括:一个浏览器主进程一个GPU进程一个网络进程多个渲染进程多个插件进程
    存在问题:更高的资源占用和更复杂的体系结构。

五、未来面向服务的架构

2016年,Chrome官方团队使用“面向服务的架构”(SOA)的思想设计了新的Chrome架构。

02 | TCP协议:如何保证页面文件能被完整送达浏览器?


衡量web性能的一个重要指标叫"FP(First Paint)",指页面加载到首次开始绘制的时长。影响FP的重要因素有一个网络加载速度。
网络加载的过程就是数据包的传输过程,站在数据包角度,从“数据包如何送达主机”,“主机如何将数据包转交给应用”,“数据如何被完整送达应用程序”三个方面来分析。

一、IP:把数据包送达目的主机

  • 数据包要在互联网上进行传输,要符合网际协议IP(Internet Protocol)标准
  • 计算机的地址称为IP地址,访问任何网站实际上只是你的计算机向另外一台计算机请求信息。
  • IP头是IP数据包开头的信息,包含IP版本、源IP地址、目标IP地址、生存时间等信息。

二、UDP:把数据包送达应用程序

IP是非常底层的协议,只负责把数据包传达给目标主机,但是并不知道交给哪个应用程序。
因此需要基于IP之上开发能和应用打交道的协议,最常见的协议就是UDP协议–User Datagram Protocol(用户数据包协议)
UDP通过端口号把数据包分发给正确的程序。
UDP可以校验数据是否正确,但是不提供重传机制,只是丢弃当前的包。虽然UDP不能保证数据的准确性,但是传输速度非常快。

三、TCP:把数据完整的送达应用程序

TCP(Transition Control Protocol,传输控制协议),是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP提供重传机制、引入了数据包排序机制。

一个完整的TCP连接的生命周期包含了“建立连接“、”传输数据“、“断开连接”三个阶段。
建立连接阶段:这个阶段通过三次握手来建立客户端与服务端之间的连接,它们之间总共要发送三个数据包以确认连接的建立。
传输数据阶段:该阶段,接收端需要对每个数据包进行确认操作。
断开连接阶段:四次挥手来保证双方都能断开连接。

03|HTTP请求流程:为什么很多站点第二次打开速度会很快


HTTP协议是建立在TCP连接基础之上的。
HTTP是一种允许浏览器向服务器获取资源的协议,是Web的基础。
浏览器端发起HTTP请求流程如下:

一、构建请求

浏览器构建请求行信息,构建好后,浏览器准备发起网络请求。

二、查找缓存

在准备发起网路请求阶段,浏览器偷偷的在它的缓存中查询是否有要请求的资源。
若有:拦截请求,返回资源副本,直接结束请求。
若缓存查找失败:继续下一步。

三、准备IP地址和端口号

浏览器第一步会请求域名系统DNS返回域名对应的IP,如果没有特别指明端口号,则默认为80。 (浏览器提供了DNS数据缓存服务,若缓存过也就不会去请求,直接解析。从而减少一次网络请求)

四、等待TCP队列

拿到IP地址与端口号后,还需要在TCP队列中排队才能建立TCP连接。
这是因为:Chrome有个机制,同一个域名同时最多只能建立6个TCP连接,若此刻同时有10个请求发生。则四个会进入TCP队列进行排队。 当然,若当前请求数量少于6个,则会直接进入下一步。

五、建立TCP连接

建立TCP连接,上一节我们已经知道,一个完整的TCP连接过程包括“建立连接”、“数据传输”、“断开连接“三个阶段。

六、发送HTTP请求

HTTP请求是在TCP连接的数据传输阶段工作的,这个时候浏览器向服务器发送请求行,它包括请求方法、请求URI、HTTP版本协议。HTTP中的数据在这个通信过程中传输。

七、服务端处理HTTP请求流程

返回请求:通过 ‘curl -i domainName’命令,可以返回响应行(协议版本和状态码)、响应头(服务端返回请求的时间、Cookie、返回的数据类型等)、响应体信息.
通常情况,一旦服务器向客户端返回了请求数据,它就要关闭TCP连接,但是如果浏览器或者服务器设置了Connection:keep-alive,那么TCP连接在发送后将仍保持打开状态。保持TCP连接可以省去下次请求时需要建立连接的时间,提升资源加载速度。

八、问题解答

  1. 为什么很多站点第二次打开速度会很快?

主要原因肯定是第一次加载页面的过程中,缓存了一些数据(从上面的过程分析,我们知道DNS缓存和页面资源缓存这两块数据是会被浏览器缓存起来的).
网站把很多资源都缓存到了本地,浏览器缓存直接使用本地副本来回应请求,而不会产生真实的网络请求,从而节省了时间。

  1. 登录状态是如何保持的

简单地说,如果服务器端发送的响应头内有 Set-Cookie 的字段,那么浏览器就会将该字段的内容保持到本地。当下次客户端再往该服务器发送请求时,客户端会自动在请求头中加入 Cookie 值后再发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到该用户的状态信息。

04| 导航流程:从输入URL到页面展示,这中间发生了什么?

从输入URL到页面展示

1.用户输入

如果是搜索内容,地址栏使用浏览器默认的搜索引擎合成带关键字的URL,如果符合URL规则,则合成完整的URL。

2.URL请求过程

浏览器主进程通过进程间通信(IPC)把URL请求发送到网络进程,网络进程接收到URL请求后,会发起真正的URL请求。
首先,浏览器会查找本地缓存是否缓存了该资源,如果缓存则直接返回资源给浏览器主进程,如果没有缓存,那么直接进入网络请求流程:请求前的第一步是DNS解析,用来获取域名对应的IP地址,如果是HTTPS协议,还需要建立TLS连接。
接下来就是利用IP地址和服务器建立TCP连接,连接建立后,浏览器端会构建请求行、请求头等信息。
服务器接收到请求信息后,根据请求信息生成响应行、响应头发给网络进程。网络进程接收到后,开始解析响应数据。

3.准备渲染进程

同一站点:协议相同、根域名相同。
通常情况下,打开一个新的页面,浏览器就会为开辟一个新的渲染进程,但若从A页面打开的B页面,它们同属同一站点,那么使用同一渲染进程。

4.提交文档

浏览器进程将网络进程接受到的HTML数据提交给渲染进程。

5.渲染阶段

一旦文档被提交,渲染进程就开始页面解析和子资源加载了。

05| 渲染流程:HTML、CSS和JAVASCRIPT是如何变成页面的?

按照渲染的时间顺序,流水线可以分为:构建DOM树、样式计算、布局计算、分层、绘制、分块、光栅化、合成。
每个阶段需要关注:输入的内容、处理过程、输出的内容

1.构建DOM树

因为浏览器无法直接理解和使用HTML,所以需要将HTML转换为浏览器能够理解的结构–DOM树。

  • 输入内容是HTML文件
  • 经过HTML解析器解析
  • 输出树状的DOM结构–DOM树结构与HTML内容几乎一模一样,但DOM是保存在内存中树状结构

2.样式计算

样式计算的目的是为了计算出DOM节点中每个元素的具体样式

  • 输入内容是CSS文件
  • 处理过程是将CSS文件进行转换成浏览器可以理解的结构–styleSheets、对属性值进行标准化(em-px,red-rgb,bold-700)、计算DOM树中每个节点的样式属性(css继承和层叠规则)
  • 输出了经过处理的styleSheets

3.布局阶段

DOM结构有了、样式结构有了,需要对几何位置信息进行布局。

  • 创建布局树(DOM结构与样式结构结合,将display为none的去除,构成布局树)
  • 布局计算(输入为布局树,经过复杂计算,输出也为布局树)、由于输入输出一致,因此Google下一代布局系统的优化叫做LayoutNG。

4.分层

页面开始绘制之前,浏览器会对3D变换、页面滚动、z-index等操作去为特定的节点生产专用的图层、并生成一颗对应的图层树。
结果是:最终每一个节点都会直接或间接的从属于一个层。
满足分层有两个条件:用于层叠上下文属性(定位属性、透明属性、滤镜等)和需要裁剪的地方(overflow)

5.图层绘制

将图层绘制命令拆分为很多小的绘制指令,然后一个个执行这些命令,汇总成待绘制列表。

6.栅格化操作

有了这些绘制命令、浏览器渲染引擎中的合成线程进行绘制。
所谓栅格化操作就是按照视口附近的图块优先生成位图。

7.合成和显示

浏览器进程通过via组件,接收合成线程发过来的绘制图块命令,将页面绘制到内存中,显示在屏幕上。

相关概念

重排

改变了元素长宽、浏览器会出发重新布局–后续一系列过程,会更新完成的渲染流水线,因此开销最大。

重绘

改变了颜色等未引起几何位置变化,重绘相较重排、省去了布局和分层阶段,因此效率会高一些。

直接合成

比如CSS的transform实现的动画效果,可以避开重排和重绘阶段,大大提升绘制效率。