🔄 SSE 服务器推送原理详解

Server-Sent Events 完整通信流程可视化

🔌 第一阶段:TCP 三次握手

在建立 SSE 连接之前,客户端和服务器必须先通过 TCP 三次握手建立可靠的连接通道。

🖥️
浏览器
客户端
SYN seq=x
1 第一次握手
客户端发送 SYN,请求建立连接
2 第二次握手
服务器返回 SYN+ACK
3 第三次握手
客户端确认,连接建立完成
🖧
服务器
Server
🖥️ 客户端发送的数据包
🖧 服务器返回的数据包
SYN = 同步请求
ACK = 确认应答

📨 第二阶段:HTTP SSE 请求

TCP 连接建立后,客户端发起 HTTP 请求,告诉服务器"我要建立 SSE 连接"。

1 客户端请求
GET /events HTTP/1.1 Host: api.example.com Accept: text/event-stream Connection: keep-alive Cache: no-cache

🔑 关键:Accept: text/event-stream
告诉服务器我需要 SSE 格式的数据流

➡️
2 服务器响应
HTTP/1.1 200 OK Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive Transfer-Encoding: chunked

🔑 关键:Transfer-Encoding: chunked
分块传输编码,数据可以增量推送

📋 SSE 事件格式

event: message data: {"time": "14:30:25", "price": 156.78} id: 1001 event: message data: {"time": "14:30:30", "price": 157.12} id: 1002 event: close data: 连接关闭

每条消息以 data: 开头,以 \n\n 结尾。
可以指定 event: 类型(如 message、close、error),id: 用于断线重连。

🔀 第三阶段:连接复用与效率优化

SSE 之所以高效,核心在于 HTTP 长连接连接复用 技术。

🌐 HTTP/1.1 Keep-Alive 传统

一次 TCP 连接,复用多次 HTTP 请求,避免重复握手

事件1
事件2
事件3
事件4
↻ 持续连接中...
✅ 复用连接
节省握手时间
⚠️ 队头阻塞
串行等待

🚄 HTTP/2 多路复用 现代

在单一 TCP 连接上并行传输多个数据流,彻底解决队头阻塞

流1
A
B
C
流2
流3
★★
✅ 并行传输
无阻塞
✅ 单TCP连接
更少资源

⚡ 与 WebSocket 对比

特性 SSE WebSocket
连接方向 单向(服务端→客户端) 全双工(双向)
协议基础 HTTP/HTTPS 独立协议 (ws://)
兼容性 IE/Edge 需 polyfill 良好
自动重连 ✅ 内置 需手动实现
适用场景 实时推送、通知 聊天、游戏、协作

📊 完整数据流时间线

让我们看看从建立连接到接收数据的完整过程:

T=0ms
🔌 TCP 握手 (SYN → SYN+ACK → ACK)
T=50ms
📤 HTTP 请求 (GET /events, Accept: text/event-stream)
T=60ms
✅ HTTP 响应 (200 OK, Transfer-Encoding: chunked)
T=100ms
📨 数据流推送中... (保持长连接,增量传输)
T=500ms
📨 event: update | data: {"price": 156.78}
T=1000ms
📨 event: update | data: {"price": 157.12}
准备就绪