AI时代下网络传输协议的选择

关于本笔记

本笔记用于说明 WebSocket、SSE 与 HTTP 区别与应用场景。

在当今的 Web 开发中,”实时性”(Real-time)已经从加分项变成了硬需求。从早期的网页聊天室,到如今大火的生成式 AI(LLM)Token 流式输出,选择合适的网络传输协议直接决定了应用的架构复杂度和服务器成本。

很多开发者在面对实时通信时,脑海中蹦出的第一个词就是 WebSocket。但在如今的协议生态中,盲目选择 WebSocket 可能会让你背上沉重的“架构债”。本文将以客观、硬核的视角,深度拆解 HTTP、WebSocket 与 SSE(Server-Sent Events) 的底层区别,并结合当下 AI 时代与传统业务场景,聊聊该如何做技术选型。


目录


底层解构

要看清它们的区别,我们先从通信模型、协议特征和运维成本三个维度建立一张全景图:

特性维度 HTTP (传统/常态) WebSocket SSE (Server-Sent Events)
通信方向 单向(客户端发起请求) 全双工 (Bi-directional) 单向 (Server Push / 文本流)
底层协议 HTTP / 1.1 / 2 / 3 独立 TCP 协议 (基于 HTTP 握手升级) 纯粹的 HTTP 协议 (text/event-stream)
连接复用 请求-响应式,完毕即释放(Keep-Alive 仅复用 TCP) 持久连接,直到显式关闭 持久连接,直到显式关闭
断线重连 N/A (由每次独立请求处理) 需要前端手动实现心跳与重连逻辑 浏览器原生内置自动重连与断点恢复
防火墙/代理 完美兼容 可能会被某些严格的架构/公司代理拦截 完美兼容(等同于长耗时的 HTTP 响应)
有状态性 无状态 强有状态(服务器必须维护 Connection 实体) 有状态(但对后端进程的绑定弱于 WS)

HTTP:无法打破的“请求-响应”紧箍咒

传统的 HTTP(哪怕是支持了 Keep-Alive 的 HTTP/1.1 或多路复用的 HTTP/2)本质上都是客户端驱动的。服务端就像一个被动的自动售货机:不投币(不发 Request),就绝对不会吐出商品(Response)。虽然可以通过长轮询 (Long Polling) 来模拟实时性,但频繁建立连接的头部开销和“空跑”丢包,在现代高并发场景下无异于饮鸩止渴。

WebSocket:野蛮生长的全双工通道

当 Web 需要绝对自由的双向长连接时,WebSocket 诞生了。它在初始阶段借用 HTTP 的 Upgrade: websocket 协议头完成握手,随后便彻底脱离 HTTP 协议,在底层的同一个 TCP 通道上进行双向、无状态限制的二进制或文本传输。它的帧(Frame)非常轻量,没有臃肿的 HTTP Header,延迟极低。

SSE:返璞归真的 HTTP 管道流

很多工程师常常忽略了 SSE (Server-Sent Events)。它是 HTML5 标准的一部分,完全基于标准的 HTTP 协议
它的工作原理极其闷骚且优雅:客户端发起一个普通的 HTTP 请求,服务端在返回的 Header 中声明 Content-Type: text/event-stream。然后,这个连接就永远不关闭。服务端可以像挤牙膏一样,源源不断地向客户端发送一行行的文本数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// SSE 服务端返回的典型报文
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

id: 1
event: message
data: {"text": "Hello"}

id: 2
event: message
data: {"text": "World"}


AI时代下的选择:为什么大模型普遍偏爱SSE?

如果你观察过 ChatGPT、Claude 或者 DeepSeek 的网络请求,你会发现一个惊人的共识:它们的对话文本流式输出(Token Streaming),几乎清一色采用了 SSE 协议,而不是 WebSocket。

这背后的技术考量非常反直觉:既然是 AI “聊天”对话,为什么不用双向通信的 WebSocket,反而倒退回单向的 SSE?

  1. 业务本质是“单向重度输出”

在 AI Chat 场景中,用户的行为模式是:输入一句话(轻量请求) $\rightarrow$ 等待 AI 吐出几百上千字(长时、高频的重度流式输出)。
用户在发送完 Prompt 之后,在 AI 回复期间几乎不需要再向服务器发送高频数据。这种“一问百答”的模式,完美契合 SSE 的单向通道模式:客户端通过一个普通的 POST/GET 把 Prompt 发过去,服务端通过 SSE 把 Token 源源不断地“推”给前端。

  1. 基建红利:HTTP/2 与 HTTP/3 的多路复用

在过去(HTTP/1.1 时代),浏览器对同一个域名的 SSE 连接有严格的限制(通常最多 6 个)。这意味着如果用户开了多个 AI 标签页,连接很快就会耗尽。
但如今(2026年),HTTP/2 和 HTTP/3 早已全面普及(覆盖超 90% 的 Web 流量)。在 H2/H3 下,TCP/QUIC 引入了多路复用机制,所有的 SSE 流都可以在同一个连接中分流(Streams)传输,彻底打破了 6 个连接的限制,且没有 HTTP/1.1 的队头阻塞(Head-of-Line Blocking)问题。

  1. 运维成本的降维打击
  • 网关与负载均衡: WebSocket 属于非 HTTP 协议,常规的 Nginx、Cloudflare 等 CDN 或企业防火墙,需要专门配置才能支持 WS 升级,甚至经常被公司内网的深度包检测(DPI)拦截。而 SSE 就是纯粹的 HTTP 响应,普通的负载均衡器不需要任何特殊改动就能完美分发。
  • 水平扩展(Scalability): 如果用 WebSocket,服务器必须在内存中维护成千上万个 Socket 实例。若后端做多节点水平扩展,为了确保消息路由正确,你必须引入 Redis Pub/Sub 或 NATS 来做跨节点的消息广播和连接同步。而 SSE 本质上是无状态的 HTTP 生成器(比如 Python 的 asyncio 异步生成器 yield),当连接断开时,资源能立刻被垃圾回收,基建极其“枯燥且安全”。
  • 原生断线重连: 移动端网络不稳定时,WebSocket 一旦断开,你必须自己写一套复杂的 Heartbeat -> Ping/Pong -> Exponential Backoff 的重连代码。而浏览器对 SSE 提供了原生支持(EventSource API),断线了浏览器自己会在后台默默重连,甚至能通过 Last-Event-ID 自动向后端请求断点续传。

小结:

除非你的 AI 应用需要极其复杂的“用户中途高频打断/实时语音互动(通常走 WebRTC)”,否则 AI 文本流式输出,SSE 是绝对的行业标准和最优解。


其它业务场景的选择

脱离了 AI 场景,回到传统的互联网业务,我们又该如何根据技术特征各司其职?

  1. 场景 A:必须死守 WebSocket 的主战场

如果你的业务满足:高频(每秒多次)、低延迟(<100ms)、强双向交互。不要犹豫,WebSocket 依然是无可替代的王者。

  • 多人协同编辑(如 Figma、Google Docs): 每一个用户的鼠标轨迹、每一次按键,都需要实时同步给房间内的其他人,客户端既是高频接收者,也是高频发送者。
  • 实时多人在线游戏: 玩家的移动指令、技能释放(Client $\rightarrow$ Server)与世界状态同步(Server $\rightarrow$ Client)必须在同一个低延迟全双工通道内闭环。
  • 金融高频交易盘口: 用户需要在一秒内看到数十次报价变动,同时需要以毫秒级延迟提交买卖订单。
  1. 场景 B:适合用 SSE 替代 WebSocket 的“伪双向”战场

很多开发者习惯性把“实时更新”等同于 WebSocket。事实上,对于绝大多数“服务器推数据,客户端看数据”的单向场景,改用 SSE 能让你的架构轻松 10 倍。

  • 监控大屏 / 实时仪表盘 / 股票走势图: 数据每秒都在变,但都是服务器在源源不断地推,客户端只是被动渲染。
  • 系统通知 / 运营长连接推送: 类似于外卖骑手位置更新、社交媒体未读红点提示、电商降价通知。
  • 耗时任务进度条: 比如后台导出 100 万行 Excel,或者部署代码时的 Log 实时滚动输出。

    过去大家喜欢用 WS 做日志输出,现在用 FastAPI/Express 配合 SSE,几行代码就能搞定一个极其健壮的实时日志流。

  1. 场景 C:回归 HTTP(RESTful / 轮询)的传统战场

技术不是越新越好,不要为了技术KPI强行上长连接。

  • 低频状态更新(如外卖订单状态): 订单状态从“已接单 $\rightarrow$ 制作中 $\rightarrow$ 配送中”,整个过程长达半小时,总共就变动 3-4 次。这种场景下,客户端每隔 30 秒进行一次轻量级的普通 HTTP 轮询,或者利用定时器查询,服务器和网络带宽的开销几乎可以忽略不计,开发成本最低。

HTTP拓展讲解

在日常开发中,我们常看各种网络优化的八股文,但作为一名不甘于平庸的 IT 技术人,如果我们的视野只停留在 HTTP 1.1,显然无法看清现代大厂架构演进的底层逻辑。

从传统的文本传输,到如今吃满带宽的二进制流,再到大厂 App(如抖音、淘宝)全面拥抱的 UDP 时代,Web 协议经历了一场为了抹平网络延迟、压榨传输极限的史诗级演进。

今天,我们就站在架构师的视角,纵向拆解 HTTP 1.0 $\rightarrow$ 1.1 $\rightarrow$ 2.0 $\rightarrow$ 3.0 的技术演进图谱,看看那些改变互联网体验的底层黑科技。

HTTP 1.x 时代

HTTP/1.0 和 HTTP/1.1 名字只差一个小版本,但它们在连接复用、缓存、Host 头、状态码和带宽优化上都有明显差异。

  • 连接方式:HTTP/1.0 为短连接,HTTP/1.1 支持长连接。
  • 状态响应码:HTTP/1.1 中新加入了大量的状态码,光是错误响应状态码就新增了 24 种。比如说,100 (Continue)——在请求大资源前的预热请求,206 (Partial Content)——范围请求的标识码,409 (Conflict)——请求与当前资源的规定冲突,410 (Gone)——资源已被永久转移,而且没有任何已知的转发地址。
  • 缓存处理:在 HTTP/1.0 中主要使用 header 里的 If-Modified-Since、Expires 来作为缓存判断的标准,HTTP/1.1 则引入了更多的缓存控制策略,例如 Entity Tag、If-Unmodified-Since、If-Match、If-None-Match 等更多可供选择的缓存头来控制缓存策略。
  • 带宽优化及网络连接的使用:HTTP/1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP/1.1 则在请求头引入了 Range 头域,它允许只请求资源的某个部分,即返回码是 206 (Partial Content),这样就方便了开发者自由选择以便于充分利用带宽和连接。
  • Host 头处理:HTTP/1.1 在请求头中加入了 Host 字段。

HTTP 1.1 最大的功劳是引入了长连接(Connection: keep-alive),避免了 1.0 时代每次请求都要进行 TCP 三次握手的巨大开销。

然而,HTTP 1.1 依然存在致命的设计硬伤

  1. 痛点根源:应用层队头阻塞(Head-of-Line Blocking)

尽管 HTTP 1.1 复用了同一个 TCP 连接,但它在通道内的通信是严格串行的。
客户端必须等前一个请求的响应完全接收之后,才能发送下一个请求。如果排在最前面的请求在服务端遇到了复杂的 SQL 查询或大文件计算(被卡住了),后面所有本该瞬间返回的轻量级请求都会被死死堵住。

  1. 前端当年的“无奈妥协”

为了绕过这个硬伤,过去十几年间,前端工程师和运维被迫发明了大量“奇技淫巧”:

  • 域名分片(Domain Sharding): 浏览器限制对单个域名的并发 TCP 连接数(通常为 6 个)。于是大家把静态资源分散到 img1.cdn.comimg2.cdn.com 等多个域名上,强行多开 TCP 通道。
  • 精灵图/雪碧图(CSS Sprites): 把几十个小图标拼成一张大图来合并请求。
  • 大包捆绑(Webpack/Vite): 宁可牺牲局部更新的灵活性,也要把几十个 JS 文件揉成一个,就是为了减少 HTTP 请求次数。

HTTP 2.0 时代:二进制流与多路复用

2015 年发布的 HTTP 2.0(基于 Google 的 SPDY 协议)彻底颠覆了 HTTP 1.x 的文本传输模式,其核心目标就是:用一个 TCP 连接,彻底吃满所有带宽。

  1. 核心技术解密
  • 二进制分帧层(Binary Framing Layer):
    HTTP 2.0 不再采用 1.x 的纯文本(Header + Body)形式,而是将所有信息分割为更小的帧(Frame),并采用二进制编码。这直接将 HTTP 的解析从繁重的“字符串匹配”降维到了“位运算”,执行效率暴增。
  • 多路复用(Multiplexing):
    在同一个 TCP 连接中,可以并行发送无数个请求和响应。每个请求/响应被称为一个流(Stream),它们被切碎成带有 ID 标记的二进制帧混杂在通道中传输。收到后,对端再根据 ID 组装。自此,连接不需要排队,域名分片技术彻底退出历史舞台。
  • HPACK 头部压缩:
    HTTP 1.x 的 Header 极其臃肿(每次都带上长长的 Cookie、User-Agent)。HTTP 2.0 在客户端与服务端两端维护了一张共同的静态/动态哈希表。相同的 Header 只需要传一个索引号(几个 bit),大幅压榨了空间成本。
  1. 隐藏的硬伤:传输层队头阻塞

HTTP 2.0 完美解决了 应用层 的队头阻塞,但它却撞上了更底层的硬骨头 —— TCP 协议自身的队头阻塞

因为 HTTP 2.0 把所有鸡蛋放在了一个篮子里(只用一个 TCP 连接)。一旦网络发生丢包,TCP 为了保证“可靠传输”,会暂停整个连接去等待那个丢失包的重传。这时候,该 TCP 连接上所有的 HTTP 流全部停摆。

实际上: 在弱网(如地下车库、高铁、移动 4G 切换)环境下,HTTP 2.0 的性能甚至不如 HTTP 1.1(因为 1.1 有 6 个独立 TCP 连接,丢了一个包,另外 5 个还能跑)。

HTTP 3.0 时代:抛弃 TCP,拥抱全新的 QUIC 协议

为了彻底干掉 TCP 带来的历史包袱,2018 年提出的 HTTP 3.0 做出了一个惊天的决定:抛弃 TCP,改用 UDP。

很多人会问:UDP 是不可靠的、会丢包的,Web 传输怎么能允许丢包?

HTTP 3.0 只是利用了 UDP 的无连接特性,自己在 UDP 之上实现了一套比 TCP 更现代、更高效的可靠传输协议 —— QUIC(Quick UDP Internet Connections)。

进行解析:

  • 真正解开传输层队头阻塞:
    QUIC 协议在底层就原生支持“流(Stream)”。在 HTTP 3.0 中,如果 Stream 1 的数据包丢了,只有 Stream 1 会陷入等待重传,Stream 2、Stream 3 依然可以畅通无阻地传输。传输层的队头阻塞被彻底拔除。

  • 0-RTT 极速握手连接:
    传统的 HTTPS(HTTP 2.0 + TLS 1.2)建立连接需要:TCP 三次握手(1 RTT) + TLS 密钥交换(1-2 RTT),首包响应往往需要 2-3 个 RTT(往返时延)。
    而 HTTP 3.0 将传输握手与加密握手(TLS 1.3)合二为一。首次连接只需 1 RTT,再次连接时甚至能做到 0-RTT —— 客户端在发第一个包的同时就能带上加密的业务数据。

  • 连接迁移(Connection Migration):
    TCP 是基于“四元组”(源IP、源端口、目的IP、目的端口)来唯一确定一个连接的。当你从 Wi-Fi 切换到手机 5G 信号时,IP 变了,TCP 连接必须断开重连(手游断线、视频卡顿就是这个原因)。
    QUIC 抛弃了四元组,改用一个由客户端生成的 64位 Connection ID。只要这个 ID 不变,无论你的网络怎么切、IP 怎么变,底层的业务流完全无感知,不需要重新握手

简要总结

为了方便大家建立全局的直观认知,我们将这四个时代的底层演进线索整理成如下对比表:

技术维度 HTTP 1.0 HTTP 1.1 HTTP 2.0 HTTP 3.0
底层传输协议 TCP TCP TCP UDP (基于 QUIC)
默认连接模式 短连接 长连接 (串行) 长连接 (多路复用) 无连接 (逻辑复用)
数据传输形式 纯文本 纯文本 二进制分帧 二进制分帧
队头阻塞位置 应用层 (Request 级别) 应用层 (Response 级别) 传输层 (TCP 丢包阻塞整个连接) 彻底无队头阻塞
安全层 (TLS) 额外高级叠加 (HTTPS) 额外高级叠加 (HTTPS) 强制依赖 TLS 1.2+ 原生内置 TLS 1.3
网络切换表现 频繁重建连接 频繁重建连接 重连成本极高 支持连接迁移 (无感切换)
  • HTTP 1.1 目前依然是大量内部微服务 RPC、老旧系统、本地开发(localhost)的万能基石,兼容性最好。
  • HTTP 2.0 是目前公网 Web 服务的绝对主力。如果你的业务主要面向城市固网、宽带环境,升级到 HTTP 2.0 能带来最明显的白屏时间收益。
  • HTTP 3.0 (QUIC) 则是移动端、大流量 App、跨国电商、直播和弱网环境下的终极利器。如果你的业务涉及到频繁的移动端网络切换(如车库、地铁),或者要求极致的首屏拉起速度,部署 HTTP 3.0 将是拉开与竞争对手技术差距的分水岭。

总结

在 2026 年的今天,网络协议的演进早已不是“谁取代谁”的单一叙事。作为开发者,我们可以总结出一套现代的选型直觉:

  1. 能用纯粹的 HTTP 解决的(低频交互、非实时),坚决用 HTTP。
  2. 只要是单向的数据流动(服务器推、客户端看、或者像 AI Token 这种一问百答的流式输出),优先选择基于 HTTP/2+ 的 SSE。
  3. 只有在业务退无可退、必须依赖高频双向实时交互时,再请出 WebSocket 这尊大佛,并做好在底层引入 Redis Pub/Sub 等高可用基建的准备。

把复杂的工具留给极端的场景,把简单的技术留给日常的业务,这才是最优雅的架构实践。