HTTP 长轮询与服务器发送事件(SSE)
字数 2102 2025-12-01 17:02:18
HTTP 长轮询与服务器发送事件(SSE)
-
传统客户端-服务器通信的局限
- 在标准的HTTP/Web模型里,通信总是由客户端(如浏览器)主动发起请求,服务器被动响应。服务器无法在未收到请求时,主动向客户端推送新信息。
- 对于需要实时或准实时获取服务器更新信息的应用(如聊天室、股票报价、新闻推送),传统做法是客户端轮询:每隔固定时间(如每秒)向服务器发送一次请求,询问是否有新数据。这种方式简单,但效率低下,会产生大量无效请求(即使没有数据更新),增加服务器和网络负担。
-
HTTP 长轮询(Long Polling)
- 概念:长轮询是对传统轮询的一种优化,旨在减少无效请求。
- 工作原理:
- 客户端像往常一样向服务器发起一个HTTP请求。
- 服务器收到请求后,并不立即响应。如果此时服务器有客户端需要的新数据,它会立即返回响应。
- 如果服务器没有新数据,它会保持这个连接打开,并挂起(hang)请求,直到以下任一情况发生:
- 有新的数据产生,服务器立即使用这个已建立的连接将数据作为响应返回给客户端。
- 一个预设的超时时间(如30秒、60秒)到达。此时即使没有新数据,服务器也会返回一个无新数据的响应(可能是一个空响应或特定状态码),然后关闭连接。
- 客户端收到响应(无论是包含数据的还是超时的响应)后,立即(或在短暂延迟后)发起一个新的长轮询请求,重复上述过程。
- 效果与优缺点:
- 效果:相比短轮询,长轮询显著减少了请求次数,并且能将服务器端产生的新消息近乎实时地(取决于网络延迟)传递到客户端。
- 优点:实现相对简单,兼容性极好(基于标准HTTP)。
- 缺点:
- 每次请求-响应周期结束后,都需要建立新的连接,依然存在开销。
- 服务器需要为每个挂起的连接保持资源(如内存、线程/进程),在大量并发客户端时对服务器有压力。
- 本质上仍然是客户端“拉取”模式的一种模拟,并非真正的服务器推送。
-
服务器发送事件(Server-Sent Events, SSE)
- 概念:SSE是一种真正的、单向的服务器向客户端推送数据的Web标准技术。它基于HTTP协议,提供了一种高效、低延迟的从服务器到客户端的单向通信通道。
- 工作原理:
- 建立连接:客户端使用JavaScript的
EventSourceAPI,向一个特定的服务器端点发起一个普通的HTTP GET请求。该请求头中包含Accept: text/event-stream。 - 保持连接:服务器响应此请求时,将响应头的
Content-Type设置为text/event-stream,并保持此HTTP连接长期打开,不关闭。 - 推送数据:此后,只要服务器有需要推送的新数据,就可以通过这个持久的连接,按照SSE定义的简单文本格式(以
data:开头的行等),随时写入(发送)一条“消息”。 - 接收数据:客户端的
EventSource对象会持续监听这个连接,自动解析接收到的消息流,并触发onmessage等事件,将数据传递给JavaScript代码进行处理。 - 自动重连:如果连接意外断开,
EventSource对象会自动尝试重新连接。
- 建立连接:客户端使用JavaScript的
- 核心特点:
- 真正的推送:服务器可以在任意时刻主动发送数据。
- 单向:只支持服务器到客户端方向。客户端如需向服务器发送信息,需使用另一个独立的通道(如XHR或Fetch API)。
- 基于HTTP/HTTPS:易于在现有网络设施中部署,通常能穿透防火墙。
- 文本协议:默认传输UTF-8文本数据。如需传输二进制数据,需先进行Base64编码。
- 内置功能:协议规范支持事件ID、重连时间设置、自定义事件类型等。
- 优缺点:
- 优点:真正的服务器推送,协议轻量、简单,自动重连,浏览器API易用。
- 缺点:单向通信;浏览器端有最大并发连接数限制(同一域名下通常6个),SSE会占用一个;在不支持
EventSource的老旧浏览器中需要降级方案(如使用长轮询)。
-
对比与应用场景
- HTTP长轮询 vs SSE:
- 协议本质:长轮询是“拉取”的巧妙模拟,SSE是标准的“推送”。
- 连接管理:长轮询频繁建立/关闭连接;SSE保持单一长连接,效率更高。
- 消息及时性:SSE消息到达延迟通常更低。
- 复杂度:SSE有标准API和协议格式,客户端实现更简洁;长轮询逻辑需更多手动控制。
- 应用场景选择:
- SSE:非常适合需要服务器向客户端持续发送事件流或数据更新的场景,例如实时新闻推送、股票行情、社交媒体动态流、服务器日志监控、任务执行进度报告等。
- HTTP长轮询:在需要极高兼容性(支持所有浏览器和HTTP/1.1环境)且对连接效率要求不是极致的场景中,仍是一个可靠的选择。它也可以作为不支持SSE环境下的降级方案。
- 注意:对于需要全双工(双向实时通信)的场景,如在线游戏、实时协作编辑,WebSocket是更合适的技术。SSE和长轮询是实现“服务器推送”需求的两种重要技术,而WebSocket提供了一个更强大、更底层的双向通道。
- HTTP长轮询 vs SSE: