一句话说清楚:长轮询(Long Polling)是客户端发一个 HTTP 请求,服务器先不回复,把这个请求“挂”着;等真的有了新数据,或者等到超时,才返回一个响应;客户端收到响应后立刻再发一个请求,如此循环。
打个比方
短轮询(Short Polling)像不停打电话问快递站:“我的包裹到了吗?”大多数时候只得到“没到”,白打一遍。长轮询是快递站说:“电话别挂,到了我马上喊你。”于是这条线一直占着。包裹真到了,喊一声然后挂断;你立刻重新拨过去继续等。如果等太久,快递站也会说句“暂时没有”,你照样重拨。
关键点在于:什么时候有数据由服务器说了算,但每一次数据仍然是客户端“要”回来的。所以它本质还是拉,只是把节奏交给了服务端,常被叫做伪推送。
几个必须知道的细节
- 一次请求最多带一次响应。推完就结束,客户端负责马上重连,于是形成“请求—响应—再请求”的循环。
- 服务端不能真拿线程死等。通常用异步 I/O 把请求挂起,有数据时再唤醒,否则几千个连接就把线程池占满了。
- 超时要设。中间的代理、负载均衡往往有自己的空闲超时,挂太久会被当成坏连接掐掉。
- 挂起的连接是真实占用。连接数、内存、会话保持,都得提前算总账。
| 方式 | 谁决定时机 | 方向 | 典型延迟 | 主要代价 |
|---|---|---|---|---|
| 短轮询 | 客户端定时 | 拉 | 取决于间隔 | 大量空请求 |
| 长轮询 | 服务端(挂起) | 拉(像推) | 有数据即返回 | 每次响应后重连 |
| SSE | 服务端 | 单向下行 | 低 | 一条长连接占着 |
| WebSocket | 双方 | 双向全双工 | 最低 | 需协议升级 |
和相邻概念的区别
短轮询实现最简单,代价是延迟等于间隔、空请求多。SSE(Server-Sent Events)一次连上就持续推,只走下行,适合通知流和日志流。WebSocket 双向全双工、延迟最低,但要走协议升级,链路上的中间设备不一定都友好。长轮询夹在中间:笨,但兼容性最好。
对从业者的意义
长轮询是实时推送普及之前的通用手法,今天依然活着:异步任务查进度、训练和推理任务的结果回传、通知未读提醒,乃至一些模型接口“挂住直到有结果”的等待模式,背后往往都是它的变体。优点是纯 HTTP,浏览器和老系统几乎不用改造;缺点是每次响应后都要重建连接,请求头开销和连接压力都实打实。
选型可以这样想:事件偶发、客户端在浏览器、后端不想大改——长轮询够用;高频双向交互——上 WebSocket;纯粹的单向广播——SSE 更省事。各平台对超时、连接数、代理行为的具体限制,以官方文档为准。
