Wiki-Framework 1.2.0 的 wiki-sse:用普通 HTTP 做后台实时推送

2026-07-01 39 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

后台系统里最容易被低估的功能,往往是“通知”。审批流走到哪一步、任务是否完成、用户是否在线、导入是否失败——这些信息如果只能靠刷新页面拿到,体验会很笨重。Wiki-Framework 1.2.0 新增的 wiki-sse 模块,把 Server-Sent Events 作为框架内置能力补上,让服务端单向推送不必一上来就引入 WebSocket。

为什么是 SSE,而不是继续轮询

轮询当然能做:前端每 3 秒请求一次 /notifications,后端查库再返回。但它的问题也很明显:

  • 没有消息时也在请求,浪费连接和服务端资源。
  • 轮询间隔短,压力大;间隔长,实时性差。
  • 每个业务都自己写一套定时器、取消逻辑和错误重试,前端代码容易散。

WebSocket 的能力更完整,适合双向通信、聊天室、协同编辑、实时游戏这类场景。但很多后台需求其实只需要“服务端告诉浏览器发生了什么”。这时 SSE 刚好卡在中间:

  • 基于普通 HTTP,部署和排查成本更低。
  • 浏览器原生支持 EventSource
  • 连接断开后浏览器可以自动重连。
  • 适合通知、进度、状态变更等服务端单向推送。

wiki-sse 的价值就在这里:把这类轻量实时能力纳入 Wiki-Framework,而不是让每个项目重复造一遍。

wiki-sse 适合放在哪些业务里

可以把 SSE 理解成“页面打开后一条持续不断的 HTTP 响应”。服务端不一次性结束响应,而是在有事件时写入类似这样的数据:

event: approval-progress
data: {"id":"A-1001","status":"approved"}

这类模型特别适合后台系统中的几类需求:

  • 审批进度:流程节点变化后推送给当前申请人或管理员。
  • 站内通知:新任务、新评论、异常告警即时出现在页面角标。
  • 导入/导出进度:长任务不需要前端一直查进度接口。
  • 在线状态:用户登录、离线、心跳状态变化由服务端广播。

边界也要说清楚:SSE 是单向推送。客户端要发消息,仍然走普通 HTTP API;如果你需要客户端和服务端高频双向通信,WebSocket 仍然更合适。

可以这样实践:前端用 EventSource 接收通知

下面是一个可直接改造到后台页面里的前端示例。假设后端提供了 /api/sse/notifications 端点,并按 SSE 协议返回事件流。

<!doctype html>
<html lang="zh-CN">
  <body>
    <h1>实时通知</h1>
    <ul id="messages"></ul>

    <script>
      const list = document.querySelector('#messages');
      const source = new EventSource('/api/sse/notifications');

      source.addEventListener('open', () => {
        console.log('SSE connected');
      });

      source.addEventListener('notification', (event) => {
        const payload = JSON.parse(event.data);
        const item = document.createElement('li');
        item.textContent = `${payload.time} - ${payload.message}`;
        list.prepend(item);
      });

      source.addEventListener('error', () => {
        console.warn('SSE disconnected, browser will retry automatically');
      });

      window.addEventListener('beforeunload', () => {
        source.close();
      });
    </script>
  </body>
</html>

要改的地方很少:

  • /api/sse/notifications 换成你的 wiki-sse 服务端地址。
  • 把事件名 notification 换成后端实际发送的事件名。
  • 按业务结构解析 event.data

服务端事件长什么样

即使框架封装了发送细节,理解 SSE 的线格式仍然有帮助。一个最小响应通常长这样:

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

event: notification
data: {"message":"审批单 A-1001 已通过","time":"2025-01-18 10:30:00"}

关键点是:

  • Content-Type 必须是 text/event-stream
  • 每条消息用空行分隔。
  • event 是事件名,前端用 addEventListener 监听。
  • data 是字符串,通常放 JSON。

如果项目经过 Nginx 代理,还要注意关闭缓冲,否则服务端已经推了,浏览器却迟迟收不到。可以这样配置一个 SSE 路径:

location /api/sse/ {
    proxy_pass http://wiki_backend;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    proxy_cache off;
    proxy_read_timeout 1h;
}

这段配置可以按你的网关域名、后端 upstream 名称修改后使用。

落地时别忽略这些细节

引入 wiki-sse 时,建议把它当成基础设施能力,而不是随手塞进某个业务接口:

  • 连接管理:用户关闭页面、切换账号、Token 过期时,要及时释放服务端连接。
  • 权限隔离:通知只能推给有权限的人,不能因为广播方便就跨租户、跨部门泄露数据。
  • 心跳机制:长连接经过代理、负载均衡时可能被断开,定期发送心跳能减少“假在线”。
  • 重连补偿:SSE 会自动重连,但断线期间的关键事件最好能通过通知列表或进度查询接口补回来。
  • 容量评估:每个打开页面都是一条连接,管理员大屏、运营后台、移动端同时在线时要估算连接数。

采用建议

如果你的 Wiki-Framework 项目已经有通知、审批进度、在线状态这类需求,wiki-sse 很适合优先接入。它比轮询更省,比 WebSocket 更轻,和后台系统的“服务端单向提醒”模型也更贴合。

一个稳妥的改造路径是:先把通知中心或任务进度这种低风险场景接入 SSE;保留原来的查询接口作为断线补偿;确认代理、鉴权和连接释放都稳定后,再扩展到更多实时模块。


相关推荐