HTTP 的局限

HTTP 是请求—响应模型:客户端发起请求,服务器返回响应,连接结束。

如果服务器有数据要主动推给客户端(如聊天消息、实时行情),HTTP 本身做不到。

几种替代方案

轮询(Polling)

客户端定时发请求:"有新消息吗?"

缺点:

  • 大量无效请求(大部分时候没有新消息);
  • 实时性差(取决于轮询间隔);
  • 浪费带宽和服务器资源。

长轮询(Long Polling)

客户端发请求,服务器不立即返回,而是等到有新数据时再返回;如果超时仍无数据,也返回。

客户端收到响应后立即再发一个请求。

改进:减少了无效请求,实时性接近实时。

缺点:

  • 每次响应后都要重新建立连接(HTTP 开销);
  • 服务器需要维持大量挂起的请求;
  • 实现相对复杂。

Server-Sent Events(SSE)

基于 HTTP 的单向推送:服务器可以持续向客户端发送数据。

特点:

  • 单向(只能服务器 → 客户端);
  • 基于 HTTP,实现简单,自动重连;
  • 文本协议(要传二进制需编码)。

适合:实时通知、日志流、进度更新等只需单向推送的场景。

WebSocket

全双工的双向通信通道。

建立过程:

  1. 客户端发起一个特殊的 HTTP 请求,带 Upgrade: websocket 头;
  2. 服务器同意(返回 101 Switching Protocols);
  3. 连接从 HTTP 协议"升级"为 WebSocket 协议;
  4. 之后双方可以随时互相发送数据,无需再发起请求。

优点:

  • 真正的双向实时通信;
  • 数据帧开销小(握手之后,每个数据帧只有 2–14 字节的头部,而 HTTP 请求的头部往往有几百字节);
  • 支持二进制和文本。

代价:

  • 需要服务器维护长连接状态(与无状态的 HTTP 不同,这影响架构和扩展性);
  • 负载均衡需要考虑连接保持(需要"粘性会话"或专门的网关);
  • 需要处理连接断开和重连;
  • 某些代理和防火墙可能对 WebSocket 支持不好。

心跳与保活

长连接可能被中间设备(NAT、防火墙)在空闲时切断。

解决方案是心跳:定期发送一个小的 ping/pong 帧,保持连接活跃。

WebSocket 协议本身定义了 ping/pong 帧,应用层也可以自己实现。

重连策略

网络中断不可避免。客户端需要:

  • 检测连接断开;
  • 指数退避重连(避免瞬间大量重连请求压垮服务器);
  • 重连后恢复状态(如重新订阅频道、拉取断连期间的消息)。

怎么选

  • 只需服务器推送(通知、直播弹幕)→ SSE 更简单;
  • 需要双向实时(聊天、协作编辑、多人游戏)→ WebSocket;
  • 实时性要求不高(每分钟更新一次的数据看板)→ 定时轮询完全够用,也最简单。

不要为了"技术先进"而引入 WebSocket——它的复杂度和运维成本是实实在在的。

说明:本文为实时通信协议的公开知识整理。