004-HTTP2与HTTP3

HTTP/2 与 HTTP/3 深度解析

HTTP/2 新特性

1. 二进制分帧层 (Binary Framing Layer)

  • 突破性改变:将HTTP消息分解为独立的帧,采用二进制格式传输
  • 帧类型:
    • HEADERS帧:包含头部信息
    • DATA帧:包含有效载荷
    • PRIORITY帧:指定流的优先级
    • RST_STREAM帧:流终止
    • SETTINGS帧:连接配置参数
    • PUSH_PROMISE帧:服务器推送资源
    • PING帧:检测连接活性
    • GOAWAY帧:停止连接

2. 多路复用 (Multiplexing)

  • 核心优势:单个TCP连接上并行交错传输多个请求/响应
  • 解决的问题:
    • 彻底避免HTTP/1.x的队头阻塞问题
    • 消除不必要的连接建立开销(6个并行连接限制)
  • 实现方式:通过流ID(Stream ID)标识不同的请求/响应流

3. 头部压缩 (HPACK)

  • 压缩算法:专门为HTTP/2设计的HPACK算法
  • 压缩原理:
    • 静态表:包含61个常见HTTP头部字段
    • 动态表:缓存本次连接中新出现的头部字段
    • Huffman编码:对字符串进行压缩
  • 效果:典型场景下头部大小减少85-90%

4. 服务器推送 (Server Push)

  • 创新机制:服务器可主动向客户端推送资源
  • 工作流程:
    1. 客户端请求HTML文档
    2. 服务器在响应HTML的同时,推送相关CSS/JS资源
    3. 推送的资源被存入客户端缓存
    4. 当客户端需要这些资源时,直接从缓存读取
  • 优势:减少额外的网络往返(RTT)

5. 流优先级 (Stream Prioritization)

  • 权重分配:每个流可被分配1-256的权重
  • 依赖关系:流可以声明依赖于其他流
  • 应用场景:确保关键资源(如CSS)优先加载

6. 流量控制 (Flow Control)

  • 基于信用(credit-based)的流量控制机制
  • 可针对每个流进行独立控制
  • 防止接收方被过量的数据淹没

HTTP/2 的缺陷与限制

1. TCP层面的队头阻塞 (Head-of-Line Blocking)

  • 根本问题:虽然HTTP/2解决了应用层的队头阻塞,但TCP协议本身的特性导致:
    • TCP要求数据按顺序到达
    • 单个丢包会导致整个连接等待重传
  • 影响:在高丢包率网络环境下性能下降明显

2. 连接建立开销

  • TCP三次握手:至少1个RTT
  • TLS握手:完全握手需要2个RTT(启用TLS 1.3可减少到1个RTT)
  • 冷启动延迟问题依然存在

3. 服务器推送的实际问题

  • 推送的资源可能已被缓存,造成带宽浪费
  • 浏览器可能取消不需要的推送(通过RST_STREAM)
  • 实现复杂,采用率不高

4. 中间设备兼容性问题

  • 某些网络中间件(如代理、防火墙)不能正确处理HTTP/2流量
  • 可能降级到HTTP/1.x,失去性能优势

5. 队头阻塞的变相转移

  • 虽然解决了请求级别的队头阻塞,但资源依赖关系可能导致新的阻塞模式

HTTP/3 的核心改进

1. 基于QUIC协议

  • 革命性改变:放弃TCP,改用UDP作为传输层协议
  • QUIC特性:
    • 内置加密(基于TLS 1.3)
    • 0-RTT/1-RTT连接建立
    • 改进的拥塞控制
    • 连接迁移支持(IP地址变化不影响连接)

2. 彻底解决队头阻塞

  • 每个数据流独立传输
  • 单个数据包丢失只影响该数据流,不影响其他流
  • 真正的多路复用,无底层协议限制

3. 更快的连接建立

  • 0-RTT握手:对之前连接过的服务器可立即发送数据
  • 1-RTT握手:新连接也比TCP+TLS快

4. 改进的拥塞控制

  • 可插拔的拥塞控制框架
  • 默认使用更现代的算法(如BBR)
  • 更好的网络适应性

5. 连接迁移

  • 连接标识符不绑定IP地址
  • 设备切换网络(如WiFi转4G)时保持连接

6. 其他优化

  • 不可靠数据支持(用于实时应用)
  • 前向纠错(FEC)能力
  • 更精细的流量控制

HTTP/3 的当前状态与挑战

采用现状

  • 2022年6月正式成为IETF标准(RFC 9114)
  • 主要浏览器(Chrome/Firefox/Safari)已支持
  • Cloudflare、Google等大型服务商已部署

部署挑战

  1. UDP被限制:某些网络环境限制或限速UDP流量
  2. 中间设备支持:防火墙/NAT设备对QUIC支持不完善
  3. 服务器CPU开销:QUIC加密处理比TCP+TLS更耗资源
  4. 操作系统支持:需要用户态实现,内核支持仍在推进

性能对比场景

网络条件 HTTP/1.1 HTTP/2 HTTP/3
低延迟稳定网络
高延迟网络
高丢包网络
移动网络

总结:演进路线图

HTTP/1.1 → HTTP/2 → HTTP/3 的核心改进方向:

  1. 从文本协议到二进制协议
  2. 从单路传输到真正的多路复用
  3. 从明文传输到强制加密
  4. 从TCP到UDP基础
  5. 从固定连接到智能连接迁移

HTTP/3通过QUIC协议实现了传输层的革命性改进,特别适合现代移动互联网和高延迟、高丢包的网络环境,代表了未来Web协议的发展方向。

005-输入URL到页面加载完成流程

从输入URL到页面加载完成的超详细解析

整体流程概览

  • URL解析
  • DNS查询
  • TCP连接建立(三次握手)
  • HTTPS协商(TLS握手)
  • HTTP请求与响应
  • 浏览器解析渲染
  • TCP连接关闭(四次挥手)

一、URL解析与处理(深度扩展)

1.1 URL结构分解

一个完整的URL包含以下部分:

https://www.example.com:443/path/to/page?query=string#fragment
  • 协议方案https(还有http、ftp、ws等)
  • 主机名www.example.com(可能包含子域名)
  • 端口号:443(HTTPS默认端口,HTTP默认80)
  • 路径/path/to/page(服务器资源路径)
  • 查询字符串?query=string(键值对参数)
  • 片段标识符#fragment(页面内锚点)

1.2 URL编码机制

为什么需要编码

  • 保留字符:! * ' ( ) ; : @ & = + $ , / ? % # [ ]
  • 非ASCII字符:中文等Unicode字符
  • 空格:需要转为+%20

编码过程示例

1
encodeURIComponent("搜索 前端") // "搜索%20前端"

1.3 HSTS深入

工作原理

  1. 首次访问时通过HTTP头Strict-Transport-Security: max-age=31536000告知浏览器
  2. 浏览器将该域名加入HSTS列表
  3. 后续访问自动转为HTTPS(即使输入http://)

安全意义

  • 防止SSL剥离攻击(中间人强制降级为HTTP)
  • 避免301重定向的首次攻击窗口

二、DNS解析全流程(深度扩展)

2.1 完整查询顺序

  1. 浏览器缓存:检查最近访问记录
  2. 系统缓存
    • Windows:ipconfig /displaydns
    • macOS/Linux:sudo killall -HUP mDNSResponder
  3. hosts文件
    • Windows:C:\Windows\System32\drivers\etc\hosts
    • Unix:/etc/hosts
  4. 路由器缓存:家庭路由器的DNS缓存
  5. ISP DNS缓存:互联网服务提供商的递归DNS服务器
  6. 递归查询
    • 根域名服务器(全球13组)
    • 顶级域服务器(.com/.org等)
    • 权威域名服务器(域名注册商提供)

2.2 DNS记录类型详解

类型 作用 示例
A IPv4地址 example.com → 192.0.2.1
AAAA IPv6地址 example.com → 2001:db8::1
CNAME 别名 www.example.com → example.com
MX 邮件交换 example.com → mail.example.com
TXT 文本记录 用于验证、SPF等
NS 域名服务器 example.com → ns1.example.com
SOA 起始授权 域管理信息

2.3 DNS安全问题

常见攻击

  • DNS劫持:篡改解析结果
  • DNS污染:伪造响应包
  • DNS放大攻击:利用递归查询进行DDoS

防御方案

  • DNSSEC:通过数字签名验证响应真实性
  • DNS-over-HTTPS:加密DNS查询(如Cloudflare 1.1.1.1)
  • EDNS Client Subnet:精准CDN调度同时保护隐私

三、TCP连接建立(三次握手深度解析)

3.1 握手报文细节

第一次握手(SYN)

Flags: SYN=1, ACK=0
Sequence Number: 随机初始序列号(ISN)
Window Size: 接收窗口大小
MSS: 最大报文段长度(通常1460字节)

第二次握手(SYN-ACK)

Flags: SYN=1, ACK=1
Sequence Number: 服务器ISN
Acknowledgment Number: 客户端ISN+1
Window Size: 服务器接收窗口
MSS: 服务器MSS

第三次握手(ACK)

Flags: ACK=1
Sequence Number: 客户端ISN+1
Acknowledgment Number: 服务器ISN+1

3.2 为什么不能是两次握手?

根本原因:信道不可靠与历史连接问题

具体场景分析

  1. 重复SYN包

    • 客户端发送SYN1(网络延迟)
    • 超时重发SYN2(成功建立连接后关闭)
    • SYN1到达服务器,如果是两次握手会直接建立无效连接
  2. 双向信道验证

    • 第三次握手确保客户端能收到服务端的响应
    • 避免服务端单方面建立连接浪费资源

3.3 SYN Flood攻击与防御

攻击原理

  • 伪造大量SYN包但不完成握手
  • 占满服务器的半连接队列(backlog)

防御方案

  1. SYN Cookie

    • 不存储连接状态
    • 通过加密算法生成序列号
    • 收到ACK时验证合法性
  2. 其他措施

    • 增加backlog队列大小
    • 减少SYN-RECEIVED状态超时时间
    • 防火墙限速

四、TLS握手过程(HTTPS安全基础)

4.1 TLS 1.2完整握手

步骤详解

  1. Client Hello

    • 随机数(Client Random)
    • 支持的加密套件(如TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
    • 支持的TLS版本
    • SNI(Server Name Indication)
  2. Server Hello

    • 选择加密套件
    • 服务器随机数(Server Random)
    • 数字证书(包含公钥)
  3. 证书验证

    • 验证证书链有效性
    • 检查吊销状态(OCSP/CRL)
    • 验证域名匹配
  4. 密钥交换

    • 客户端生成预主密钥(Premaster Secret)
    • 用服务器公钥加密传输
  5. 会话密钥生成
    master_secret = PRF(pre_master_secret, “master secret”, ClientHello.random + ServerHello.random)

4.2 TLS 1.3重大改进

优化点

  1. 1-RTT握手

    • 客户端在第一个消息中就猜测密钥交换算法
    • 服务端直接返回共享密钥
  2. 0-RTT模式

    • 对近期连接过的服务器可立即发送加密数据
    • 存在重放攻击风险(需业务层防护)
  3. 算法精简

    • 移除RSA密钥交换
    • 禁止静态DH
    • 仅保留AEAD加密模式(如AES-GCM)

4.3 证书体系详解

证书链验证

用户证书 → 中间CA证书 → 根CA证书
  • 根CA证书内置在操作系统/浏览器
  • 验证时需检查签名和时间有效性

证书类型

  • DV(域名验证):基本验证
  • OV(组织验证):验证企业真实性
  • EV(扩展验证):绿色地址栏(逐渐淘汰)

五、HTTP/2核心特性(对比HTTP/1.1)

5.1 二进制分帧层

帧结构

+-----------------------------------------------+
| Length (24) | Type (8) | Flags (8) | R (1) | Stream ID (31) |
+-----------------------------------------------+
|                   Frame Payload                           |
+----------------------------------------------------------+

帧类型

  • HEADERS:包含HTTP头部
  • DATA:包含请求/响应体
  • PRIORITY:设置流优先级
  • RST_STREAM:终止流
  • SETTINGS:连接参数配置

5.2 多路复用实现原理

流(Stream)特性

  • 每个流有唯一ID
  • 流可以设置优先级
  • 流之间完全独立

对比HTTP/1.1

  • HTTP/1.1的管道化(pipelining)问题:
    • 响应必须按请求顺序返回
    • 一个阻塞会影响后续所有请求
  • HTTP/2彻底解决队头阻塞(应用层)

5.3 服务器推送争议

合理使用场景

  • 关键CSS/JS文件
  • 首屏必需的静态资源

潜在问题

  1. 推送过多资源浪费带宽
  2. 浏览器缓存可能导致重复推送
  3. 需要精细控制(通过<link rel="preload">提示)

六、浏览器渲染引擎工作原理

6.1 关键线程协作模型

+---------------------------------------------------+
|                   Browser Process                 |
+---------------------------------------------------+
|  Network Thread  |   UI Thread   |  Storage Thread |
+---------------------------------------------------+
            ↑
            | IPC
            ↓
+---------------------------------------------------+
|                  Renderer Process                 |
+---------------------------------------------------+
|  Main Thread  |  Compositor Thread | Raster Thread |
|  (JS/DOM/CSS) |                    |               |
+---------------------------------------------------+

线程职责

  1. 主线程

    • 解析HTML构建DOM
    • 计算样式和布局
    • 执行JavaScript(V8引擎)
  2. 合成线程

    • 分层(Layer)管理
    • 滚动等动画优化
    • 调用GPU加速
  3. 光栅线程

    • 将图层分块(Tile)
    • 使用GPU加速光栅化

6.2 渲染流水线详细阶段

  1. 解析HTML

    • 字节 → 字符 → 令牌 → 节点 → DOM树
    • 遇到<script>会阻塞(除非async/defer)
  2. 样式计算

    • 解析CSS生成CSSOM
    • 继承:font-size等可继承属性
    • 层叠:处理选择器优先级
  3. 布局阶段

    • 生成布局树(排除display:none节点)
    • 计算精确几何位置(重排阶段)
  4. 分层与绘制

    • 根据will-change、z-index等创建图层
    • 生成绘制指令列表(类似Canvas绘图命令)
  5. 合成与显示

    • 合成线程处理视觉滚动等
    • GPU加速的纹理合成
    • 最终提交给显示系统

6.3 性能优化关键点

避免强制同步布局

1
2
3
4
5
6
7
8
9
// 错误示例(读取offsetWidth导致强制布局)
const width = element.offsetWidth;
element.style.width = width + 10 + 'px';

// 正确做法(使用requestAnimationFrame)
requestAnimationFrame(() => {
const width = element.offsetWidth;
element.style.width = width + 10 + 'px';
});

优化建议

  1. 使用CSS动画替代JS动画
  2. 避免频繁操作DOM(使用文档片段)
  3. 使用content-visibility: auto跳过屏外渲染
  4. 合理使用will-change提示浏览器

七、TCP连接关闭(四次挥手深度解析)

7.1 挥手状态机

+---------+       FIN         +----------+
| CLOSED  | <--------------- | FIN_WAIT1|
+---------+                  +----------+
                              |   ^
                              ACK |
                              v   |
+---------+       FIN         +----------+
| CLOSING | <--------------- | FIN_WAIT2|
+---------+                  +----------+
  |   ^                       |   ^
  |   |                       |   |
  |   +-------- FIN ----------+   |
  |                               |
  +------------ ACK -------------+

7.2 TIME_WAIT关键问题

为什么需要2MSL(最大报文生存时间)

  1. 确保最后一个ACK到达对端

    • 如果丢失,服务端会重发FIN
    • 客户端需要保持在可响应状态
  2. 让网络中残留报文失效

    • 避免相同四元组的新连接收到旧报文

MSL典型值

  • Linux:60秒
  • Windows:2分钟
  • 因此TIME_WAIT通常为2-4分钟

7.3 连接重置场景

RST包触发条件

  1. 访问未监听的端口
  2. 异常终止连接
  3. 半开连接检测(对方已崩溃)

与FIN的区别

  • FIN是优雅关闭,会等待数据发送完毕
  • RST是强制终止,立即释放资源

八、深入问答准备

8.1 为什么JavaScript是单线程?

历史原因

  • 最初设计用于简单的表单验证
  • 避免多线程操作DOM的同步问题

实现优势

  1. 简化内存模型:无锁机制、无竞态条件
  2. 确定性执行顺序:事件循环保证执行顺序可预测
  3. 与渲染引擎协作:避免JS执行与页面渲染冲突

现代补充方案

  • Web Worker:后台计算线程
  • SharedArrayBuffer:共享内存
  • Atomics API:原子操作

8.2 浏览器多进程架构优势

安全隔离

  • 沙箱化渲染进程(无法直接访问系统资源)
  • 插件进程隔离(Flash等容易崩溃的组件)

性能提升

  • 利用多核CPU并行处理
  • 单个标签页崩溃不影响整体

资源控制

  • 每个进程独立内存空间
  • 可以单独限制资源用量(如GPU内存)

8.3 进程 vs 线程对比表

特性 进程 线程
创建开销 大(需要分配独立资源) 小(共享进程资源)
通信方式 IPC(管道、共享内存等) 直接读写共享内存
上下文切换成本 高(需切换地址空间) 低(仅切换执行上下文)
容错性 一个崩溃不影响其他进程 一个崩溃导致进程终止
资源共享 需要通过显式机制共享 自动共享所有进程资源
多核利用 天然支持 需要显式并行编程

8.4 现代浏览器进程模型示例

Chrome多进程架构

Browser Process (1个)
   ├── GPU Process (1个)
   ├── Network Service (1个)
   ├── Storage Service (1个)
   └── Renderer Processes (多个,每个标签页/iframe)
       ├── Main Thread
       ├── Worker Threads
       └── Compositor Thread

内存节省技术

  • Site Isolation:同站点标签页共享进程
  • Process Pooling:进程复用池

九、前沿技术演进

9.1 HTTP/3与QUIC协议

核心改进

  1. 基于UDP:避免TCP队头阻塞
  2. 0-RTT连接:快速恢复会话
  3. 连接迁移:网络切换无感知

企业采用现状

  • Google:YouTube等主要服务已部署
  • Cloudflare:全球边缘网络支持
  • 苹果:iOS 15+支持QUIC

9.2 WebAssembly高性能场景

适用领域

  1. 视频/图像处理(FFmpeg.wasm)
  2. 3D游戏/图形计算(Unity WebGL)
  3. 密码学运算(区块链应用)
  4. 科学计算(TensorFlow.js后端)

性能对比

操作 JavaScript WebAssembly
矩阵运算(1M) 120ms 15ms
SHA-256哈希 80ms 6ms

9.3 新的性能指标体系

Web Vitals

  1. LCP (Largest Contentful Paint):最大内容渲染时间(<2.5s)
  2. FID (First Input Delay):首次输入延迟(<100ms)
  3. CLS (Cumulative Layout Shift):累计布局偏移(<0.1)

测量工具

  • Chrome DevTools的Lighthouse
  • web-vitals.js库
  • Search Console报告

十、实战调试技巧

10.1 网络分析工具链

  1. Wireshark:抓取TCP/UDP原始包
    • 过滤器:tcp.port == 443 && http2
  2. Chrome DevTools
    • Network面板查看HTTP/2流
    • Performance面板分析渲染流水线
  3. curl命令
    1
    curl -v --http2 https://example.com

10.2 关键性能优化检查点

  1. 资源加载
    • 关键路径CSS内联
    • 非关键JS异步加载
  2. 渲染优化
    • 避免布局抖动
    • 使用content-visibility
  3. 内存管理
    • 检测DOM节点泄漏
    • Worker中处理大数据集

10.3 真实案例分析

案例:电商网站首屏优化

  1. 问题:LCP时间>4s
  2. 诊断
    • 关键图片未预加载
    • 同步第三方脚本阻塞渲染
  3. 解决方案
    • 使用<link rel=preload>提前加载英雄图
    • 将分析脚本改为async
    • 实施服务端渲染(SSR)
  4. 结果:LCP降至1.8s

通过这种深度技术解析和实际案例结合的方式,不仅能应对技术面试,更能建立完整的Web性能优化知识体系。建议在理解原理的基础上,多使用开发者工具进行实践验证。