如何从其他独立中间件发送SSE,实现订单场景实时消息推送
实时订单推送实现方案
方案1:原生SSE实现(无需额外依赖)
核心逻辑是单独维护SSE客户端连接池,跨模块调用广播方法触发推送,完美适配你订单逻辑和SSE接口拆分在不同文件的场景。
- 首先新建独立的SSE连接管理模块
sse-manager.js,全局共用:
// sse-manager.js const sseClients = new Set(); // 新增客户端连接 function addClient(res) { sseClients.add(res); // 客户端断开连接时自动移除,避免内存泄漏 res.on('close', () => { sseClients.delete(res); }); } // 向所有连接的客户端广播消息 function broadcast(message) { const sseData = `data: ${JSON.stringify(message)}\n\n`; for (const client of sseClients) { client.write(sseData); } } module.exports = { addClient, broadcast };
- 改造SSE接口:
const { addClient } = require('./sse-manager'); app.get('/sse', (req, res) => { res.set({ 'Cache-Control': 'no-cache', 'Content-Type': 'text/event-stream', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '*' // 按需配置跨域 }); res.flushHeaders(); // 配置客户端断线重试间隔 res.write('retry: 10000\n\n'); // 将当前连接加入管理池 addClient(res); });
- 订单接口中调用推送:
不管你的/add-order逻辑在哪个文件,只要引入sse-manager的广播方法即可触发推送,不会影响/add-order接口本身的响应:
const { broadcast } = require('./sse-manager'); app.post('/add-order', async (req, res) => { // 原有订单校验、写入数据库逻辑 const newOrder = await createOrder(req.body); // 订单写入完成后广播新订单消息 broadcast({ event: 'new_order', data: newOrder }); // 正常响应/add-order请求 res.json({ code: 0, msg: '下单成功', data: newOrder }); });
方案2:使用npm包简化实现
如果不想自己维护连接管理逻辑,可以直接用成熟的express-sse包:
- 安装依赖:
npm install express-sse - 代码示例:
const SSE = require('express-sse'); // 全局初始化SSE实例 const sse = new SSE(); // SSE接口 app.get('/sse', sse.init); // 订单接口推送 app.post('/add-order', async (req, res) => { const newOrder = await createOrder(req.body); sse.send(newOrder, 'new_order'); res.json({ code: 0, msg: '下单成功' }); });
方案3:不使用SSE的替代实现
- WebSocket方案:如果后续需要双向通信能力,推荐使用
socket.io或ws包,自带广播、重连、断线重试等成熟能力,适合更复杂的实时交互场景。 - 前端轮询方案:如果业务并发量低、实时性要求在秒级以上,可以直接让前端每隔2-5秒请求一次最新订单列表,实现成本最低,无需处理长连接相关的异常问题。
补充注意事项
如果你的服务是多实例集群部署,以上单进程内存存储连接池的方案会出现推送不全的问题,需要搭配Redis发布订阅能力实现跨实例广播:每个服务实例订阅Redis的new_order频道,/add-order接口写入订单后向Redis频道发消息,每个实例收到消息后再向自己管理的SSE客户端推送即可。
内容的提问来源于stack exchange,提问作者Matus86309
相关产品推荐
相关产品推荐

