大模型首字加速:用 Node.js 原生 SSE 做流式网关

📅 2026/6/27 2:18:43
大模型首字加速:用 Node.js 原生 SSE 做流式网关
大模型首字加速用 Node.js 原生 SSE 做流式网关在 AI SaaS 产品里首字延迟直接决定用户去留。大模型推理慢如果让用户盯着白屏等十几秒流失率会非常高。用 SSEServer-Sent Events做流式传输能把首字响应压缩到 100 毫秒内这是提升体验最直接的手段。为什么需要流式中转大语言模型是自回归生成的一个字一个字往外吐。生成 500 字摘要可能需要 10 秒以上。如果接口是一次性返回 JSON前端只能一直转 Loading用户会觉得系统卡死了。直接把前端连到云端大模型 API 也不行这样绕过了我们的认证、计费和配额控制。所以需要在网关层做一个 SSE 中转代理既要拦截请求做鉴权又要实时把大模型的数据流透传给前端。网关实现逻辑利用 HTTP 1.1 的长连接特性网关接收大模型的 Stream 数据实时中继给前端。流程大概是这样的客户端通过EventSource建立连接。网关校验身份和余额。设置Content-Type: text/event-stream和Cache-Control: no-cache。网关向大模型 API 发起流式请求。监听大模型返回的data事件解析 Token 数据包。格式化为标准 SSE 格式data: JSON_STRING\n\n写入客户端响应。检测到结束标记或连接断开计算 Token 消耗并扣费关闭连接。这样首屏等待时间能从 10 秒以上降到 100 毫秒级。Node.js 原生实现下面是一个用 Node.js 原生http模块实现的 SSE 网关。不依赖第三方中间件直接处理 Stream 数据并在连接断开时自动回收资源。// sse_stream_gateway.js const http require(http); const https require(https); const url require(url); const LLM_API_URL https://api.openai.com/v1/chat/completions; const API_KEY process.env.API_KEY || sk-mock-key; function logging(msg) { console.log([SSE Gateway] ${msg}); } const server http.createServer((req, res) { const parsedUrl url.parse(req.url, true); if (parsedUrl.pathname /v1/stream req.method POST) { logging(Incoming stream request. Setting up SSE connection...); // 1. 设置 SSE 协议头部 res.writeHead(200, { Content-Type: text/event-stream, Cache-Control: no-cache, Connection: keep-alive, Access-Control-Allow-Origin: *, X-Accel-Buffering: no // 禁用 Nginx 缓存防止数据积压 }); // 2. 准备向下游大模型发起请求 const payload JSON.stringify({ model: gpt-3.5-turbo, messages: [{ role: user, content: Generate a long story. }], stream: true }); const options { hostname: api.openai.com, port: 443, path: /v1/chat/completions, method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${API_KEY}, Content-Length: Buffer.byteLength(payload) } }; // 3. 发起上游请求 const llmReq https.request(options, (llmRes) { // 4. 监听上游数据并实时转发 llmRes.on(data, (chunk) { res.write(chunk); }); llmRes.on(end, () { logging(LLM stream completed. Closing client connection.); res.end(); }); }); llmReq.on(error, (err) { logging(LLM upstream connection error: ${err.message}); res.write(data: ${JSON.stringify({ error: Upstream connection error })}\n\n); res.end(); }); // 5. 客户端断开时销毁上游请求避免浪费算力 req.on(close, () { logging(Client disconnected prematurely. Destroying upstream request.); llmReq.destroy(); }); llmReq.write(payload); llmReq.end(); } else { res.writeHead(404, { Content-Type: application/json }); res.end(JSON.stringify({ error: Not Found })); } }); const PORT process.env.PORT || 9096; server.listen(PORT, () { logging(SSE Streaming Gateway is active on http://127.0.0.1:${PORT}); });生产环境要注意的几个点做流式传输时有几个运维层面的问题需要提前考虑Nginx 缓存问题如果网关前面有 Nginx默认会开启代理缓冲区攒够 4KB 才发一次这会让流式效果大打折扣。需要在 Nginx 配置里加X-Accel-Buffering: no。连接数耗尽SSE 依赖长连接高并发下会占用大量文件句柄。要调大ulimit并考虑心跳包机制保持连接稳定。计费对账流式传输是先出结果再算 Token存在透支风险。比较稳妥的做法是请求前预扣保证金结束后按实际用量多退少补。小结首字加速对 AI 应用体验影响很大。在网关层加一个 SSE 流式中转配合连接断开时的资源回收不用大改架构就能把首字响应降到 100 毫秒内。这对提升用户留存和付费转化都有直接帮助。