多进程资源加载

539 阅读4分钟

背景

在早期的多进程架构设计中,所有的网络资源都是由主进程 Browser 处理。

这样做不仅可以让 Browser process 可以控制每个 renderer 对网络的访问,也可以让我们可以在多个 renderer process 之间保持一致的会话状态(cookies and cached data)。

控制网络访问数量对于早期用户而言非常重要,同一台主机打开太多连接是一个巨大的压力。

ResourceDsipatcherHost 用于管理所有的 renderer process 的资源请求。

ResourceMessageFilter 用于区分不同 Renderer 的资源消息

routes some message to handlers on the I/O thread

Blink

Blink 中有一个 ResourceLoader 对象负责获取数据。每一个 Loader 都有一个用于执行实际请求的 WebURLLoader:The header file for this interface is inside the Blink repo.

ResourceLoader 实现了接口 WebURLLoaderClient. 这是 renderer 用来将数据和其他事件分派给 Blink 的回调接口

Renderer

renderer 的 WebURLLoader 实现称为 WebURLLoaderImpl,在代码中位于 content/child/ ,它使用全局 ResourceDispatcher singleton 对象「每个 renderer process 对应一个」来创建唯一的请求 ID,并通过 IPC/Mojo 将请求转发到 Browser process. 来自 Browser process 的响应结果会引用此请求 ID,然后 ResourceDispatcher 可以将响应结果转换回 RequestPeer 对象「WebURLRequestImpl」

Browser

browser 中的 RenderProcessHost 对象接收来自每个 renderer 的 IPC/Mojo 请求。它把这些的请求指向全局的 ResourceDispatcherHost,并用一个指针指向对应的 renderProcessHost

「ResourceDispatcherHost::Receiver 的具体实现」

and the request ID generated by the renderer to uniquely identify the request.

然后,每一个请求被转换为 URLRequest 对象,该对象又把请求转发到内部需要特定协议实现的 URLRequestJob,当 URLRequest 生成通知时,ResourceDispatcherHost::Receiver 和 reuquestID 将被用来将通知发送到正确的 RenderProcessHost,以便发送回 renderer 进程。

因为之前由 renderer 生成的 ID 被保留下来,因此它能够将所有响应与 Blink 生成的特定请求相关联。

Cookies

所有的 cookies 都由 /net/base 中的 CookieMonster 对象管理,我们不与其他浏览器的网络堆栈共享 cookies,cookie monster 存在于处理所有网络请求的主进程中,因为所有 tab 的 cookies 需要相同

在页面中,我们可以通过 document.cookie 获取 Cookie.

当遇到这种情况时,我们会从 renderer 向 browser 发送一条同步消息去请求 cookie. 当 browser 处理 cookie 时,Blink 线程 将会被挂起。当 renderer 的 I/O 线程接收到来自浏览器的响应时,挂起的线程被取消,并将得到的结果返回给 JavaScprit 引擎

最新方案

普通的多进程架构也面临许多问题,这些问题主要体现在:

  • 大多数用户的使用习惯已经更偏向于在使用浏览器的过程中打开大量的 tab 页面,于是当我们新开一个页面时,进程不得不重新分配一个公共基础模块的副本,这会占用冗余的内存空间
  • 各个模块之间耦合性高,扩展性差,老的架构难以适应新的需求

2016年,chrome 团队借鉴了现代操作系统所采用的面向服务架构,重新设计了 chrome 的架构。

面向服务架构 SOA:Services Oriented Architecture

如果你对 SOA 比较陌生,那么你可以通过了解微服务的方式来了解 SOA,微服务架构是 SOA 的衍生架构思想。

在该架构的设计思想指导下,chrome 根据需要,将某些模块单独独立出来,设计成为一个独立的服务(Service),每个服务都可以在独立的进程中运行。

例如,网络处理相关的逻辑已经从 Brwser 进程中独立出来,成为 network process

每个服务都有对外开放的接口,访问服务只能通过这些对外的接口

服务与服务之间,只能通过约定好的协议进行通信

image.png

因此,在新架构中,网络请求被独立为一个新的 service,在独立的进程中运行

兼容方案

当用户设备的内存不足时,chromium 会放弃 SOA 架构,将基础模块重新整合回主进程,变成跟之前一样的架构模式,从而达到节省内存的目的。

我的个人公众号我的个人微信
这波能反杀icanmeetu