← 返回 Day 85 正文

Day 85 · 图解

Day 085 — WebSocket 通信 图解

1. WebSocket 协议握手流程

┌─────────┐                                      ┌─────────┐
│  客户端  │                                      │  服务器  │
│ Browser  │                                      │  Server  │
└────┬────┘                                      └────┬────┘
     │                                                │
     │  ① HTTP Upgrade 请求                           │
     │  GET /chat HTTP/1.1                            │
     │  Host: example.com                             │
     │  Upgrade: websocket                            │
     │  Connection: Upgrade                           │
     │  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==   │
     │───────────────────────────────────────────────▶│
     │                                                │
     │  ② 服务器确认切换协议                           │
     │  HTTP/1.1 101 Switching Protocols              │
     │  Upgrade: websocket                            │
     │  Connection: Upgrade                           │
     │  Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzh...  │
     │◀───────────────────────────────────────────────│
     │                                                │
     │  ③ WebSocket 连接建立                           │
     │◄═══════════════════════════════════════════════▶│
     │                                                │
     │  ④ 双向数据传输                                 │
     │◄═══════════════════════════════════════════════▶│
     │                                                │
     │  ⑤ 关闭连接                                    │
     │◄───────────────────────────────────────────────│
     │                                                │

2. HTTP 轮询 vs WebSocket 对比

HTTP 轮询(低效):
─────────────────────────────────────────────
时间轴 ─────────────────────────────────────▶

客户端:  ──请求──    ──请求──    ──请求──    ──请求──
         │           │           │           │
服务器:  ──响应──    ──响应──    ──响应──    ──响应──
                    ↑ 新数据在这里产生,但客户端不知道

WebSocket(高效):
─────────────────────────────────────────────
时间轴 ─────────────────────────────────────▶

客户端:  ═══握手═════════════════════════════════
         │
服务器:  ════════════════════════════════════════
              ↑           ↑           ↑
           推送数据     推送数据     推送数据
         (服务器主动发送,无需客户端请求)

3. 聊天室系统架构

┌──────────────────────────────────────────────────────────┐
│                    聊天室系统架构                          │
├──────────────────────────────────────────────────────────┤
│                                                          │
│   ┌────────┐     WebSocket      ┌──────────────────┐    │
│   │Alice   │◄══════════════════▶│                  │    │
│   └────────┘                    │                  │    │
│   ┌────────┐     WebSocket      │   聊天室服务器     │    │
│   │  Bob   │◄══════════════════▶│                  │    │
│   └────────┘                    │  ┌────────────┐  │    │
│   ┌────────┐     WebSocket      │  │ 连接管理器  │  │    │
│   │Carol   │◄══════════════════▶│  └────────────┘  │    │
│   └────────┘                    │  ┌────────────┐  │    │
│   ┌────────┐     WebSocket      │  │ 消息广播器  │  │    │
│   │  Dave  │◄══════════════════▶│  └────────────┘  │    │
│   └────────┘                    │  ┌────────────┐  │    │
│                                 │  │ 心跳检测器  │  │    │
│                                 │  └────────────┘  │    │
│                                 │  ┌────────────┐  │    │
│                                 │  │ 消息历史    │  │    │
│                                 │  └────────────┘  │    │
│                                 └──────────────────┘    │
│                                          │               │
│                                          ▼               │
│                                 ┌──────────────────┐    │
│                                 │  消息日志 / 存储   │    │
│                                 └──────────────────┘    │
│                                                          │
└──────────────────────────────────────────────────────────┘

4. 消息流转过程

Alice 发送消息 "你好" 给 Bob:

Alice 的客户端         聊天室服务器           Bob 的客户端
     │                     │                     │
     │── {"type":"chat",   │                     │
     │    "content":"你好"}│                     │
     │────────────────────▶│                     │
     │                     │                     │
     │                     │── {"type":"chat",   │
     │                     │    "username":"Alice",│
     │                     │    "content":"你好"} │
     │                     │────────────────────▶│
     │                     │                     │
     │                     │                     │ 显示消息
     │                     │                     │ "[Alice] 你好"
     │                     │                     │
     │                     │  (同时广播给其他用户) │
     │                     │  Carol, Dave...     │

5. 心跳检测时序

服务端                              客户端
  │                                   │
  │──── ping (每20秒) ───────────────▶│
  │◀─── pong ────────────────────────│  ← 正常响应
  │                                   │
  │──── ping ────────────────────────▶│
  │                                   │
  │◀─── pong ────────────────────────│
  │                                   │
  │                                   │ ...连接静默断开...
  │──── ping ────────────────────────▶│  ← 10秒超时
  │     (等待 pong...)                │
  │     (超过 ping_timeout=10s)       │
  │                                   │
  │  判定连接死亡,主动关闭             │
  │  清理资源                          │
  │                                   │

6. 断线重连策略(指数退避)

重连延迟 (秒)
    │
 30 │                              ┌─────
    │                              │
    │                    ┌─────────┘
 15 │                    │
    │          ┌─────────┘
  8 │          │
    │  ┌───────┘
  4 │  │
    │──┘
  2 │
  1 │──┐
    │  │
  0 ├──┼──┼────┼────────┼──────────┼────▶ 重连次数
    0  1  2    3        4          5

策略:每次重连延迟翻倍,最大不超过 30 秒
连接成功后延迟重置为 1 秒