对于现代实时 Web 应用程序来说,将事件从服务器发送到客户端的能力是必不可少的。多年来,这种必要性导致了多种方法的发展,每种方法都有自己的优点和缺点。最初,长轮询是唯一可用的选择。随后 WebSockets 继承了它,为双向通信提供了更强大的解决方案。继 WebSocket 之后,服务器发送事件 (SSE) 提供了一种更简单的方法,用于从服务器到客户端的单向通信。展望未来,WebTransport 协议有望通过提供更高效、灵活和可扩展的方法来进一步彻底改变这一格局。对于利基用例[1],WebRTC 也可能被考虑用于服务器-客户端事件。
本文旨在深入研究这些技术,比较它们的性能,强调它们的优点和局限性,并为各种用例提供建议,以帮助开发人员在构建实时 Web 应用程序时做出明智的决策。这是我在实现 RxDB 复制协议以兼容各种后端技术时收集的经验的浓缩总结。
什么是长轮询?
长轮询是第一个启用服务器-客户端消息传递方法的“妙招”,该方法可以通过 HTTP 在浏览器中使用。该技术通过正常的 XHR[2] 请求模拟服务器推送通信。与传统轮询(客户端定期从服务器重复请求数据)不同,长轮询会建立与服务器的连接,该连接在新数据可用之前保持打开状态。一旦服务器有新的信息,它就会向客户端发送响应,并关闭连接。客户端收到服务器的响应后立即发起新的请求,如此循环往复。此方法允许更即时的数据更新并减少不必要的网络流量和服务器负载。但是,它仍然会导致通信延迟,并且效率低于 WebSocket 等其他实时技术。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function longPoll() { fetch("http://example.com/poll") .then((response) => response.json()) .then((data) => { console.log("Received data:", data); longPoll(); }) .catch((error) => {
setTimeout(longPoll, 10000); }); } longPoll();
|
在客户端实现长轮询非常简单,如上面的代码所示。然而,在后端,要确保客户端接收所有事件并且在客户端当前重新连接时不会错过更新,可能存在多种困难。