Topcoat Server-Sent Events 指南:流式响应与断点续传

Topcoat Server-Sent Events 指南:流式响应与断点续传 Topcoat Server-Sent Events 指南流式响应与断点续传【免费下载链接】topcoatA batteries-included framework for building web apps项目地址: https://gitcode.com/GitHub_Trending/top/topcoatTopcoat 是一款开箱即用batteries-included的 Rust Web 应用框架它的 Server-Sent EventsSSE支持让你用几行代码就能实现流式响应与断点续传服务器把事件流式地推送到浏览器连接断开后还能从断点处继续而不是从头重放。本指南带你从零理解 SSE 的原理并学会在 Topcoat 路由中构建自己的事件流。什么是 Server-Sent EventsSSE 是一种基于普通 HTTP 的单向推送机制服务端通过一个长连接持续向浏览器推送事件浏览器内置的EventSource负责订阅断线时自动重连无需自己写心跳轮询相比 WebSocketSSE 更简单——不需要升级协议、不需要双向通信天然兼容代理与负载均衡。它非常适合实时日志、任务进度条、消息通知、股票报价等服务端不断往外发的场景。开启 Topcoat 的 SSE 功能SSE 模块位于 Topcoat 路由组件topcoat-router中response.rs、event.rs、keep_alive.rs通过sse特性开关启用。在Cargo.toml中为topcoat加上该特性即可可参考官方示例topcoat { workspace true, features [sse] }完整的可运行示例在 examples/sse/ 目录下Cargo.toml 展示了特性配置方式。三步构建流式响应让一个路由变成事件流只需要返回一个包裹了事件流的Sse响应写事件流用futures_util::stream构造任意事件发生器比如每隔 1 秒发一条 tick#[route(GET /ticks)] async fn ticks() - ResultSseimpl StreamItem ResultEvent use { let events stream::unfold(0u64, |tick| async move { tokio::time::sleep(Duration::from_secs(1)).await; let event Event::new() .event(tick) .id(tick.to_string()) .data(tick.to_string()); Some((Ok(event), tick 1)) }); Ok(Sse::new(events)) }逐字段组装事件每个Event由字段拼成event.rs 中定义了完整的构建器构建器作用.data(...)事件负载文本.json_data(...)把任意可序列化结构体转成 JSON 作为负载.event(...)事件类型名前端按名字分发监听器.id(...)事件 ID断点续传的关键.retry(...)告知客户端断线后多久重连.comment(...)注释客户端会忽略用于保活客户端订阅浏览器端只需几行 JavaScriptfeed.js 就是完整演示const ticks new EventSource(/ticks); ticks.addEventListener(tick, (event) console.log(event.data));连接成功后浏览器会持续接收tick事件流结束例如进度任务完成时客户端调用close()关闭连接即可。 小贴士路由返回类型里的use约束是为了防止流借用请求上下文——流的生命周期比处理器更长。如果流里需要读取请求上下文先cx.clone()再把所有句柄移入流中即可。断点续传Last-Event-ID 是怎么工作的这是 SSE 最强大的特性Topcoat 把它做成了开箱即用的两步第一步给事件发号。用.id(...)为每个事件设置唯一递增的编号。第二步重连时读回编号。当浏览器自动重连时它会在Last-Event-ID请求头中回传最后收到的事件 ID。用 Topcoat 提供的last_event_id(cx)读回它从断点继续#[route(GET /ticks)] async fn ticks(cx: Cx) - ResultSseimpl StreamItem ResultEvent use { let next last_event_id(cx) .and_then(|id| id.parse::u64().ok()) .map_or(0, |last| last 1); // 从 next 开始发事件而不是永远从 0 开始…… }整个流程如下服务器发出id: 42的事件网络抖动连接断开EventSource自动重连请求头带上Last-Event-ID: 42服务器读取该头从 43 号事件继续——一条都不丢也不重复。保活别让安静的连接被掐掉代理和负载均衡器通常会掐掉看起来太久没动静的连接。Topcoat 内置了KeepAlive保活机制keep_alive.rsOk(Sse::new(events).keep_alive(KeepAlive::new()))默认行为空闲 15 秒后发送一条空注释事件足以躲过大多数代理的 1 分钟空闲超时.interval(...)调整保活间隔.text(...)/.event(...)自定义保活内容的文本或事件。保活事件对客户端透明会被忽略不会影响你的业务逻辑。实战建议给每个事件设 ID这是免费获得的断点续传能力即使你的数据源数据库、消息队列本身不支持 seek也可以把已处理游标存下来JSON 负载优先用.json_data()前端JSON.parse(event.data)就能拿到结构化数据官方示例 examples/sse/src/main.rs 中的/job路由就是推送任务进度0% → 100%的完整范例结束要有明确的终止事件如发出done事件后由前端主动close()避免EventSource把流结束误判为断线而重连重放清理资源绑定到流的Drop客户端断开时流会被丢弃把数据库连接释放、任务取消等收尾逻辑挂在那里放心部署Topcoat 的路由器不会对事件流做压缩防止编码器缓冲导致事件延迟SSE 在生产链路中是直出的。核心文件速查内容路径SSE 官方文档sse.md事件构建器event.rsSse响应response.rs保活机制keep_alive.rs可运行示例examples/sse/src/main.rs前端订阅脚本examples/sse/src/feed.js从一条#[route]到带保活、可续传的实时事件流Topcoat 把 SSE 的每个环节都封装成了简单直观的 API——加上sse特性你的第一个流式接口今天就能上线 【免费下载链接】topcoatA batteries-included framework for building web apps项目地址: https://gitcode.com/GitHub_Trending/top/topcoat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考