HTTP(HyperText Transfer Protocol)是现代 Web 的基石。从诞生之初,HTTP 就被设计为一个无状态协议(Stateless Protocol)。这个设计决策深刻影响了整个 Web 技术栈的演进,从 Cookie/Session 机制到 JWT Token,再到微服务架构,无不与这一设计息息相关。
sequenceDiagram
participant C as 客户端
participant S as 服务器
C->>S: 请求 1: GET /index.html
S->>C: 响应 1: 返回页面
Note over C,S: 服务器处理完请求后<br>不保存任何状态
C->>S: 请求 2: GET /profile.html
S->>C: 响应 2: 返回页面
Note over C,S: 服务器将请求 2 视为<br>全新的、独立的请求
RFC 7230 对 HTTP 无状态性的定义:
The HTTP protocol is a stateless request/response protocol.
sequenceDiagram
participant C as 客户端
participant CD as CDN 缓存
participant S as 源服务器
C->>CD: GET /api/articles
CD->>CD: 缓存命中?
alt 缓存命中
CD->>C: 返回缓存内容
else 缓存未命中
CD->>S: 转发请求
S->>CD: 返回响应
CD->>CD: 缓存响应
CD->>C: 返回内容
end
Note over C,S: 无状态请求可被任意节点缓存
flowchart TB
subgraph 应用层需要解决的问题
A[用户身份识别]
B[会话状态存储]
C[会话安全保护]
D[会话过期处理]
end
subgraph 实现方案
A --> A1[Cookie + Session]
A --> A2[JWT Token]
B --> B1[内存存储]
B --> B2[Redis 集群]
B --> B3[数据库]
C --> C1[HTTPS]
C --> C2[HttpOnly Cookie]
C --> C3[CSRF Token]
D --> D1[过期时间]
D --> D2[滑动过期]
end
sequenceDiagram
participant C as 客户端
participant S as 服务器
Note over C: 每次请求都要携带 Token
C->>S: GET /api/user<br>Authorization: Bearer xxx...
S->>C: 200 OK
C->>S: GET /api/orders<br>Authorization: Bearer xxx...
S->>C: 200 OK
C->>S: GET /api/cart<br>Authorization: Bearer xxx...
S->>C: 200 OK
Note over C,S: Token 可能有 500-1000 字节<br>累积起来带宽开销可观
flowchart LR
subgraph 客户端
C1[浏览器 1]
C2[浏览器 2]
C3[浏览器 N]
end
subgraph 服务器
S[Web 服务器]
R[(Redis 会话存储)]
end
C1 -->|Cookie: SessionID| S
C2 -->|Cookie: SessionID| S
C3 -->|Cookie: SessionID| S
S -->|查询会话| R
Note over R: 需要存储所有用户的会话<br>内存压力大,需要分布式方案
sequenceDiagram
participant C as 客户端
participant S as 服务器
Note over C,S: 首次访问
C->>S: GET /login
S->>C: 200 OK<br>Set-Cookie: session_id=abc123
Note over C,S: 后续请求
C->>S: GET /profile<br>Cookie: session_id=abc123
S->>S: 查找 session_id 对应的用户
S->>C: 200 OK (用户数据)
flowchart TB
subgraph 客户端
Cookie[Cookie: session_id=xxx]
end
subgraph 服务器
Web[Web 服务器]
Store[(Session 存储)]
end
Cookie -->|请求携带| Web
Web -->|根据 session_id 查询| Store
Store -->|返回会话数据| Web
subgraph Session 数据
D1[用户 ID]
D2[登录时间]
D3[购物车内容]
D4[用户偏好]
end
flowchart LR
subgraph JWT 的挑战
A[无法即时注销]
B[Token 较大]
C[敏感信息暴露]
D[续期机制复杂]
end
A --> A1[需要维护黑名单<br>违背无状态初衷]
B --> B1[每次请求携带<br>带宽开销]
C --> C1[Payload 可被解码<br>不能存敏感数据]
D --> D1[Refresh Token 机制<br>增加复杂度]
sequenceDiagram
participant C as 邮件客户端
participant S as SMTP 服务器
C->>S: EHLO client.example.com
S->>C: 250 Hello
C->>S: MAIL FROM:<sender@example.com>
S->>C: 250 OK
Note over S: 记住发件人
C->>S: RCPT TO:<recipient@example.com>
S->>C: 250 OK
Note over S: 记住收件人
C->>S: DATA
S->>C: 354 End with <CR><LF>.<CR><LF>
C->>S: 邮件内容...
S->>C: 250 OK: queued
Note over S: 整个邮件事务完成
sequenceDiagram
participant C as 客户端
participant S as REST API 服务器
Note over C: 获取用户信息
C->>S: GET /users/123<br>Authorization: Bearer token
S->>C: 200 OK (用户数据)
Note over C: 更新用户信息
C->>S: PUT /users/123<br>Authorization: Bearer token<br>{"name": "新名字"}
S->>C: 200 OK
Note over C: 删除用户
C->>S: DELETE /users/123<br>Authorization: Bearer token
S->>C: 204 No Content
Note over S: 每个请求独立<br>无需记住之前发生了什么
flowchart TB
subgraph HTTP/2 新特性
A[多路复用 Stream]
B[头部压缩 HPACK]
C[服务器推送]
D[流量控制]
end
subgraph 无状态语义保持
E[请求独立性]
F[响应自描述]
G[无会话概念]
end
A --> E
B --> F
C --> E
D --> G
sequenceDiagram
participant C as 客户端
participant S as 服务器
Note over C,S: QUIC 0-RTT 连接
C->>S: 0-RTT 请求 (携带之前的数据)
S->>C: 响应
Note over C,S: 请求仍需携带完整信息
C->>S: GET /api/user<br>Authorization: Bearer token
S->>C: 200 OK
flowchart TB
subgraph 前端
F[React/Vue 应用]
F1[Zustand/Redux<br>客户端状态]
F2[LocalStorage<br>持久化数据]
end
subgraph API 网关
G[Kong/Nginx]
end
subgraph 微服务
A[认证服务]
B[用户服务]
C[订单服务]
end
subgraph 数据层
R[(Redis<br>会话缓存)]
D[(PostgreSQL<br>持久化)]
end
F -->|JWT Token| G
G -->|验证 Token| A
G --> B
G --> C
A --> R
B --> D
C --> D
F1 --> F2
flowchart TB
A[无状态设计] --> B[简单性]
A --> C[可扩展性]
A --> D[可靠性]
A --> E[可缓存性]
B --> F[易于实现和理解]
C --> G[水平扩展能力]
D --> H[容错和恢复]
E --> I[CDN/代理缓存]
J[代价: 会话管理复杂性] --> A