服务端单向给客户端推送消息(SSE)

1,258 阅读4分钟

服务器发送事件(Server-Sent Events,SSE)

SSE 是一种服务器向客户端推送数据的技术。

与传统的 HTTP 请求-响应模式不同,SSE 允许服务器在数据可用时主动将数据推送给客户端,而无需客户端不断轮询服务器以获取新数据。

主要特点和优势

  1. 实时性:能够实现近乎实时的数据推送,使客户端能够及时获取最新信息。

    • 例如,实时的股票行情更新、体育比赛比分推送等。
  2. 低开销:相较于客户端频繁的轮询请求,SSE 减少了不必要的网络流量和服务器负载。

  3. 简单易用:实现相对简单,客户端和服务器端的编程都不复杂。

  4. 兼容性:大多数现代浏览器都支持 SSE。(没错,就是IE不支持)

工作原理

客户端通过向服务器发送一个特殊的 HTTP 请求来建立 SSE 连接。服务器响应时设置特定的头信息,如 Content-Type: text/event-stream ,表示这是一个 SSE 流。然后,服务器可以随时向客户端发送以 data: 开头的多行文本数据。

应用场景

  1. 实时通知:如系统通知、新消息提醒。

    • 例如,社交媒体平台的新点赞或评论通知。
  2. 监控和日志:实时展示服务器的监控数据或日志信息。

  3. 在线协作:实时同步多个用户之间的操作。

服务端代码(nodejs/express)

import * as express from 'express'
const app = express()
const cors = require('cors');
app.use(cors());//允许跨域
app.use(express.json())

app.get('/stream', (req, res) => {
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');
    setInterval(() => {
        const data = `data: { "message": "Hello, SSE! - ${new Date().toISOString()}" }\n`;
        res.write(data);
    }, 2000);
});

app.listen(3000, () => {
    console.log('start sever at 3000')
})

res.setHeader('Connection', 'keep-alive');

用于保持连接处于活跃状态,这有助于确保 SSE 连接的稳定性和持续性。如果不设置这个头,连接可能会在某些情况下意外中断,影响数据的实时推送。

  • 例如,如果服务器在一段时间内没有发送数据,而连接没有被标记为 keep-alive,一些中间代理或浏览器可能会关闭连接。

res.setHeader('Cache-Control', 'no-cache')

用于防止浏览器或中间缓存对 SSE 流进行缓存。因为 SSE 流的数据是实时变化的,缓存可能导致客户端获取到过时或不正确的数据。

  • 例如,如果数据被缓存,客户端可能会一直显示之前缓存的旧数据,而不是实时接收到新的数据。

客户端代码

if (typeof(EventSource)!= "undefined"){
      const source = new EventSource("http://xx.xx.xx.xx:3000/stream");
        source.onmessage = function(event) {
          var message = JSON.parse(event.data).message;
          console.log('message:',message);
        };
        // source.close();//取消
    }

与WebSocket的区别

SSE(Server-Sent Events)和 WebSocket(WS)都是用于在客户端和服务器之间进行实时数据通信的技术,但它们有以下一些重要的区别:

  1. 全双工通信

    • WebSocket:支持全双工通信,意味着客户端和服务器可以同时相互发送数据。
    • SSE:是单向的,服务器向客户端推送数据,客户端无法直接向服务器发送数据。
  2. 协议开销

    • WebSocket:建立连接时的握手开销相对较大。
    • SSE:基于 HTTP 协议,建立连接相对简单,开销较小。
  3. 数据格式

    • WebSocket:可以发送任意二进制或文本数据,数据格式更灵活。
    • SSE:数据格式是特定的文本格式,以 data: 开头。
  4. 错误处理

    • WebSocket:提供更丰富的错误处理机制。
    • SSE:错误处理相对较简单。
  5. 适用场景

    • WebSocket:适用于需要双向实时交互的场景,如在线游戏、实时协作工具等。

    • SSE:更适合服务器向客户端单向推送数据的场景,如实时通知、股票行情更新等。

例如,在一个在线聊天应用中,如果需要用户之间实时发送消息,WebSocket 更合适,因为双方都需要主动发送消息。而对于一个只需要服务器向用户推送新消息提醒的应用,SSE 可能就足以满足需求,且更易于实现和维护。