Server-sent Events 和 WebSockets 应该如何选用

当前,随着 Web 技术的不断发展,越来越多的应用场景需要进行实时数据传输,而对于前端来说,Server-sent Events(SSE)与 WebSockets 是两种主要的实时数据传输方案。然而,两者各有优缺点,因此在实际项目中,我们需要根据具体需求选择合适的方案。本文将从应用场景、技术特点等方面详细介绍 Server-sent Events 和 WebSockets 的选择和应用。

一、SSE 和 WebSockets 的应用场景

首先,我们需要了解 Server-sent Events 和 WebSockets 的应用场景,以便对比两者的异同之处。

1. Server-sent Events(SSE)

Server-sent Events 也称为事件源(EventSource),即在客户端通过事件流(Event Stream)接收来自服务端的数据。Event Stream 其实就是一个一直打开的 HTTP 连接,服务器通过这个连接向客户端实时推送数据。根据这个特性,Server-sent Events 适用于以下应用场景:

  • 简单通知类:如新闻通知、股市行情通知等不需要超高实时性的应用场景。
  • 要求客户端轮询技术:如轮询一些简单的服务端接口,例如在线人数、在线用户等。

需要注意的是,由于 SSE 基于 HTTP 协议实现,因此不能发送二进制数据,且只能使用文本格式。

2. WebSockets

WebSockets 内置了类似于 TCP 协议的双向通信机制,因此相比于 SSE 具有更高的实时性和可靠性。WebSockets 适用于以下应用场景:

  • 实时音视频通信;
  • 实时数据展示(如能够做到接受潜在的大量消息,并将其交织在一起的应用程序)。例如,对于在线多人游戏或股票交易这类需要实时交互的应用来说,WebSockets 是最佳选择。

二、SSE 和 WebSockets 的技术特点

除了应用场景之外,我们还需要考虑 Server-sent Events 和 WebSockets 的技术特点,这有助于我们更好地理解两种方案的适用范围和限制。

1. Server-sent Events(SSE)

Server-sent Events 的技术特点如下:

  • SSE 基于 HTTP,需要重用已经存在的连接来向客户端推送数据,因此 SSE 消耗的资源更少且可靠性更高。而由于使用长轮询时需要不断新建连接,所以长轮询的消耗要比 SSE 高。
  • SSE 只能向客户端推送文本数据,并且数据格式只能是一种。传输的数据需要通过转义字符来进行编码(如换行、制表等)。因此 SSE 难以传输大文件和二进制数据。
  • SSE 在大多数浏览器上都有原生支持。但是,在 IE 浏览器中,由于 IE 不支持 EventSource 接口,需要使用 Polyfill。

2. WebSockets

WebSockets 的技术特点如下:

  • WebSocket 是一种全双工协议,客户端和服务端之间可以自由发送和接收消息,因此 WebSockets 比 SSE 具有更高的实时性和可靠性。
  • WebSocket 可以传输二进制和文本等多种数据类型,并且是多种数据格式的最佳选择。
  • WebSockets 使用了自定义的协议,客户端和服务端之间可以进行自由通信,因此需要使用对应的库或框架来实现。此外,WebSocket 的协议相对 SSE 和 HTTP 更加复杂,因此在实际应用中需要注意对 WebSocket 进行优化,以避免其带来的过多开销。

三、SSE 和 WebSockets 的示例代码

下面是 Server-sent Events 和 WebSockets 的示例代码,以供大家参考:

1. Server-sent Events(SSE)

  • 服务端示例代码(Node.js):
const http = require('http');
http.createServer((req, res) => {
    res.writeHead(200, {'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive'});
    setInterval(() => {
        const data = 'data: ' + Date.now() + '\n\n';
        res.write(data);
    }, 1000);
}).listen(8080);
  • 客户端示例代码(HTML + JavaScript):
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Server-sent Events 示例</title>
</head>
<body>
    <div id="message"></div>
    <script>
        const message = document.getElementById('message');
        const source = new EventSource('http://localhost:8080/');
        source.onmessage = function (event) {
            message.innerText = event.data;
        }
    </script>
</body>
</html>

2. WebSockets

  • 服务端示例代码(Node.js):
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
    setInterval(() => {
        ws.send(new Date().toLocaleString());
    }, 1000);
});
  • 客户端示例代码(HTML + JavaScript):
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>WebSockets 示例</title>
</head>
<body>
    <div id="message"></div>
    <script>
        const message = document.getElementById('message');
        const ws = new WebSocket('ws://localhost:8080');
        ws.onmessage = function (event) {
            message.innerText = event.data;
        }
    </script>
</body>
</html>

四、成本考虑

在选择合适的实时数据传输方案时,我们还需要考虑成本问题。从成本角度来看,SSE 与 WebSockets 有以下不同点:

  • SSE 基于 HTTP 协议,因此不需要维护长连接等,有着更少的开销。
  • WebSockets 在关闭连接等异常情况下,需要重新建立连接,因此打开和断开 WebSockets 连接的一般开销比SSE 的要高一些。

同时,我们还需要注意到,如果数据通信的负载很大,那么 Server-sent Events 的资源平均使用率要比 WebSockets 更高。因此,在实际应用中,我们需要根据具体需求和可接受的成本来选择合适的方案。

五、总结

本文从应用场景、技术特点、成本等多方面详细介绍了 Server-sent Events 和 WebSockets 的选择和应用。对于前端开发人员来说,选择其中的一种或技术的组合,需要根据具体业务需求以及技术特点来进行决策。在实际项目中,我们需要建立系统的架构设计,以便在不同的业务场景中实现更完善的实时数据传输。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65aa3c87add4f0e0ff3d5ceb


纠错反馈