应用层协议
1. HTTP 演进
1.1 HTTP/1.1
最广泛部署的版本(1997 年发布,至今仍大量使用)。
核心特性:
| 特性 | 说明 |
|---|---|
| 持久连接(Keep-Alive) | 默认复用 TCP 连接,避免每次请求重新握手 |
| 管线化(Pipelining) | 可连续发送多个请求(但响应必须按序返回) |
| 分块传输(Chunked Transfer) | 不需要预知 Content-Length |
| Host 头部 | 支持虚拟主机 |
问题——队头阻塞(Head-of-Line Blocking):
- 管线化中前一个响应未完成,后续响应被阻塞
- 实践中大多数浏览器禁用了管线化
- 变通方案:每个域名开 6 个并行 TCP 连接
1.2 HTTP/2
2015 年标准化,由 Google SPDY 演进而来。
核心改进:
| 特性 | 机制 |
|---|---|
| 二进制分帧 | 将 HTTP 消息拆分为二进制帧,替代文本格式 |
| 多路复用 | 单个 TCP 连接上并行传输多个请求/响应流 |
| 头部压缩(HPACK) | 静态表 + 动态表 + Huffman 编码 |
| 服务器推送 | 服务器主动推送客户端可能需要的资源 |
| 流优先级 | 客户端指定资源优先级 |
HTTP/1.1: HTTP/2:
连接1: GET /a → 响应a 连接1:
连接2: GET /b → 响应b Stream 1: GET /a → 响应a
连接3: GET /c → 响应c Stream 2: GET /b → 响应b
连接4: GET /d → 响应d Stream 3: GET /c → 响应c
(多个TCP连接) Stream 4: GET /d → 响应d
(单个TCP连接,帧交织传输)
仍存在的问题:TCP 层的队头阻塞——一个丢包导致整个 TCP 连接的所有流暂停。
1.3 HTTP/3(QUIC)
2022 年标准化,基于 UDP + QUIC 协议。
核心改进:
| 特性 | 说明 |
|---|---|
| 基于 UDP | 绕过 TCP 的限制,用户空间实现传输协议 |
| 无队头阻塞 | 每个流独立丢包恢复,一个流丢包不影响其他流 |
| 0-RTT / 1-RTT 连接建立 | 传输层握手 + TLS 握手合并 |
| 连接迁移 | 使用 Connection ID 而非四元组标识连接,切换网络不断连 |
| 头部压缩(QPACK) | HPACK 的改进版,适应乱序传输 |
TCP + TLS 1.3: QUIC:
SYN QUIC Initial (含 TLS ClientHello)
SYN-ACK QUIC Handshake (含 TLS ServerHello)
ACK + ClientHello → 1-RTT 即可发送数据
ServerHello
→ 2-RTT 后才能发送数据 0-RTT: 恢复连接时可立即发送数据
1.4 HTTP 方法
| 方法 | 语义 | 幂等 | 安全 |
|---|---|---|---|
| GET | 获取资源 | 是 | 是 |
| POST | 创建资源 / 提交数据 | 否 | 否 |
| PUT | 替换整个资源 | 是 | 否 |
| PATCH | 部分更新资源 | 否 | 否 |
| DELETE | 删除资源 | 是 | 否 |
| HEAD | 获取头部(不含 body) | 是 | 是 |
| OPTIONS | 查询支持的方法 | 是 | 是 |
1.5 HTTP 状态码
| 范围 | 类别 | 常见示例 |
|---|---|---|
| 1xx | 信息 | 100 Continue |
| 2xx | 成功 | 200 OK, 201 Created, 204 No Content |
| 3xx | 重定向 | 301 Moved Permanently, 304 Not Modified |
| 4xx | 客户端错误 | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found |
| 5xx | 服务器错误 | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable |
2. HTTPS 与 TLS
2.1 TLS 握手(TLS 1.3)
sequenceDiagram
participant C as 客户端
participant S as 服务器
C->>S: ClientHello (支持的密码套件, 密钥共享参数)
S->>C: ServerHello (选定密码套件, 密钥共享参数)
Note over C,S: 双方计算出共享密钥 (ECDHE)
S->>C: {EncryptedExtensions}
S->>C: {Certificate}
S->>C: {CertificateVerify}
S->>C: {Finished}
C->>S: {Finished}
Note over C,S: 1-RTT 完成,开始加密通信
TLS 1.3 改进(相比 TLS 1.2):
- 握手从 2-RTT 降至 1-RTT(支持 0-RTT 恢复)
- 移除不安全的加密算法(RC4、3DES、SHA-1 等)
- 仅支持 AEAD 加密(如 AES-GCM、ChaCha20-Poly1305)
- 前向安全(PFS)成为强制要求
2.2 证书体系
证书链:
根 CA 证书(预装在操作系统/浏览器中)
└── 中间 CA 证书
└── 服务器证书(域名绑定)
验证流程:
- 服务器发送证书链
- 客户端验证签名链直到受信任的根 CA
- 检查域名匹配、有效期、吊销状态(OCSP/CRL)
Let's Encrypt:免费、自动化的证书颁发(ACME 协议),推动了 HTTPS 普及。
3. DNS(Domain Name System)
3.1 域名层次
根域 "."
├── 顶级域 (TLD): .com, .org, .cn, .io
│ ├── 二级域: google.com, example.org
│ │ ├── 子域: mail.google.com, www.example.org
3.2 查询方式
| 方式 | 流程 |
|---|---|
| 递归查询 | 客户端 → 本地 DNS 服务器(递归解析器)→ 逐级查询 → 返回最终结果 |
| 迭代查询 | 服务器不代查,而是告诉查询者"去问谁" |
典型解析流程(以 www.example.com 为例):
- 客户端 → 递归解析器(如
8.8.8.8) - 递归解析器 → 根服务器:".com 的 NS 是?"
- 递归解析器 → .com TLD 服务器:"example.com 的 NS 是?"
- 递归解析器 → example.com 权威服务器:"www.example.com 的 A 记录是?"
- 返回 IP 地址给客户端
DNS 缓存在每一级都存在(TTL 控制过期时间)。
3.3 记录类型
| 类型 | 含义 | 示例 |
|---|---|---|
| A | 域名 → IPv4 地址 | example.com → 93.184.216.34 |
| AAAA | 域名 → IPv6 地址 | example.com → 2606:2800:220:1:... |
| CNAME | 别名 → 规范名 | www.example.com → example.com |
| MX | 邮件交换服务器 | example.com → mail.example.com |
| NS | 域名服务器 | example.com → ns1.example.com |
| TXT | 文本信息 | SPF、DKIM 验证 |
| SRV | 服务定位 | _sip._tcp.example.com |
| SOA | 区域授权起始 | 序列号、刷新间隔等 |
3.4 DNS 安全
- DNS 劫持:篡改 DNS 响应,引导用户到恶意网站
- DNSSEC:对 DNS 响应进行数字签名,防止篡改
- DoH(DNS over HTTPS):加密 DNS 查询,防止窃听
- DoT(DNS over TLS):同上,端口 853
4. WebSocket
4.1 动机
HTTP 是请求-响应模型,服务器不能主动推送。WebSocket 提供全双工通信。
4.2 握手
基于 HTTP Upgrade 机制:
客户端:
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
服务器:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
握手后切换为 WebSocket 协议,双方可随时发送消息。
4.3 适用场景
| 场景 | 原因 |
|---|---|
| 实时聊天 | 双向即时消息 |
| 实时数据推送 | 股票行情、体育赛事 |
| 在线游戏 | 低延迟双向通信 |
| 协同编辑 | 多用户实时同步 |
4.4 替代方案
| 技术 | 机制 | 对比 |
|---|---|---|
| SSE(Server-Sent Events) | 服务器 → 客户端单向推送 | 更简单,仅单向 |
| 长轮询(Long Polling) | 客户端发请求,服务器保持直到有新数据 | 兼容性好但效率低 |
| WebSocket | 全双工 | 最灵活但实现复杂 |
5. API 设计范式
5.1 REST(Representational State Transfer)
| 原则 | 说明 |
|---|---|
| 资源导向 | URL 表示资源(名词),HTTP 方法表示操作(动词) |
| 无状态 | 每个请求包含所有必要信息 |
| 统一接口 | GET/POST/PUT/DELETE 语义一致 |
| 可缓存 | 利用 HTTP 缓存机制 |
GET /api/users → 获取用户列表
GET /api/users/123 → 获取用户 123
POST /api/users → 创建用户
PUT /api/users/123 → 更新用户 123
DELETE /api/users/123 → 删除用户 123
5.2 GraphQL
Facebook 开发的查询语言:
| 特性 | 对比 REST |
|---|---|
| 客户端指定返回字段 | 避免 over-fetching / under-fetching |
| 单一端点 | 不需要多个 URL |
| 强类型 Schema | 自描述的 API |
| 嵌套查询 | 一次请求获取关联数据 |
query {
user(id: 123) {
name
email
posts {
title
createdAt
}
}
}
局限:缓存困难(POST 单端点)、N+1 查询问题、复杂度限制。
5.3 gRPC
Google 开发的高性能 RPC 框架:
| 特性 | 说明 |
|---|---|
| Protocol Buffers | 二进制序列化,比 JSON 更紧凑更快 |
| HTTP/2 | 多路复用、头部压缩 |
| 强类型 | .proto 文件定义接口,代码生成 |
| 流式传输 | 单向流和双向流 |
| 多语言支持 | 自动生成客户端/服务器代码 |
service UserService {
rpc GetUser (UserRequest) returns (UserResponse);
rpc ListUsers (ListRequest) returns (stream UserResponse); // 服务端流
}
适用场景:微服务间通信、低延迟要求、多语言环境。
5.4 对比总结
| 维度 | REST | GraphQL | gRPC |
|---|---|---|---|
| 数据格式 | JSON | JSON | Protobuf(二进制) |
| 传输协议 | HTTP/1.1+ | HTTP/1.1+ | HTTP/2 |
| 类型系统 | 弱(OpenAPI 可选) | 强(Schema) | 强(.proto) |
| 实时通信 | 不原生支持 | Subscriptions | 双向流 |
| 浏览器支持 | 原生 | 原生 | 需 gRPC-Web 代理 |
| 适合场景 | 公开 API、简单 CRUD | 复杂前端查询 | 微服务内部通信 |
6. CDN(Content Delivery Network)
6.1 原理
将内容缓存到全球分布的边缘节点,用户访问最近的节点:
用户 → DNS 解析 → CDN 智能调度 → 最近的边缘节点
├── 缓存命中 → 直接返回
└── 缓存未命中 → 回源获取 → 缓存 → 返回
6.2 CDN 功能
| 功能 | 说明 |
|---|---|
| 静态加速 | 缓存图片、JS、CSS 等静态资源 |
| 动态加速 | 优化路由路径,减少回源延迟 |
| DDoS 防护 | 分布式节点吸收攻击流量 |
| HTTPS 终结 | 在边缘节点卸载 TLS |
| 边缘计算 | 在边缘节点运行逻辑(如 Cloudflare Workers) |
6.3 缓存策略
通过 HTTP 头部控制:
| 头部 | 功能 |
|---|---|
Cache-Control: max-age=3600 |
资源缓存 1 小时 |
Cache-Control: no-cache |
每次验证是否过期(可缓存) |
Cache-Control: no-store |
完全不缓存 |
ETag |
资源指纹,用于条件请求 |
Last-Modified |
最后修改时间 |
缓存失效(Cache Invalidation)是分布式系统中最难的问题之一:
- URL 版本化:
/app.v2.js或/app.js?v=abc123 - Purge API:主动清除 CDN 缓存
- 短 TTL + 条件请求