SSE — 什么是Server-Sent Events及单向流式传输

作者: IT Sectr 发布日期: 2026-06-02 阅读时间: 8 分钟

SSE(Server-Sent Events)——W3C标准,允许服务器通过单个HTTP连接以单向模式向客户端发送流数据。与WebSocket不同,SSE基于普通HTTP工作,不需要客户端使用特殊协议或库。根据W3C HTML Living Standard(2025)规范,EventSource API在所有现代浏览器中得到支持,包括Chrome、Firefox、Safari和Edge。

要点

  • SSE——通过HTTP连接从服务器到客户端单向数据传输的标准。
  • EventSource API——无需外部库即可接收SSE的内置浏览器接口。
  • 自动重新连接——浏览器在断开连接时自动恢复连接。
  • 文本协议——数据以text/event-stream格式传输,采用简单的文本格式。
  • 单向通信——SSE适用于通知、新闻推送、报价器和监控,但不适用于聊天。

什么是SSE?

SSE(Server-Sent Events)——一种允许Web服务器在建立连接后随时向客户端发送数据的技术。它由WHATWG作为HTML Living Standard的一部分进行标准化,并使用MIME类型text/event-stream。SSE支持传输文本数据,可以指定消息标识符、事件类型和重新连接延迟。

与需要双向协议和升级请求的WebSocket不同,SSE基于普通HTTP工作。服务器设置Content-Type: text/event-stream头,分块发送数据并保持连接打开。客户端通过浏览器的EventSource API接收数据,该API自动解析流并生成事件。

根据CanIUse(2025)数据,EventSource API在全球97.5%的浏览器中得到支持。在Internet Explorer和一些移动浏览器(Samsung Internet 7.0版本之前)中不受支持。对于这些情况,存在通过XHR流模拟EventSource的polyfill。SSE不适用于HTTP/1.1管道,但完全兼容HTTP/2服务器推送。

历史和标准化

SSE于2009年作为HTML5规范的一部分被提出,名为Server-Sent DOM Events。首次实现出现于Opera 9.0,随后是Firefox 6.0(2011)、Chrome 9.0(2011)和Safari 5.0(2010)。2015年,该规范被分离为HTML Living Standard的独立章节。尽管有十年的历史,由于其单向特性,SSE仍然不如WebSocket流行。

SSE如何工作

SSE的工作机制如下:客户端使用服务器端点的URL创建EventSource实例。浏览器发送带有Accept: text/event-stream头的GET请求。服务器以200 OK状态和Content-Type: text/event-stream头响应,然后开始以event-stream格式发送数据。连接保持打开状态,直到服务器发送终止信号或客户端调用close()。

服务器端,数据分块传输(分块传输编码)。每个数据块是由字段行(event、data、id、retry)组成的文本消息。服务器可以随时发送消息,这使SSE成为通知和状态更新的理想选择。连接不需要像WebSocket那样持续进行心跳包交换,尽管retry字段控制重新连接频率。

根据性能测试(2024)数据,SSE在消息大小为256字节时,每个连接每秒最多可提供10,000条消息的吞吐量。在服务器端,每个SSE连接消耗约5-10 KB内存,使一台拥有1 GB RAM的服务器能够支持50,000+并发连接。由于没有二进制协议,这比WebSocket显著减少。

event-stream格式

text/event-stream格式——一种简单的文本协议,其中每条消息由换行符分隔的命名字段组成。每个字段的格式为“字段名: 值”。消息由两个换行符(\n\n)分隔。

支持的字段:event(事件类型,默认为message)、data(数据字符串,可以多行)、id(最后事件标识符,存储在Last-Event-ID中)、retry(重新连接时间,以毫秒为单位)。注释以冒号(:)开头,解析器会忽略它们,但可用于心跳。

字段必需用途
event事件类型(默认为message)
data消息的数据字符串
id用于Last-Event-ID的事件标识符
retry重新连接延迟(毫秒)

event-stream流示例

text
: heartbeat comment
event: update
data: {"user": "Alice", "action": "typing"}
id: 1001

event: notification
data: {"type": "info", "text": "New version available"}
data: {"type": "action", "url": "/upgrade"}
retry: 3000

event: close
data: Session ended

客户端的EventSource API

EventSource API——用于接收SSE的内置浏览器接口。要创建连接,只需使用端点的URL调用构造函数即可。EventSource自动建立连接、处理重新连接并将传入消息解析为JavaScript事件。

EventSource事件:open(连接已建立)、message(收到消息,未指定event)、error(连接错误)。对于自定义事件(event: custom),可以使用addEventListener并指定事件名称。EventSource在重新连接时自动发送Last-Event-ID头,允许服务器从中断点恢复流。

根据MDN文档(2025),EventSource支持CORS和凭据传输(withCredentials)。EventSource不适合传输自定义头或请求体——需要通过fetch + ReadableStream手动实现。EventSource不支持二进制数据——仅支持文本和JSON。

客户端JavaScript代码

js
const eventSource = new EventSource('/api/events/stream');

eventSource.addEventListener('open', () => {
    console.log('SSE连接已打开');
});

eventSource.addEventListener('message', (event) => {
    const data = JSON.parse(event.data);
    console.log('已接收:', data);
    renderUpdate(data);
});

eventSource.addEventListener('notification', (event) => {
    const notification = JSON.parse(event.data);
    showNotification(notification.text);
});

eventSource.addEventListener('error', (error) => {
    console.error('SSE错误:', error);
    // 浏览器自动重新连接
});

// 关闭连接
eventSource.close();

SSE与WebSocket:比较

SSE和WebSocket——用于实时通信的不同技术,各有优势。WebSocket适用于双向数据交换(聊天、游戏、协作编辑),SSE适用于服务器到客户端的单向流(通知、新闻推送、报价器)。

关键区别——WebSocket需要从HTTP/1.1升级到WebSocket协议(ws://)的请求,这可能会被企业代理阻止。SSE基于普通HTTP工作,可通过所有代理,不需要特殊的服务器配置。SSE实现也更简单——服务器不需要额外的库,只需正确格式化HTTP响应即可。

根据对比测试(2024)数据,在一个服务器进程上,由于协议更简单,SSE比WebSocket支持多30-50%的连接。然而,SSE的延迟更高(50-200毫秒,WebSocket为10-50毫秒),因为SSE使用分块HTTP,而不是带有二进制帧的完全双向流。

特性SSEWebSocket
方向服务器 → 客户端双向
协议HTTP(text/event-stream)ws:// / wss:// (RFC 6455)
浏览器97.5%(内置EventSource)97%(内置WebSocket)
数据仅文本 / JSON文本 + 二进制(Blob、ArrayBuffer)
代理处理通过所有代理需要代理配置
重新连接自动(浏览器)手动实现
历史记录Last-Event-ID无内置历史记录

如何在服务器上实现SSE

在服务器上实现SSE不需要库——只需设置正确的HTTP头并以text/event-stream格式发送数据即可。让我们看看使用内置http模块在Node.js中的实现示例。服务器设置Content-Type和Cache-Control头,然后每隔N秒发送消息。

根据MDN Web Docs(2025),SSE的必需头包括:Content-Type: text/event-stream、Cache-Control: no-cache和Connection: keep-alive。如果没有Cache-Control,浏览器可能会缓存SSE流,导致传输停止。Connection: keep-alive明确指示浏览器保持连接打开。

Node.js服务器代码

js
const http = require('http');

http.createServer((req, res) => {
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
    });

    let eventId = 0;
    const interval = setInterval(() => {
        eventId++;
        res.write(`id: ${eventId}\n`);
        res.write(`event: update\n`);
        res.write(`data: {"时间": "${new Date().toISOString()}", "id":${eventId}}\n\n`);
    }, 2000);

    req.on('close', () => {
        clearInterval(interval);
    });
}).listen(3000);

Python(Flask)中的SSE

python
from flask import Response, Flask
import time
import json

app = Flask(__name__)

@app.route('/stream')
def stream():
    def generate():
        event_id = 0
        while True:
            event_id += 1
            data = json.dumps(
                {'ticker': 'AAPL', 'price': 150.25})
            yield f'id: {event_id}\nevent: price\ndata: {data}\n\n'
            time.sleep(1)
    return Response(generate(),
        mimetype='text/event-stream')

移动应用中的SSE

在移动应用中使用SSE受到iOS和Android缺乏原生EventSource实现的限制。在移动平台上,SSE通过第三方库实现:在iOS上——通过URLSession和NSURLProtocol,在Android上——通过支持SSE的OkHttp(okhttp-sse)。对于React Native和Flutter,有模拟EventSource的包可用。

在iOS上可以通过URLSessionDataDelegate实现原生SSE。在urlSession(_:dataTask:didReceive:)方法中接收数据时,应用累积缓冲区并手动解析event-stream格式。根据iOS开发博客(2024),由于没有心跳包,iOS上SSE的电池消耗比持续的WebSocket连接低40%。

在Android上,OkHttp提供了EventSource.Factory类用于订阅SSE流。Android应用可以在FCM不可用时使用SSE进行通知,或用于后台数据同步。Android上的SSE与WorkManager配合良好,适用于长期后台任务。根据OkHttp文档(2025),okhttp-sse支持带有自定义监听器的自动重新连接。

常见问题

SSE与WebSocket有何不同?

SSE——通过HTTP的单向传输(服务器→客户端),不需要客户端库。WebSocket——带有二进制协议的双向传输。SSE实现更简单,WebSocket适用于客户端也发送数据的任务。

SSE支持二进制数据吗?

不,SSE只传输文本数据。对于二进制数据(图像、音频),需要进行Base64编码,这会增加33%的大小。对于二进制流,最好使用WebSocket。

SSE如何处理连接中断?

EventSource在中断时自动重新连接。延迟时间由流中的retry字段设置(默认1000毫秒)。重新连接时,浏览器发送Last-Event-ID头,允许服务器从中断点恢复流。

浏览器可以维持多少个SSE连接?

每个浏览器对与同一域名的同时HTTP连接数量都有限制。对于HTTP/1.1——每个域名6-8个连接,对于HTTP/2——最多100个。SSE使用单个连接,因此不会与其他请求竞争。

SSE可以用于聊天吗?

SSE仅适用于接收消息(传入)。发送消息(传出)需要单独的HTTP请求(POST)。对于完整的聊天,更方便使用WebSocket或Socket.IO,在单个连接中实现双向通信。

总结

  • SSE——通过普通HTTP连接从服务器到客户端单向数据传输的标准,无需额外库。
  • EventSource API——内置浏览器接口,支持率占现代浏览器的97.5%。
  • 简单的文本协议text/event-stream,包含event、data、id和retry字段。
  • 自动重新连接,支持Last-Event-ID,可从中断点恢复流。
  • 效率——与WebSocket相比,由于协议更简单,SSE在服务器上支持更多连接(50,000+)。
  • 在移动平台上,SSE通过OkHttp(Android)或URLSession(iOS)实现,并手动解析流。
  • 对于单向流(通知、推送、报价器)选择SSE,对于双向通信——WebSocket或Socket.IO。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读