Chromium 一次网络请求全流程

2026-03-11 pv

我们每天都在使用浏览器。

你的每一次网络请求,实际都跨越了千山万水,需要浏览器、操作系统、网络基础设施各方力量的鼎立配合。

在用户眼中,看上去无非只是点击几次鼠标,就能拿到想要的结果。

但这个过程,远比看起来复杂

今天这篇文章,不同于常规的面试回答,而是从 Chromium 底层视角出发,完整描述发生在一次请求背后的故事,琐碎,但异常精彩。

如果拿着这个答案去和面试官 Battle,或许他会惊叹于你对这个问题的理解深度。

我们即将看到,在充满不确定性的世界里,Chromium 如何将访问网络这件事,变得确定化

整个流程,分四部分:准备工作;发起请求;提交渲染;显示

比将大象装进冰箱,多了一步。

1. 准备工作

在发起网络请求前,预先要做两件事:

  • 参数填充
  • 注册 Throttle

NavigationControllerImpl::LoadURLWithParams() 会根据传入参数,创建一个贯穿整个请求过程的 NavigationRequest

同时,NavigationThrottleRunner 注册一系列类似 Hook 的 Throttles。

官方文档解释是:

NavigationThrottles allow observing, deferring, blocking, and canceling a given navigation. (NavigationThrottles 允许观察、延迟、阻止和取消给定的导航。)

可作用于导航过程中某些特定阶段:

  • WillStartRequest — 网络请求发起前
  • WillRedirectRequest — 重定向
  • WillFailRequest — 请求失败
  • WillProcessResponse — 请求结果到达
  • WillCommitWithoutUrlLoader — 不需要 URL 加载器的导航 (比如,about:blank)

整个过程发生在 Browser Process(浏览器进程)。

2. 发起请求

网络相关的功能,被放置在一个独立的 Network Process(网络进程)里。

这是一个沙盒进程(Sandbox Process),权限低(Low-Privilege)。

两点好处:

  • 服务解耦——逻辑清晰,便于维护
  • 安全——即便攻击者攻破网络进程,因为权限低,做不了什么坏事

详细架构如下:

┌────────────────────────────────────────────────────────────────────────┐
│ Browser Process │
│ │
│ NavigationURLLoaderImpl, RenderFrameHost, etc. │
│ │ │
│ │ Mojo IPC │
│ ▼ │
├────────────────────────────────────────────────────────────────────────┤
│ Network Service Process │
│ │
│ ┌──────────────┐ │
│ │NetworkService│──── the singleton service │
│ └──────┬───────┘ │
│ │ CreateNetworkContext() │
│ ▼ │
│ ┌──────────────┐ │
│ │NetworkContext │──── wraps a net::URLRequestContext │
│ │ │ (cookies, cache, proxy, DNS config per profile) │
│ └──────┬───────┘ │
│ │ CreateURLLoaderFactory() │
│ ▼ │
│ ┌────────────────┐ │
│ │URLLoaderFactory│──── one per frame/context │
│ └──────┬─────────┘ │
│ │ CreateLoaderAndStart() │
│ ▼ │
│ ┌──────────┐ │
│ │ URLLoader│──── drives a single net::URLRequest │
│ └──────┬───┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ net::URLRequest → URLRequestHttpJob │ │
│ │ → HttpCache → HttpNetworkTransaction │
│ │ → DNS → TCP → TLS → HTTP/2/3 │
│ └─────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────┘

通过 Mojo 这种 IPC 机制,Browser Process 将后续工作移交给 Network Process。

真正的请求从 URLRequest 开始,在 URLRequest::StartJob 中开启一段网络之旅:填充请求元数据(RequestInfo),抓取 Cookies,借助 NetworkDelegate 创建一个 HttpTransaction

下面就是经典的流水线操作:

  • 检查硬盘缓存
  • 缓存不命中或失效,创建一个套接字:
    • 解析 Proxy —— ProxyResolutionService
    • 解析 DNS —— HostResolver
    • 建立 TCP 连接 —— TCPClientSocket
    • 对于 HTTPS 还需要 TLS 握手 —— SSLClientSocket,主要包括:
      • 证书验证
      • 密钥交换
      • ALPN 协商 (HTTP 1.1,HTTP 2/3)

发送 HTTP 请求,等待响应,然后交给 Browser Process 处理。

先收到 Response headers,包括:

  • 状态码
  • 内容类型
  • 内容编码
  • 安全头等(CSP,HSTS 等)

接着需要处理:

  • MIME 类型嗅探 —— MimeSniffingResourceHandler
  • 跨域检查(Cross-Origin Checks) —— 跨域的读取会被禁止
  • 执行内容安全策略(CSP)
  • 下载检测 —— 根据 MIME 类型,如果是不可渲染结果,比如 application/zip,返回内容被交给下载组件
  • 进程选择 —— 响应结果会交给合适的 Render Process 处理并展示,遵循”站点隔离(Site Isolation)“原则

3. 提交渲染

继续借助 IPC,Browser Process 将剩余工作传递给 Render Process:

  • 响应头(Response headers)
  • 一个 mojo::DataPipe 用于传输响应体(Response body)
  • 安全,导航等相关参数

紧接着,就是 HTML 解析:

  • 预加载扫描(Preload scanner),提前发现子资源,例如:<script>, <link>, <img>,并发抓取(Parallel fetch);像那些阻碍渲染的资源,<script> 或 <line rel=“stylesheet”>,会暂停解析,直到加载完成
  • 分词(Tokenizer)
  • 构建树(Tree builder)

剩下的,就是 CSS 解析,样式计算,布局(Layout),绘制(Paint),组合(Compositing)。

之前 文章🔗 文章过。

4. 显示

Render Process 将 CompositorFrame 交给 GPU Process。

GPU Process 将所有的帧(浏览器 UI 界面、每个渲染器帧等)聚合,SkiaRenderer 绘制最终的四边形(Quad)。

为保证结果的完整呈现,使用交换缓冲区(Swap buffers),完成的帧被呈现给操作系统窗口系统(Windows 系统使用 DXGI 交换链,其他平台使用 EGL),经过 VSync(Vertical Synchronization,垂直同步),显示器展示。

5. 总结

需要承认,这篇文章写得很困难。

一方面源于,Chromium 本身就是一个超级复杂的工程,组件和代码众多,年代久远,文档也不完备,网络上可参考的有价值的文章并不多,另一方面为保证准确,需要精确到代码行数的调试。

理论,结合实践,才能不断地逼近事情真相

好在现在有 AI,极大简化了代码检索和组织的难度,但开发者的判断和确认依然必要:同样一个问题,我去问 GPT 和 Gemini,结果有时还会打架。这就需要你去 Codebase 中核对。

相信你也看出来了,本篇文章,其实只是以 “Chromium 一次网络请求全流程” 为引子,测试 AI 对于一个复杂问题理解和描述的能力。

已经做得足够好了。

我想,在后开发时代,已经有了 AI 这样强大的工具,普通开发者需要思考如何适应新的角色。

根据这次实验,我认为,提出正确问题(Right Question)、品味(Taste)、判断力(Judgement),依然重要

AI 很强,但并非全能,至少目前如此。

(完)

参考

  1. Chromium Docs - Life of a Navigation🔗
  2. 应用层协议协商 - 维基百科,自由的百科全书🔗
  3. Site Isolation Design Document🔗
在 GitHub 上编辑本页面

最后更新于: 2026-03-11T08:51:04+08:00