← 返回题目列表

长轮询、SSE 和 WebSocket 有什么区别?实时推送场景怎么选?

高频 中等 第 2 / 27 题 更新于 2026/07/31
长轮询SSEWebSocket实时推送

简化版

长轮询还是 HTTP 请求响应模型,服务端只是把响应挂起到有数据或超时;SSE 是基于 HTTP 的服务端单向文本流;WebSocket 是一次握手后的全双工长连接。只需要服务端推送、浏览器兼容和简单运维时优先 SSE;需要双向实时通信、低延迟互动、频繁上行消息时优先 WebSocket;兼容老系统或推送频率很低时可以用长轮询。

详细版

三者的核心区别在于连接模型和通信方向:

方案连接形态通信方向典型场景
长轮询多次 HTTP 请求,每次可挂起客户端请求,服务端延迟响应简单通知、老系统兼容
SSE一次 HTTP 响应持续输出文本事件服务端到客户端单向消息通知、进度条、监控日志
WebSocketHTTP Upgrade 后变成帧协议双向全双工聊天、协同编辑、在线游戏

长轮询的问题是请求多、服务端连接挂起多、实时性受超时和重连影响。SSE 比长轮询更自然,因为连接不断开,服务端可以持续写 text/event-stream,浏览器还支持自动重连和 Last-Event-ID。WebSocket 能力最强,但也带来连接状态、心跳、断线重连、鉴权、代理配置等复杂度。

面试回答时不要只说“哪个更高级”。正确选型要看:是否需要客户端频繁发消息、消息是否必须二进制、代理和网关是否支持、连接规模有多大、是否要断点续传、是否能接受 HTTP 语义和调试工具。

完整版教学

一、长轮询为什么还能用于实时推送

长轮询本质仍然是 HTTP:客户端发请求,服务端如果暂时没有数据,就先不返回,等有数据再返回;返回后客户端立刻发下一次请求。它解决的是普通短轮询“频繁空请求”的浪费,例如每 1 秒轮询一次,1 分钟就是 60 次请求,其中 55 次可能都是空结果。

长轮询把空请求合并成更少的挂起请求。假设服务端设置 30 秒超时,1 分钟最多只有 2 次空响应;如果第 12 秒有消息,就第 12 秒返回,客户端再重新请求。代价是服务端要维护大量未完成请求,网关、线程模型、连接池和超时配置都要配合。

普通轮询: 请求 -> 空响应 -> 等 1s -> 请求 -> 空响应 -> ...
长轮询:   请求 -> 等到有数据或 30s 超时 -> 响应 -> 立即下一次请求

长轮询的关键词不是“长连接协议”,而是“把一次 HTTP 响应延迟到有数据时再返回”。

二、SSE 的本质是 HTTP 文本流

SSE 使用普通 HTTP 响应,但响应头是 Content-Type: text/event-stream,服务端不一次性结束响应,而是不断写入事件。浏览器端通过 EventSource 接收消息,连接断开后会自动重连,服务端还可以通过 id: 配合 Last-Event-ID 做断点续传。

一个最小事件长这样:

HTTP/1.1 200 OK
Content-Type: text/event-stream

id: 101
event: price
data: {"symbol":"BTC","price":65000}

id: 102
data: heartbeat

SSE 的强项是服务端单向推送。比如订单状态、任务进度、日志流、监控告警,客户端主要是“看”,很少需要向服务端高频发消息。它仍然走 HTTP,调试和代理穿透通常比 WebSocket 更友好。

三、WebSocket 为什么适合双向实时通信

WebSocket 先通过 HTTP Upgrade 握手,服务端返回 101 Switching Protocols 后,连接上的数据就不再是普通 HTTP 请求响应,而是 WebSocket 帧。双方都可以随时发送数据帧,所以它适合双向交互。

例如在线协同编辑中,客户端每秒可能发送 10 次光标位置和编辑操作,服务端也要广播其他人的操作。如果用 SSE,客户端到服务端还得额外走 HTTP POST;如果用长轮询,请求数量会很大。WebSocket 则可以在同一条连接里双向传输,延迟和协议开销更低。

Client A <==== frame ====> Server <==== frame ====> Client B
          光标/编辑操作             广播/确认/冲突处理

但 WebSocket 的代价也明显:要处理心跳、断线重连、消息序号、背压、鉴权续期、负载均衡粘性或连接迁移。它不是“用了就更快”,而是把连接状态管理交给应用自己承担。

四、从通信方向看选型

最重要的判断维度是通信方向。只要业务是单向推送,SSE 往往已经够用;只有当客户端也要频繁主动发消息时,WebSocket 才明显占优。很多通知类系统并不需要全双工,把它做成 WebSocket 反而增加运维复杂度。

需求更合适方案原因
后端推送任务进度SSE单向、文本、自动重连
聊天室WebSocket双向消息频繁
后台审核结果通知长轮询或 SSE频率低,简单可靠
股票行情流SSE 或 WebSocket单向展示用 SSE,交易互动用 WebSocket
多人协同编辑WebSocket双向低延迟和状态同步

面试追问里,候选人如果能把“通信方向”先说出来,再补充连接规模、代理支持和可靠性设计,基本就不是背概念。

五、从资源消耗看三者差异

长轮询的主要成本是“反复建立请求上下文”和“挂起请求”。SSE 和 WebSocket 都是持续连接,连接数多时主要消耗文件描述符、内存、心跳流量和负载均衡连接槽位。假设 10 万客户端在线,每个连接占 4 KB 应用层状态,单状态内存就是约 400 MB,还没有算内核 socket buffer。

连接状态内存估算:
100000 * 4 KB = 400000 KB ≈ 390 MB

WebSocket 的消息是帧,头部较小;SSE 是文本流,格式简单但只适合 UTF-8 文本。长轮询每次返回都要重新发请求头,如果 Cookie 很大,例如 2 KB,请求次数多时会浪费不少带宽。

六、可靠性设计不能只靠协议

三种方案都需要考虑可靠性。长轮询要设置合理超时,避免网关 60 秒超时而应用 120 秒才返回;SSE 要处理 Last-Event-ID,断线后从最后确认的事件继续推;WebSocket 要设计心跳、重连退避、消息序号和补偿拉取。

一个常见的可靠推送流程是:

服务端生成事件 id=105
        |
        v
推给客户端,客户端记录 last_id=105
        |
        v
断线重连时携带 Last-Event-ID: 105
        |
        v
服务端从 106 开始补发

实时推送不等于可靠投递。真正可靠通常要有事件存储、序号、ACK 或补拉接口,否则连接断开期间的消息就可能丢。

七、网关和代理经常决定最终方案

很多线上问题不是协议本身,而是网关默认配置。例如 Nginx 对 SSE 需要关闭响应缓冲,否则服务端写了事件,客户端可能要等缓冲满才看到;WebSocket 需要透传 UpgradeConnection 头;长轮询要让代理超时大于应用超时。

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 75s;
proxy_buffering off;

如果公司网关、CDN 或企业代理不支持 WebSocket,SSE 或长轮询可能更稳定。工程选型经常不是“协议能力最强”,而是“现有链路能稳定承载”。

八、常见误区与追问

  • 误区:SSE 和 WebSocket 都是长连接,所以没有区别。 SSE 是 HTTP 文本流且单向,WebSocket 是独立帧协议且双向全双工。
  • 误区:长轮询已经过时,任何场景都不能用。 低频通知、老浏览器、网关限制强的场景,长轮询仍然简单可靠。
  • 误区:WebSocket 一定比 HTTP 快。 建连后帧开销小,但连接维护、心跳、状态恢复和负载均衡成本更高。
  • 误区:SSE 不需要心跳。 很多代理会回收空闲 HTTP 流,服务端通常要定期发送注释行或心跳事件。
  • 追问:SSE 为什么支持自动重连? 浏览器 EventSource 内置重连机制,并可通过事件 idLast-Event-ID 恢复位置。
  • 追问:WebSocket 如何做鉴权? 常见做法是在握手阶段用 Cookie、Token 或子协议传递身份,并校验 Origin。
  • 追问:大量连接怎么扩容? 要减少单连接状态、使用事件驱动模型、拆分连接网关,并通过消息总线把后端事件广播到连接节点。

九、加强记忆

实时推送先看方向:服务端单向推送优先想 SSE,双方频繁互发消息再想 WebSocket,推送频率低或兼容限制多可以用长轮询。长轮询是“延迟返回 HTTP 响应”,SSE 是“不断输出 HTTP 文本事件”,WebSocket 是“Upgrade 后走帧协议”。选型时把通信方向、连接规模、代理支持、断线恢复和运维复杂度一起说出来,答案就会从概念题变成工程题。