Server-Sent Events(SSE)是一种允许服务器向客户端发送实时更新的 Web API,在开发的 MCP Server 中启动 SSE 可以实现服务器主动向客户端推送数据。
定义和基本概念
SSE 是一种基于 HTTP 协议的 Web API,它允许服务器在客户端建立连接后,持续向客户端发送事件流。与传统的客户端轮询(客户端定期向服务器发送请求以获取更新)不同,SSE 是服务器主动推送数据,这样可以减少不必要的网络请求,提高效率。
工作原理
- 建立连接:客户端通过创建一个
EventSource
对象并指定服务器端的 SSE 端点来建立与服务器的连接。这个连接是一个持久的 HTTP 请求,通常使用长连接技术。 - 服务器发送事件:服务器端保持连接打开,并在有新数据可用时,将数据按照特定的格式封装成事件流发送给客户端。每个事件由一个或多个字段组成,常见的字段有
data
(包含实际的数据)、event
(事件类型)、id
(事件 ID)等。 - 客户端接收事件:客户端的
EventSource
对象会监听服务器发送的事件,并在接收到事件时触发相应的事件处理函数。客户端可以根据事件类型和数据内容进行相应的处理。 - 连接管理:如果连接中断,客户端会自动尝试重新连接到服务器。服务器可以通过设置
retry
字段来指定客户端在连接中断后重新连接的时间间隔。
数据格式
SSE 事件流的数据格式是纯文本,每个事件由一系列的键值对组成,键和值之间用冒号分隔,每行一个键值对,事件之间用空行分隔。以下是一个简单的 SSE 事件示例:
data: 这是一条消息
id: 123
event: message
retry: 5000
data: 另一条消息
id: 124
event: message
- data:必需字段,包含实际的数据内容。如果数据较长,可以分成多行,每行以
data:
开头。 - id:可选字段,用于唯一标识事件。客户端可以使用这个 ID 来确保事件的顺序和处理重复事件。
- event:可选字段,指定事件的类型。客户端可以根据事件类型来触发不同的事件处理函数。
- retry:可选字段,指定客户端在连接中断后重新连接的时间间隔(以毫秒为单位)。
与 WebSocket 的比较
特性 | Server-Sent Events(SSE) | WebSocket |
---|---|---|
通信方向 | 单向,服务器向客户端发送数据 | 双向,服务器和客户端可以相互发送数据 |
协议 | 基于 HTTP 协议 | 基于独立的 WebSocket 协议 |
数据格式 | 纯文本,简单易读 | 可以是文本或二进制数据 |
连接管理 | 自动重连 | 需要手动实现重连机制 |
适用场景 | 适用于服务器向客户端推送实时更新,如新闻、股票行情等 | 适用于需要实时双向通信的场景,如聊天应用、多人游戏等 |
浏览器兼容性
大多数现代浏览器都支持 SSE,包括 Chrome、Firefox、Safari、Edge 等。可以通过检查 window.EventSource
是否存在来判断浏览器是否支持 SSE
应用场景
- 实时新闻和通知:新闻网站可以使用 SSE 向用户推送最新的新闻文章、突发新闻通知等。
- 股票行情和金融数据:金融网站可以实时更新股票价格、汇率等金融数据。
- 在线聊天和社交网络:可以实现实时消息推送,让用户及时收到新消息通知。
- 监控和报警系统:服务器可以实时向客户端推送系统监控数据和报警信息。
服务器端实现示例
以下是使用 Python Flask 框架实现 SSE 的示例代码:
from flask import Flask, Response
import time
import random
app = Flask(__name__)
def generate_sse_events():
while True:
data = f"数据更新: {random.randint(1, 100)}"
yield f"data: {data}\n\n"
time.sleep(1)
@app.route('/sse')
def sse():
headers = {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
return Response(generate_sse_events(), headers=headers)
if __name__ == '__main__':
app.run(debug=True)
客户端实现示例
以下是一个简单的 HTML 页面,用于接收 SSE 事件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSE 示例</title>
</head>
<body>
<div id="output"></div>
<script>
const eventSource = new EventSource('/sse');
eventSource.onmessage = function (event) {
const output = document.getElementById('output');
const newMessage = document.createElement('p');
newMessage.textContent = event.data;
output.appendChild(newMessage);
};
eventSource.onerror = function (error) {
console.error('SSE 连接出错:', error);
};
</script>
</body>
</html>