176 lines
6.4 KiB
Markdown
176 lines
6.4 KiB
Markdown
|
|
---
|
|||
|
|
tags: [计算机网络, HTTP/3, QUIC, TLS 1.3]
|
|||
|
|
create time: 2026-05-18 02:50
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# HTTP/3 与 QUIC
|
|||
|
|
|
|||
|
|
## 概述
|
|||
|
|
|
|||
|
|
HTTP/3 (RFC 9114) 基于 **QUIC** 协议,将传输层从 TCP 替换为 UDP + 内嵌的可靠传输机制。核心目标:**消除 TCP 层的 Head-of-Line blocking**,实现更快的连接建立和多路复用。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
A["HTTP/3 over QUIC<br/>UDP 443"] -->|"零 RTT 建连"| B["更快 ✅"]
|
|||
|
|
C["HTTP/2 over TCP<br/>TCP 443"] -->|"三次握手 + TLS"| D["较慢"]
|
|||
|
|
|
|||
|
|
style A fill:#98FB98,color:#000
|
|||
|
|
style C fill:#FFD700,color:#000
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## QUIC 协议栈对比
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
HTTP/3 Stack: HTTP/2 Stack:
|
|||
|
|
──────────── ────────────
|
|||
|
|
HTTP/3 HTTP/2
|
|||
|
|
│ │
|
|||
|
|
┌─┴─────────────────┐ ┌──────┴──────────────┐
|
|||
|
|
│ QUIC │ │ TLS 1.3 │
|
|||
|
|
│ + Multiplexing │ │ + TCP Flow Control │
|
|||
|
|
│ + Crypto │ └──────┬──────────────┘
|
|||
|
|
│ + Reliable Tx │ │
|
|||
|
|
└──────┬─────────────┘ ┌────┴─────┐
|
|||
|
|
│ │ TCP │
|
|||
|
|
▼ └────┬─────┘
|
|||
|
|
UDP 443 │
|
|||
|
|
▼
|
|||
|
|
IP / Ethernet
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 关键设计哲学
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
TCP 的问题: QUIC 的方案:
|
|||
|
|
───────── ──────────
|
|||
|
|
• 一条流 HOL blocking • 多 Stream 独立重传
|
|||
|
|
• 拥塞控制固定算法 • 应用层可调拥塞算法 (BBRv2 by default)
|
|||
|
|
• TLS in TCP → 双重握手 • TLS 1.3 + 0-RTT session resumption
|
|||
|
|
• NAT 中断需重建 TCP • Connection ID → NAT 变更无感知
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## QUIC 连接生命周期
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant Client
|
|||
|
|
participant Server
|
|||
|
|
|
|||
|
|
Note over Client,Server: Phase 1: Connection Establishment (TLS Handshake embedded)
|
|||
|
|
Client->>Server: Initial Packet (Client Hello + CRYPTO)
|
|||
|
|
Note over Server: Parses CRYPTO from QUIC packet header
|
|||
|
|
Server-->>Client: Server Hello + CRYPTO + HANDSHAKE
|
|||
|
|
Note over Client: Session ticket cached for resume
|
|||
|
|
Server-->>Client: NEW_CONNECTION_ID + RETIRE_CONNECTION_ID
|
|||
|
|
Client-->>Server: ACK
|
|||
|
|
|
|||
|
|
Note over Client,Server: ← CONNECTION ESTABLISHED →
|
|||
|
|
|
|||
|
|
Client->>Server: 0-RTT Data (if session resumed) ⚡
|
|||
|
|
Server->>Server: Validate 0-RTT anti-replay
|
|||
|
|
Server-->>Client: 0-RTT Accepted / Rejected
|
|||
|
|
|
|||
|
|
Note over Client,Server: Phase 2: Data Transfer
|
|||
|
|
loop Multiple Streams (independent retransmission)
|
|||
|
|
Client->>Server: HEADERS(stream=X) + DATA(stream=X)
|
|||
|
|
Server-->>Client: HEADERS(stream=X) + DATA(stream=X)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
Note over Client,Server: Phase 3: Graceful Close
|
|||
|
|
Client->>Server: FIN (last stream closed)
|
|||
|
|
Server->>Client: FIN
|
|||
|
|
Client->>Server: Final ACK
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 0-RTT(零往返时间)连接恢复
|
|||
|
|
|
|||
|
|
当客户端之前访问过同一服务器时,可以跳过完整握手:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
首次连接: 后续连接:
|
|||
|
|
────────── ──────────
|
|||
|
|
Client → SYN → Server Client → QUIC Initial (with 0-RTT data)
|
|||
|
|
SYN → Client → Server processes immediately!
|
|||
|
|
ACK → Client ↓
|
|||
|
|
Client → ClientHello 0-RTT data delivered before handshake finishes!
|
|||
|
|
ServerHello + cert → Client
|
|||
|
|
Client → encrypted application data
|
|||
|
|
|
|||
|
|
Total: 1-RTT (+0-RTT if resumed) Total: 0-RTT ⚡⚡⚡
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> [!warning] 0-RTT 的安全风险
|
|||
|
|
> 重放攻击 (Replay Attack): 中间人可捕获并重放 0-RTT 请求。因此 **0-RTT 只能用于幂等操作**(GET、HEAD、OPTIONS)。POST 等不安全操作不应使用 0-RTT。
|
|||
|
|
|
|||
|
|
## QUIC 如何消除 HoL Blocking
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
HTTP/2 over TCP: QUIC over UDP:
|
|||
|
|
═════════════════ ═══════════════════
|
|||
|
|
|
|||
|
|
Stream 1: [Data][Lost❌][More] Stream 1: [✓ Data] [✓ More]
|
|||
|
|
Stream 3: [OK OK OK OK OK] ← 全部卡住! Stream 3: [✓ OK] [✓ OK] [✓ OK]
|
|||
|
|
Stream 5: [OK OK OK OK OK] Stream 5: [✓ OK] [✓ OK]
|
|||
|
|
|
|||
|
|
原因: TCP 是字节流 原因: 每个 Stream 独立编号
|
|||
|
|
丢包导致所有后续 Stream 等待 ACK 丢失的数据只重传对应 Stream
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart LR
|
|||
|
|
L1["HTTP/2:<br/>一个包丢了<br/>全连阻塞"] -->|"TCP Hol-blocking"| SLOW["慢 ❌"]
|
|||
|
|
L2["QUIC:<br/>单个stream丢包<br/>其他stream继续"] -->|"独立重传"| FAST["快 ✅"]
|
|||
|
|
|
|||
|
|
style SLOW fill:#FF6B6B,color:#fff
|
|||
|
|
style FAST fill:#98FB98,color:#000
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Go 中启用 HTTP/3
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
import "golang.org/x/net/http3"
|
|||
|
|
|
|||
|
|
// HTTP/3 服务器
|
|||
|
|
go http.ListenAndServeTLS(":443", "cert.pem", "key.pem", srv) // h2c handler
|
|||
|
|
|
|||
|
|
// 自动降级到 HTTP/2
|
|||
|
|
http3.ListenAndServeTLS(":443", "cert.pem", "key.pem", &http3.Server{
|
|||
|
|
Handler: yourHandler,
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// gRPC 也原生支持 HTTP/3
|
|||
|
|
grpc.NewServer(grpc.HTTPSupport())
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## HTTP/3 vs HTTP/2 对照表
|
|||
|
|
|
|||
|
|
| 特性 | HTTP/2 (over TCP) | HTTP/3 (over QUIC) |
|
|||
|
|
|------|-------------------|---------------------|
|
|||
|
|
| 传输层 | TCP | **UDP** |
|
|||
|
|
| 端口 | 443 (h2 via ALPN) | **443** |
|
|||
|
|
| 并发 | 单连接多 Stream | 同左 + UDP 级冗余 |
|
|||
|
|
| 连接迁移 | ❌ 网卡切换 = 断连 | ✅ Connection ID |
|
|||
|
|
| 头压缩 | HPACK | QPACK |
|
|||
|
|
| 拥塞控制 | 内核态固定算法 | **用户态可插拔** |
|
|||
|
|
| NAT 穿透 | 依赖 TCP | UDP 更友好 (运营商限制少) |
|
|||
|
|
| 成熟度 | ✅ 广泛部署 | 🟢 快速普及 (Cloudflare/Google/Facebook) |
|
|||
|
|
| Debug 难度 | tcpdump/Wireshark 成熟 | 工具链仍在完善 |
|
|||
|
|
|
|||
|
|
## 当前 adoption
|
|||
|
|
|
|||
|
|
| CDN/服务 | HTTP/3 状态 |
|
|||
|
|
|---------|-----------|
|
|||
|
|
| Cloudflare | ✅ 默认开启 |
|
|||
|
|
| Google | ✅ 大规模部署 |
|
|||
|
|
| Facebook/Meta | ✅ |
|
|||
|
|
| Nginx | ✅ 1.25+ 正式支持 |
|
|||
|
|
| Apache | ✅ mod_http3 |
|
|||
|
|
| AWS ALB/NLB | ✅ |
|
|||
|
|
| Vercel/Netlify | ✅ |
|
|||
|
|
|
|||
|
|
## 关联笔记
|
|||
|
|
|
|||
|
|
- [[hhs/NETWORK/HTTP/2多路复用]] — QUIC 继承了 HTTP/2 的多路复用思想
|
|||
|
|
- [[hhs/NETWORK/TCP拥塞控制]] — QUIC 的用户态拥塞控制可自定义
|
|||
|
|
- [[hhs/NETWORK/HTTPS与TLS握手]] — QUIC 内置 TLS 1.3
|