告别“刷新”:一文搞懂 WebSocket、SSE 与轮询机制

在现代 Web 开发中,实时性已成为衡量用户体验的关键指标。从股票行情的跳动、AI 对话的流式输出,到在线协作编辑,都需要服务器能够"主动"与客户端通信。

为了实现这一目标,开发者们经历了从"笨拙"的轮询到"优雅"的长连接技术的演进。本文将深入剖析 短轮询、长轮询、WebSocketSSE (Server-Sent Events) 的核心区别、适用场景及技术细节。


1. 基础概念解析

🔄 短轮询

这是最原始的实现方式。客户端(浏览器)不管服务器有没有新数据,都每隔固定的时间(如 1秒)向服务器发送一次 HTTP 请求。

  • 原理:客户端定时发请求 -> 服务器立即响应(有数据返数据,无数据返空) -> 客户端处理 -> 等待下一次定时。
  • 缺点:极其浪费带宽和服务器资源。大部分请求可能是无效的(没有新数据),且实时性受限于轮询间隔。

⏳ 长轮询

这是对短轮询的优化。客户端发送请求后,如果服务器没有新数据,服务器不会立即关闭连接,而是将请求挂起(Hold住) ,直到有数据更新或达到超时时间才返回响应。客户端收到响应后,立即发起下一次请求。

  • 原理:客户端发请求 -> 服务器挂起连接(等待数据) -> 有数据了 -> 服务器响应 -> 客户端立即发新请求。
  • 优点:减少了无效请求,实时性比短轮询好。
  • 缺点:服务器需要维持大量挂起的连接,高并发下对服务器资源(线程/内存)消耗大。

⚡ WebSocket

HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

  • 原理 :通过 HTTP 协议发起握手请求,协商升级协议(Upgrade: websocket)。握手成功后,底层 TCP 连接保持打开,客户端和服务器可以随时互相发送数据
  • 特点:真正的双向通信,低延迟,支持二进制数据。

📢 SSE

Server-Sent Events 是一种允许服务器向浏览器单向 推送实时更新的技术。它基于 HTTP 协议,使用 text/event-stream 格式传输数据。

  • 原理 :客户端建立 HTTP 长连接 -> 服务器保持连接打开 -> 服务器有数据时直接推送 -> 客户端通过 EventSource API 接收。
  • 特点:基于 HTTP,单向推送(服务端 -> 客户端),原生支持断线重连。

2. 核心区别对比表

为了让你一目了然,我将这四种技术的核心差异整理如下表:

表格

特性 短轮询 长轮询 WebSocket SSE
通信方向 单向 (客户端请求) 单向 (客户端请求) 双向 (全双工) 单向 (服务端推送)
连接状态 频繁建立/断开 频繁建立/断开 (长连接挂起) 持久连接 持久连接
底层协议 HTTP HTTP WebSocket (独立协议) HTTP
数据类型 文本/JSON 文本/JSON 文本 & 二进制 仅文本 (UTF-8)
断线重连 无 (由定时器控制) 无 (需代码控制) 需手动实现 浏览器原生自动重连
实现复杂度 简单 中等 复杂 (需处理心跳、状态) 简单

3. 深度解析:WebSocket vs SSE

这是目前面试和选型中最常遇到的"二选一"问题。根据参考资料,两者的核心博弈点如下:

🛠️ 协议与连接

  • WebSocket:虽然握手阶段使用 HTTP,但一旦连接建立,它就升级为一个独立的 TCP 协议。它完全脱离了 HTTP 的请求-响应模式。
  • SSE :始终运行在 HTTP 协议之上。它利用了 HTTP 的长连接特性(Connection: keep-alive),服务器通过 Content-Type: text/event-stream 告诉浏览器"我要开始发流了,别关连接"。

🔄 通信模式

  • WebSocket双向车道。服务器可以发,客户端也可以发。适合聊天室、在线游戏等需要频繁交互的场景。
  • SSE单行道。只能服务器发给客户端。如果客户端想发数据(比如发送聊天内容),必须通过普通的 AJAX/Fetch 请求另起炉灶。

🛡️ 健壮性与重连

  • SSE 的杀手锏 :浏览器原生的 EventSource API 内置了自动重连机制 。当网络断开时,浏览器会自动尝试重新连接(通常有几秒的延迟),开发者无需编写复杂的 try-catch-reconnect 逻辑。
  • WebSocket :虽然强大,但原生 API 没有自动重连机制 。一旦连接断开,开发者必须手动监听 onclose 事件并编写重连逻辑(包括指数退避算法等),否则连接就彻底断了。

📦 数据格式

  • WebSocket :支持发送字符串和 ArrayBuffer(二进制),适合传输图片、音频流或 Protobuf 数据。
  • SSE:只能发送 UTF-8 编码的文本数据。如果需要传对象,通常序列化为 JSON 字符串。

4. 选型指南:我该用哪个?

根据参考资料中的建议,结合实际开发经验,建议如下:

✅ 选择 SSE 的场景

如果你的业务场景符合以下特征,SSE 是比 WebSocket 更轻量、更简单的选择

  1. 服务器单向推送:如实时通知、股票行情、体育比分、AI 大模型的流式回答(ChatGPT 类应用)。
  2. 数据量小且为文本:不需要传输二进制文件。
  3. 追求开发效率:不想处理复杂的连接管理和心跳检测,利用 HTTP 协议穿透防火墙更容易。
  4. 移动端兼容:在某些移动网络环境下,SSE 的保活比 WebSocket 更稳定。

✅ 选择 WebSocket 的场景

如果你的业务场景符合以下特征,WebSocket 是唯一选择

  1. 双向高频交互:如在线聊天、视频会议信令、协同编辑文档。
  2. 低延迟要求极高:如实时竞技游戏。
  3. 传输二进制数据:如实时音视频流传输。

✅ 轮询的使用场景

  • 短轮询:仅在老旧浏览器不支持 SSE/WebSocket,且实时性要求极低(如几分钟更新一次)时使用。
  • 长轮询:作为 WebSocket/SSE 的降级方案(Polyfill)。当网络环境极其恶劣,不支持长连接时,使用长轮询兜底。

5. 代码示例 (基于参考资料)

SSE 实现 (前端)

SSE 的使用非常简单,几行代码即可实现自动重连的实时流:

js 复制代码
// 前端代码
const eventSource = new EventSource('/api/stream');

// 监听消息
eventSource.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log('收到推送:', data);
};

// 监听自定义事件
eventSource.addEventListener('systemAlert', function(event) {
    console.log('系统警报:', event.data);
});

// 错误处理 (浏览器会自动尝试重连)
eventSource.onerror = function(err) {
    console.error("SSE 连接出错", err);
};

WebSocket 实现 (前端)

WebSocket 需要手动管理状态和重连:

js 复制代码
// 前端代码
const ws = new WebSocket('ws://localhost:8080');

ws.onopen = () => {
    console.log('连接已建立');
    ws.send('Hello Server');
};

ws.onmessage = (event) => {
    console.log('收到消息:', event.data);
};

ws.onclose = () => {
    console.log('连接已关闭,需要手动实现重连逻辑...');
    // reconnect();
};

📌 总结

  • 短/长轮询:是 HTTP/1.1 时代的妥协方案,现在多用于兼容降级。
  • SSE :是"轻量级的 WebSocket",专为服务端推送设计,原生支持重连,基于 HTTP,开发成本低,是 AI 流式输出和通知系统的首选。
  • WebSocket :是"全能型选手",专为双向实时交互设计,功能最强,但实现和维护成本相对较高。

参考资料及文章:

服务器发送事件

聊聊四种实时通信技术:长轮询、短轮询、WebSocket 和 SSE

前端如何理解SSE(Server-Sent Events)和WebSocket

放弃 Websocket 使用 SSE 才发现这些功能两三行代码就搞定了

为什么ChatGPT采用SSE协议而不是Websocket?

AI流式交互:SSE与WebSocket技术选型

AI场景前端必学------SSE流式传输

还在用 WebSocket 做实时通信?SSE 可能更简单

相关推荐
搬砖的前端2 小时前
本地模型+TRAE CN 打造最优模型组合实测:开源主模型+本地辅模型,对标GPT5.2/5.3/Gemini-3-Flash
前端·ai·mac·ai编程·qwen·trae·qwen3.6
userxxcc2 小时前
Waigo是用“Golang+Web”写的“视图窗口+稳定服务”的桌面端(Win、Mac、Ubuntu)多功能程序基座。开箱即用但有一定上手门槛。
javascript·golang·桌面应用基座·wails3
JaydenAI2 小时前
[FastMCP设计、原理与应用-11]Transform——数据炼金术,跨协议边界的无缝适配与格式转换
python·ai编程·ai agent·mcp·fastmcp
八代臻2 小时前
design-md
ai编程
吴声子夜歌2 小时前
Vue3——Vue CLI
前端·javascript·vue.js
我的世界洛天依2 小时前
洛天依讲编程:调音教学|调性 ——MIDI 里的「钩子函数」
linux·前端·javascript
javaDocker2 小时前
沉浸式AI编程:IDEA + Claude Code 的终极方案
java·intellij-idea·ai编程
Cobyte2 小时前
7.响应式系统比对:手写一个响应式状态库并应用在 React 上
前端·javascript·vue.js
渔舟小调2 小时前
P18 | Element Plus 通用 CRUD 页面模板:一个模板覆盖 80% 管理页面
javascript·vue.js·elementui