短轮询 — 是一种客户端与服务器交互的技术,客户端按固定的时间间隔发送HTTP请求以获取更新的数据。服务器立即处理每个请求,即使没有变化也返回当前状态。根据Amazon Web Services, 2024,短轮询是最容易实现但效率最低的轮询方法,会给服务器和网络造成过大的负载。
要点
短轮询 — 是一种通信模式,客户端定期以预设的间隔向服务器发送HTTP请求,服务器同步处理每个请求并立即返回结果。轮询间隔由客户端使用定时器设置,通常为1到60秒,取决于数据时效性的要求。
短轮询是按时间顺序在Web应用程序中组织实时通信的第一个机制。在21世纪初,在第二代XMLHttpRequest出现之前,网页使用<meta http-equiv="refresh">或定期重新加载iframe来更新内容。随着2005年AJAX(异步JavaScript和XML)技术的出现,短轮询成为无需完全重新加载页面即可更新数据的标准方法。
短轮询的架构包括三个组件:客户端定时器、HTTP请求和服务器处理程序。客户端启动一个间隔定时器,当其触发时向服务器发送GET请求。服务器对数据库或其他源执行查询,形成响应并立即返回给客户端。客户端更新界面并等待下一个定时器触发。只要应用程序处于活动状态,这个周期就会无限重复。
短轮询的主要问题是不可避免的空请求。如果数据很少更改,大多数请求返回"无变化"的结果,浪费网络带宽和处理器时间。如果有10,000个客户端和5秒的轮询间隔,服务器每秒接收2,000个请求——如果更新频率是每分钟1个事件,其中很大一部分是无用的。
短轮询按照一个简单的周期工作:客户端设置一个具有指定周期(例如5000毫秒)的间隔定时器。每次定时器触发时,客户端向服务器端点创建HTTP GET请求,通常带有最后一次更新的时间戳参数。服务器接收请求,检查在指定时间戳之后是否有新数据,并返回响应——要么带有新数据,要么带有无更新的指示。
短轮询的关键配置参数是轮询间隔。太短的间隔(少于3秒)会给服务器和网络造成高负载。太长的间隔(超过30秒)会降低数据的时效性。最佳间隔取决于场景:监控面板5-15秒,新闻源30-60秒,关键警报1-3秒。间隔的选择总是在数据时效性和基础设施负载之间的权衡。
为了减少空闲期间的负载,使用自适应间隔:如果多个连续请求返回空结果,间隔会增加(例如从5秒增加到15秒)。当新数据出现时,间隔重置为最小值。指数退避算法可以在更新稀少时将空请求数量减少3-5倍。
让我们看看使用setInterval和Fetch API的短轮询客户端实现。该函数接受端点URL和以毫秒为单位的轮询间隔。
function startPolling(url, intervalMs) {
const lastTimestamp = new Date().toISOString();
const timerId = setInterval(async () => {
try {
const params = new URLSearchParams({
since: lastTimestamp
});
const response = await fetch(url + "?" + params);
const data = await response.json();
if (data.updates && data.updates.length > 0) {
renderUpdates(data.updates);
console.log("已接收", data.updates.length, "updates");
}
} catch (error) {
console.error("轮询失败:", error);
}
}, intervalMs);
return timerId;
}
const timer = startPolling("/api/updates", 5000);
// clearInterval(timer) 用于停止
代码创建一个周期为5秒的轮询间隔,并将最后一次更新的时间戳发送到服务器。服务器可以使用此参数过滤数据,只返回新记录,从而减少传输的信息量。函数返回定时器标识符以便停止轮询。
短轮询的服务器端实现非常简单——它是一个普通的REST端点,接收GET请求并返回带有当前状态或在指定时间戳之后更改的数据的JSON响应。
const express = require("express");
const app = express();
let items = [];
app.get("/api/updates", (req, res) => {
const since = req.query.since;
const filtered = items.filter(item => item.timestamp > since);
res.json({ updates: filtered });
});
app.listen(3000);
服务器接收since参数并过滤时间戳超过指定值的记录。这种方法最小化每个响应中的数据量,只返回增量更改。如果没有新数据,服务器返回空数组,客户端按计划继续轮询。
短轮询和长轮询解决相同的任务——从服务器传递数据——但在效率上有根本区别。短轮询使用固定的请求间隔,产生可预测的负载,而长轮询则保持连接直到事件发生,从而最大限度地减少空响应的数量。
| 标准 | 短轮询 | 长轮询 |
|---|---|---|
| 实现复杂度较低 | 标准REST | 中等,异步处理 |
| 更新延迟 | 固定,最多N秒 | 最小,事件发生时 |
| 请求数量 | 恒定,每分钟N个请求 | 按事件计,通常少得多 |
| 服务器负载 | 小间隔时高 | 保持连接,异步处理 |
| 空闲时流量 | 最大,每个请求带有标头 | 最小,一个开放连接 |
| 可扩展性 | 简单,无状态请求 | 复杂,需要共享事件队列 |
技术之间的选择取决于数据的更新频率。如果事件发生频率高于每10秒一次,两种方法产生相当的负载,短轮询可能更简单。如果事件很少(更改之间相隔数小时或数分钟),长轮询更可取,因为它不会产生空请求。对于中间场景,选择取决于基础设施限制和使用WebSocket的可能性。
短轮询用于数据时效性要求低、实现简单性优先于效率的场景。最典型的案例是内部管理面板、低警报频率的监控系统以及15-30秒延迟可接受的应用。
重要限制 — 短轮询不适用于对时间敏感的应用程序(交易终端、紧急警报系统),即使1秒的延迟也不可接受。在这种情况下,应使用WebSocket、Server-Sent Events或长轮询。设计使用短轮询的系统时,应计算请求预算:有1,000个客户端和5秒间隔时,服务器每分钟处理12,000个请求,这需要相应的资源基础。
常见问题
短轮询 — 是应用程序每N秒询问服务器"有新数据吗?",而服务器每次都回答,即使什么也没改变。就像每5分钟去邮箱检查是否有新邮件一样。
最佳短轮询间隔取决于场景:监控面板5-10秒,新闻源15-30秒,状态页面30-60秒。间隔应是数据时效性和服务器负载之间的折中。从10秒开始,根据测试结果调整。
短轮询 — 客户端以固定间隔不断"拉"服务器。长轮询 — 客户端发送一个请求,服务器保持它打开直到数据出现。短轮询实现更简单,但在更新稀少时会产生更多空请求。
短轮询 比WebSocket实现更简单,不需要特殊协议——通过普通HTTP请求工作。短轮询适用于简单的内部系统,10-30秒的延迟可接受,维护WebSocket的基础设施成本不合理。
使用自适应间隔:无更新时将请求间的暂停增加2-3倍。添加带最后一个请求时间戳的since参数,使服务器只返回增量更改。在CDN或代理服务器侧缓存响应以减少后端负载。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。