深入解析 .NET 10 中的 Server-Sent Events (SSE) 及其实践应用

什么是 Server-Sent Events (SSE)?

Server-Sent Events (SSE) 是一种“服务器向客户端单向推送”技术:客户端通过 HTTP 建立连接后,服务器可持续地向客户端发送一系列事件,而客户端保持接收状态。浏览器端通过 EventSource API 订阅这一通道。相比双向通信的 WebSockets,SSE 更加轻量、协议更简单,适用于“服务器→客户端”流式更新场景。

.NET 10 中为何引入对 SSE 的原生支持?

在 ASP.NET Core 中,虽然此前开发者也能通过自定义 text/event-stream 实现 SSE,但缺少框架级封装。

在 .NET 10 中,微软正式将 SSE 作为 API 支持的一部分,使得在 Minimal API 或传统 Controller 中使用 SSE 变得更加直接和规范。具体来说,你可以通过 TypedResults.ServerSentEvents(...) 直接返回一个 IAsyncEnumerable<T> 流,框架自动处理 text/event-stream 头、事件类型标记等细节。

SSE 与 WebSockets/SignalR 的对比

  • 双向 vs 单向:WebSockets 和 SignalR 支持双向通信(客户端可向服务器发送消息),而 SSE 是单向(服务器推 → 客户端接收)。
  • 协议与开销:WebSockets 是专用协议,连接管理、状态维护复杂;SSE 基于 HTTP,更易于穿透防火墙、部署与监控。
  • 适用场景区别:如果你只是需要“服务器不断推送数据(如股票行情、监控数据、日志流)”给客户端,而客户端无需发送数据,则 SSE 是更轻的方案。若需要复杂交互(如聊天、实时协作),WebSockets/SignalR 更适合。
  • 客户端兼容性:大多数现代浏览器支持 EventSource。
  • 多实例扩展:若服务为多实例部署且要广播大量客户端,WebSockets/SignalR 通常配合消息总线(如 Redis pub/sub)更成熟,而 SSE 虽可用,但要注意连接规模与广播策略。

在 .NET 10 中使用 SSE 的步骤

下面演示在 ASP.NET Core Minimal API 中如何使用 SSE:

1. 在 Program.cs 中配置服务与 Minimal API。

2. 创建一个产生持续数据流的 IAsyncEnumerable<T> 方法。

3. 在 app.MapGet(...) 中返回 TypedResults.ServerSentEvents(...),传入流 + 事件类型。

4. 前端通过 EventSource 订阅该 API,对特定事件类型使用 addEventListener 处理。

后台 C# 示例:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<WeatherUpdateService>();
builder.Services.AddHostedService<WeatherUpdateBackground>();

var app = builder.Build();
app.MapGet("/weather-events", (WeatherUpdateService svc, CancellationToken ct) =>
    TypedResults.ServerSentEvents(
        svc.GetUpdates(ct),
        eventType: "weatherUpdate")
);
app.Run();

在此,GetUpdates(ct) 返回 async IAsyncEnumerable<WeatherInfo>,每当新数据可用时通过 yield return 发送。客户端将接收带有类型 "weatherUpdate" 的事件。

前端 JavaScript 示例:

const es = new EventSource("/weather-events");
es.addEventListener("weatherUpdate", evt => {
  const data = JSON.parse(evt.data);
  console.log("新天气:", data);
});
es.onerror = err => {
  console.error("SSE 连接错误:", err);
  es.close();
};

实战场景与注意事项

  • 实战场景:监控仪表盘(实时指标)、体育比分、版本发布通知、日志/告警流、股票/加密货币行情。

  • 连接管理:确保处理好客户端关闭、服务器止步、取消令牌(CancellationToken)等。若多客户端订阅相同源,应考虑内部广播机制。

  • 规模限制:HTTP/1.1 下每浏览器对同一域名的并发连接数有限(约 6 个),若大量客户端用 SSE,推荐使用 HTTP/2 或反向代理调优。

  • 跨域 & 缓存:返回的 MIME 类型必须为 text/event-stream,应设置 Cache-Control: no-cache。若跨域,需允许 CORS 和 withCredentials 选项。

  • 重连与心跳:客户端若断开,浏览器会尝试自动重连。服务器可周期性发送注释行(如 : keepalive\n\n)防止超时。

  • 广播模式:若服务多实例,建议结合如 Redis、NATS 之类总线,将更新广播到所有实例,再由每实例推送给其连接客户端。

总结

.NET 10 引入对 SSE 的原生支持,为需要“服务器向客户端实时推送”的场景提供了简洁、高效的解决方案。借助 ASP.NET Core Minimal API 和 TypedResults.ServerSentEvents,开发者可以很快上手实现实时数据通道。适当评估场景、注意连接规模及广播结构,就能在现代 Web 应用中优雅地运用 SSE。

评论