以掘金为例:为什么选择轮询?
不知道大家有没有留意,掘金平台的通知模块 一直使用轮询请求API,自上线至今,尽管UI和功能更新了好多版,这一块仍然使用轮询接口来获取最新数据,而不是更先进的 WebSocket 或 MQTT 。 这种典型的轮询机制在众多互联网产品中仍然广泛存在。为什么看似"简单粗暴"的轮询接口仍被大量采用?实时通信技术又该如何选型?
首先,我可以肯定的回答,肯定不是掘金平台的技术水平差
。那为什么没有使用诸如Web Socket技术呢?首先我们根据业务场景分析一下,只谈技术不谈场景都是耍流氓
为什么使用轮询?
-
兼容性好: 轮询是 HTTP 协议的基础操作,
几乎所有浏览器和服务器都支持
,而 WebSocket 需要额外的服务器支持。 -
开发成本低: 轮询的实现很简单,
只需要加个定时发送请求,离开页面关闭请求即可
。而 WebSocket 需要实现建立、连接、断开,重连。 -
低并发,长时间轮询,服务器扛得住: 首先,这个轮询是
大约30S一次
,时间太长也没意义,1分钟我觉得都OK。其次,相比较上拉刷新、下拉加载、查看等业务,这个轮询的使用频率是比较低的
,谁没事天天挂着个网页呀。就算真的有这种情况,那每日时长肯定高的很,估计运营平台都笑开花了。就算真的扛不住,升级这个功能,分分钟的事情
轮询、WebSocket、 MQTT 的对比
处理这种实时数据 的业务,常见的解决方式是:轮询、WebSocket、 MQTT。下面简单说下不同技术的优缺点
1. 轮询(Polling) 轮询是指客户端定期向服务器发送请求的操作
scss
setInterval(() => {
fetch('/api/notifications')
.then()
.then()
}, 1000 * 30)
优点:
- 简单易实现,所有 HTTP 服务器都支持
- 无需额外的协议支持,维护成本低
缺点:
- 数据延迟高,数据只能按固定时间间隔获取
大量无效请求,浪费带宽和服务器资源
适用场景: 低并发、对实时性要求不高的场景,如错误列表,站内信等
2. WebSocket
WebSocket是一种全双工通信协议,客户端和服务器可以在连接建立后随时发送数据。
ini
const ws = new WebSocket('wss://example.com/notifications');
ws.onmessage = (event) => {
console.log(event.data);
};
优点:
- 实时性强,数据变更可即时推送
- 相比轮询减少了无效请求,减少服务器负担
缺点:
- 需要额外的服务器支持(如 WebSocket 服务器)
- 连接数管理复杂,可能需要负载均衡
适用场景: 即时聊天、股票交易、在线协作等需要高实时性的场景
3. MQTT(Message Queuing Telemetry Transport)
MQTT 是一种轻量级的发布/订阅协议,通常用于物联网(IoT)。
ini
client = mqtt.Client()
client.connect("broker.example.com", 8001)
client.subscribe("sensors/#")
优点:
- 低功耗,适用于低带宽设备
- 服务器端可以进行消息存储和转发,保证数据可靠性
缺点:
- 需要专门的 MQTT 服务器
- 适用于 IoT 设备,浏览器支持较差,移动端需要SDK
适用场景: 物联网设备、智能家居、传感器数据收集
一句话总结:
对于大多数 Web 应用,轮询仍然是最常见的选择,因为它的实现简单,兼容性好。但如果应用对实时性要求高,比如聊天、直播、推送通知等,WebSocket 是更好的选择。而 MQTT 则更适合 IoT 场景。
现代架构演进方案
- 混合架构:主通道用WebSocket,兼容回退轮询
- 协议升级策略
bash
location /notifications {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
- 边缘计算优化:在边缘侧处理心跳、计算等需求
总结
没有最好的协议,只有最合适的方案 。在掘金这类技术社区中,采用轮询可能是出于历史架构演进成本、用户实际需求强度(非严格实时)等多维度权衡的结果。而我们在技术选型也应该建立在对业务场景、用户规模、团队能力的综合评估。
最后一句话: 所有的方案都要在压力测试扛得住的情况下论证,如果扛不住,果断想办法。