在互联网应用中,实时通信是一项重要的需求。传统的HTTP协议是基于请求 - 响应模型,服务器无法主动向客户端推送数据,这在实时场景中会导致高延迟和资源浪费。Server-Sent Events(SSE)协议应运而生,它基于HTTP协议,允许服务器主动向客户端推送实时数据,为实现实时通信提供了一种轻量级的解决方案。
SSE是一种基于HTTP的轻量级协议,允许服务器通过单个HTTP连接持续向客户端推送实时数据。它是HTML5标准的一部分,旨在为Web应用提供一种简单、高效的实时数据传输方式。
data:
开头,结构清晰,易于解析。早期的HTTP协议是短连接、请求 - 响应模型,无法满足实时通信的需求。为了突破这一限制,开发者探索了长轮询(Long Polling)和HTTP流(HTTP Streaming)等技术,这些技术为SSE的发展奠定了基础。
2006年,Opera 9浏览器首次引入服务器推送事件(Server-Sent Events)的概念,允许服务器通过单个HTTP连接持续发送文本数据流。这一技术最初是试验性的,未形成标准化协议,但展示了单向实时通信的潜力。
2009年,W3C将SSE纳入HTML5规范草案,目标是提供一种轻量级、基于HTTP的服务器推送解决方案。2014年,SSE作为HTML5的正式组成部分发布,明确了协议细节,包括数据格式、客户端API和自动重连机制等。
Google Gmail在2009年通过类似SSE的技术实现邮件实时推送,展示了服务器推送在大规模Web应用中的可行性,加速了SSE的普及。主流浏览器(如Chrome、Firefox、Safari)从2010年代初期开始支持SSE,HTML5的广泛采用进一步推动了SSE的标准化。
SSE的数据流是文本格式,每个事件由多个字段组成,以换行符分隔。常见的字段包括:
每个事件块以空行 \n\n
结束,支持分段传输。例如:
id: 123
event: update
data: {"status": "success"}
id: 124
data: {"message": "Hello world"}
服务器在响应SSE请求时,需要设置特定的HTTP头:
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Content-Type: text/event-stream
是SSE的核心标识,告知客户端这是一个SSE响应。Cache-Control: no-cache
禁止浏览器缓存响应,确保客户端能实时获取最新数据。Connection: keep-alive
确保连接持久化,服务器可以持续发送数据。客户端断线后会自动尝试恢复连接,并通过 Last-Event-ID
头将最后一个接收到的事件ID发送给服务器,服务器可以从该位置继续发送数据。客户端默认以指数退避策略(3秒→6秒→12秒…)尝试重连,也可以通过 retry:
字段自定义重连间隔(单位:毫秒):
retry: 5000
data: {"reconnect": "in 5 seconds"}
以下是一个使用Python的Flask框架实现的SSE服务器示例,每秒向客户端推送一次当前时间:
from flask import Flask, Response
import time
import datetime
app = Flask(__name__)
def generate():
while True:
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 构建 SSE 消息
message = f"data: {current_time}\n\n"
yield message
time.sleep(1)
@app.route('/stream')
def stream():
# 设置响应头
return Response(generate(), mimetype='text/event-stream')
if __name__ == '__main__':
app.run(debug=True)
以下是一个使用JavaScript的 EventSource
对象实现的SSE客户端示例,接收服务器推送的实时时间并显示在页面上:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSE Clienttitle>
head>
<body>
<h1>实时时间更新h1>
<div id="output">div>
<script>
// 创建 EventSource 实例
const eventSource = new EventSource('/stream');
// 监听 message 事件
eventSource.onmessage = function (event) {
const output = document.getElementById('output');
const newLine = document.createElement('p');
newLine.textContent = event.data;
output.appendChild(newLine);
};
// 监听错误事件
eventSource.onerror = function (error) {
console.error('EventSource failed:', error);
};
script>
body>
html>
特性 | SSE | WebSocket |
---|---|---|
通信方向 | 单向(服务器→客户端) | 全双工(双向) |
协议复杂度 | 基于HTTP,无需额外握手 | 独立协议,需复杂握手 |
浏览器兼容性 | 现代浏览器支持 | 广泛支持 |
断线重连 | 自动支持 | 需手动实现 |
二进制支持 | 有限(文本为主) | 支持二进制 |
SSE适用于单向、轻量级的实时通信场景,如:
WebSocket更适合双向、高并发的实时通信场景,如:
SSE可与HTTP/2无缝结合,利用其多路复用特性提升性能:
通过Cloudflare等CDN节点就近分发数据,降低全球用户的延迟。
根据网络状况动态调整数据推送速度,避免拥塞。
SSE协议作为一种基于HTTP的轻量级实时数据推送协议,为Web应用提供了一种简单、高效的实时通信解决方案。它继承了HTTP协议的兼容性和简单性,同时解决了实时数据传输的需求。对于不需要双向通信的场景,SSE是比WebSocket更轻量、更易维护的选择。随着Web技术的不断发展,SSE协议在实时通知、流式输出等领域将继续发挥重要作用。