开100个标签页,为什么浏览器没崩?
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
今天用酒店的故事,聊聊 Chrome 的多进程架构。 进程与线程:有什么区别?想象一下: 进程如同一个独立的厨房,有自己的灶台、冰箱、厨师。 线程如同厨房里的厨师,多个厨师共享同一个厨房的资源——灶台是共用的,冰箱是共用的,但每个厨师可以同时干活。 关键区别:
Chrome多进程架构
渲染进程:每个标签页一个最重要的进程是渲染进程——每个标签页都有自己的渲染进程: 这就是为什么一个标签页崩溃不会影响其他标签页——每个渲染进程都有自己独立的内存空间,互不干扰。 为什么Chrome选择多进程?早期浏览器(如IE、Firefox早期版本)都是单进程架构: 单进程的问题:
Chrome设计者认为:稳定性和安全性比内存占用更重要。 进程间通信:IPC不同进程之间怎么"对话"?
IPC消息类型Chrome中主要的消息类型:
IPC工作流程点击链接时, 整个过程仅需几十毫秒。
|
| 线程 | 职责 | 为什么需要独立 |
|---|---|---|
| 主线程 | JS执行、DOM、Layout、事件处理 | JS必须单线程执行 |
| 合成线程 | 图层合成、滚动、动画 | 滚动必须60fps,不能等JS |
| 光栅线程 | 绘制指令执行、像素填充 | 耗时操作,不能阻塞主线程 |
主线程要干太多事情:
这就是为什么长任务(Long Task)会卡页面——主线程太忙,用户的点击、滚动都没人处理。
Chrome把滚动交给了合成线程处理,不经过主线程:
传统方式(经过主线程):
滚动事件 → 主线程处理 → 重新布局 → 重绘 → 合成
↑
可能被JS阻塞
Chrome方式(合成线程直接处理):
滚动事件 → 合成线程 → 直接合成 → 输出
↑
完全不经过主线程
所以即使JS卡住了,页面滚动和动画依然流畅。
渲染进程为什么能"安全"地运行任意网页?
因为 Chrome 给渲染进程加了沙箱(Sandbox)——如同酒店房间:你可以用自己的东西,但不能动酒店的基础设施,也不能进别人房间。
沙箱限制:
渲染进程能做的事:
├── ✅ 执行JS(V8引擎隔离)
├── ✅ 操作DOM(沙箱内DOM树)
├── ✅ 计算样式
└── ✅ 发送网络请求(通过IPC代理)
渲染进程不能做的事:
├── ❌ 直接读写文件系统
├── ❌ 直接访问摄像头/麦克风(需用户授权)
├── ❌ 直接访问系统剪贴板(全权)
├── ❌ 直接读取本机Cookie/密码
├── ❌ 直接创建网络连接(必须经过网络进程)
└── ❌ 直接调用系统API
沙箱主要依赖操作系统提供的隔离机制:
| 机制 | 说明 |
|---|---|
| 进程隔离 | 每个渲染进程有独立虚拟地址空间 |
| 用户权限限制 | 渲染进程以低权限用户运行 |
| 系统调用过滤 | 禁止某些危险系统调用 |
| 文件访问限制 | 无法访问用户文件 |
即使网页中的恶意代码能执行,它也被"关在笼子里",无法直接伤害你的电脑。
2018 年 Chrome 引入Site Isolation(站点隔离),把安全提升到新级别。
每个标签页一个渲染进程:
标签页1 → 渲染进程A → 可以访问标签页1的内存
标签页2 → 渲染进程A → 可以访问标签页2的内存
↓
同一个进程
理论上可以访问彼此
每个跨站点的iframe也可能是独立进程:
example.com 页面:
┌─────────────────────────────────────────┐
│ 主页面(主框架) → 渲染进程A │
│ ├── iframe(ads.example.com) → 渲染进程B │
│ ├── iframe(analytics.com) → 渲染进程C │
│ └── iframe(cdn.example.com) → 渲染进程D │
└─────────────────────────────────────────┘
↓
进程级别完全隔离
防止Spectre/Meltdown等侧信道攻击:
攻击场景:
1. evil.com 运行在 渲染进程A
2. victim.com 也在 渲染进程A(作为iframe)
3. 恶意JS利用Spectre漏洞
4. 通过侧信道 timing攻击 读取渲染进程A的内存
5. 理论上可以读到 victim.com 的数据!
有了 Site Isolation,即使 evil.com 被攻破,它的渲染进程也无法访问 victim.com 的数据——因为它们根本不在同一个进程里。
更严格的隔离带来更高的内存占用:
| 情况 | 进程数 |
|---|---|
| 10个同源标签页 | 10个渲染进程 |
| 10个跨源标签页 | 可能10+个渲染进程 |
| 一个页面有5个跨站iframe | 6个渲染进程 |
Chrome为了安全,愿意付出更多内存代价。
很多人抱怨Chrome"吃内存"。
确实,多进程架构比单进程消耗更多内存,但这是故意的设计权衡:
虽然多进程更耗内存,但Chrome也做了很多优化:
渲染进程合并:同源的多个标签页可能共享一个渲染进程
内存共享:使用**共享内存(Shared Memory)**减少复制
进程休眠:长时间未激活的标签页进程可以休眠
垃圾回收优化:V8 的垃圾回收已经高度优化
内存爆炸场景:
├── 开100个淘宝/京东商品页(每个都有大量JS)
├── 开50个在线文档(Google Docs、Notion)
├── 开20个视频网站(爱奇艺、优酷、B站)
└── 结果:内存占用轻松上10GB
这是Chrome的"有钱任性"设计哲学——用内存换稳定性和用户体验。
核心思想:Chrome用"酒店"架构——每个房间(进程)独立,隔音好,一个房间出问题不影响其他;房间内有限制,不能动基础设施;甚至同一页面的不同访客也要隔开。
技术不复杂,但正是这套架构,让"100个网页同时运行"成为可能。
下次 Chrome 占用几百MB甚至几GB内存时,别急着骂它——那是它"有钱任性"的设计,是为了让你的浏览器更稳定、更安全、更流畅。