常见的实时通信技术(轮询、sse、websocket、webhooks)
1. HTTP轮询:最老实的办法
刚开始做实时功能时,我第一个想到的就是轮询。特别简单直白,就像你每隔5分钟就刷新一次朋友圈看看有没有新消息一样。
短轮询:勤快但费劲
短轮询就是客户端隔三差五地问服务器:"有新消息没?"不管有没有,服务器都会立即回答:"没有"或者"有,给你"。
专业一点的说法:
- 客户端定期向服务器发送HTTP请求
- 服务器立即响应,无论是否有新数据
- 客户端处理响应后,等待固定间隔再次请求
// 前端代码示例
setInterval(() => {
fetch('/api/check-updates')
.then(res => res.json())
.then(data => {
// 处理数据
});
}, 5000); // 每5秒问一次
优点:
- 实现简单,是个后端都会写
- 兼容性无敌,连IE6都支持
缺点:
- 太费流量了,就像你每隔5分钟就给朋友发微信"在吗?"
- 延迟感人,如果消息刚好在你两次询问之间来了,就得等下次轮询
长轮询:聪明一点的做法
后来我发现长轮询更聪明些。客户端问完"有新消息吗?",服务器会一直等着,直到真的有消息了才回复。
长轮询是对短轮询的改进:
- 客户端发送请求到服务器
- 服务器保持连接打开,直到有新数据或超时
- 一旦有数据或超时,服务器响应
- 客户端收到响应后立即发起新请求
function longPoll() {
fetch('/api/long-poll')
.then(res => res.json())
.then(data => {
// 处理数据
longPoll(); // 立即发起下一次请求
});
}
体验提升:
- 消息来得更快了,基本实时
- 请求次数少了,省流量
新问题:
- 服务器得一直挂着这些连接,人一多就撑不住了
- 还是得不停地建立新连接
2. SSE:服务器主动找你聊天
后来我发现SSE(Server-Sent Events)这个好东西。它就像你朋友主动给你发微信,不用你老问了。
- 客户端通过EventSource API建立到服务器的连接
- 连接保持打开状态,服务器可随时推送数据
- 数据以特定格式(text/event-stream)传输
- 自动处理连接中断和重连
// 前端
const eventSource = new EventSource('/sse-endpoint');eventSource.onmessage = (e) => {
console.log('收到消息:', e.data);
};
爽点:
- 消息实时推送,延迟超低
- 自动重连,断网也不怕
- 用起来特别简单
不爽的地方:
- 只能服务器推给你,你不能推给服务器(单向)
- 有些老浏览器不支持
- 只能传文本,想传文件没门
适合场景:
- 股票行情推送
- 新闻实时更新
- 像ChatGPT那种一个字一个字往外蹦的效果
3. WebSocket:真正的双向通话
想要真正的实时双向通信?那就得上WebSocket了。这就像微信通话,两边都能随时说话。
- 独立协议(ws://或加密wss://)
- 通过HTTP升级握手建立连接
- 之后保持持久连接双向通信
// 前端
const socket = new WebSocket('wss://example.com/ws');socket.onopen = () => {
socket.send('你好!');
};socket.onmessage = (e) => {
console.log('收到:', e.data);
};
为什么香:
- 真正的实时,延迟极低
- 双向通信,想发就发
- 一个连接管所有,省资源
坑也不少:
- 兼容性还是有点问题(不过现在大部分浏览器都OK了)
- 得自己处理断线重连
- 安全性要特别注意
最适合:
- 在线游戏(比如王者荣耀)
- 实时聊天(微信、QQ这种)
- 协同编辑(像腾讯文档)
4. Webhooks:让服务器主动找你
Webhooks比较特别,它让服务器主动调用你的接口。比如你女朋友说"有事给我打电话",这就是Webhooks。
工作流程:
- 你告诉服务器你的回调地址
- 服务器有事就直接call你
专业一点的说法
- 客户端(实际是接收服务器)提供回调URL
- 服务端在事件发生时向该URL发送HTTP请求
- 接收方处理事件并返回响应
// 你的服务器接口
app.post('/webhook', (req, res) => {
console.log('收到通知:', req.body);
res.status(200).end();
});
好处:
- 实时性很好
- 不用轮询,省事
要注意:
- 你的接口必须随时待命
- 得做好安全验证
- 高并发时可能会挂
常用在:
- 支付结果通知(比如支付宝回调)
- GitHub代码提交触发CI/CD
- 各种第三方服务集成
5、全面对比表
技术指标 | HTTP短轮询 | HTTP长轮询 | SSE (Server-Sent Events) | WebSocket | Webhooks |
---|---|---|---|---|---|
通信方向 | 客户端→服务器 | 客户端→服务器 | 服务器→客户端 | 双向全双工 | 服务器→客户端 |
协议基础 | HTTP | HTTP | HTTP | 独立协议(ws/wss) | HTTP |
连接方式 | 短连接 | 长连接 | 持久连接 | 持久连接 | 反向HTTP调用 |
实时性 | 低(依赖轮询间隔) | 中(减少轮询间隔) | 高 | 极高 | 高 |
数据格式 | 任意 | 任意 | 文本(Event Stream) | 文本/二进制 | 任意 |
实现复杂度 | ★★☆☆☆ | ★★★☆☆ | ★★★★☆ | ★★★★★ | ★★★☆☆ |
兼容性 | 全平台 | 全平台 | 现代浏览器 | 现代浏览器 | 全平台 |
服务器压力 | 高(频繁请求) | 中(保持连接) | 低 | 中(维护连接) | 取决于回调频率 |
客户端压力 | 低 | 低 | 低 | 中(需管理连接) | 需部署服务端 |
流量消耗 | 高(大量请求头) | 中 | 低(复用连接) | 极低 | 低 |
自动重连 | 需手动实现 | 需手动实现 | 内置支持 | 需手动实现 | 需手动实现 |
数据安全性 | 标准HTTPS | 标准HTTPS | 标准HTTPS | WSS加密 | 需额外验证 |
适用场景 | 简单通知,低频更新 | 中等实时性要求 | 实时通知推送 | 高频双向交互 | 服务器触发的外部通知 |
典型应用 | 简单消息提醒 | 基础聊天功能 | 股票行情、新闻推送 | 在线游戏、IM应用 | 支付回调、CI/CD触发 |
实现示例 | 定时AJAX请求 | 挂起HTTP请求 | EventSource API | WebSocket API | 提供回调URL端点 |
6、补充说明
-
渐进增强策略:
- 优先考虑:WebSocket > SSE > 长轮询 > 短轮询
- 回退方案:可考虑功能检测后自动降级
-
混合使用场景:
- WebSocket + Webhooks:用于不同业务场景
- SSE + 短轮询:兼容性方案
-
性能考量:
- 万级连接:WebSocket ≈ SSE > 长轮询 ≫ 短轮询
- 带宽消耗:短轮询 > 长轮询 > Webhooks > SSE > WebSocket
-
移动端特别提示:
- 注意移动网络下的连接稳定性
- 考虑省电模式对长连接的影响
-
安全建议:
- 所有技术都应使用加密版本(wss/https)
- Webhooks必须实现签名验证
- 限制连接频率防止DDoS