SSE (Server-Sent Events) 服务器发送事件
SSE协议本质上就是一个Http的get请求,当然也是支持Https,服务端在接到该请求后,返回状态。同时请求头设置也变为流形式。
shell
Content-Type: text/event-stream,
Cache-Control: no-cache,
Connection: keep-alive前端实现
通过 EventSource 创建一个 EventSource 对象,然后通过 onmessage 事件监听服务器发送的消息。
js
const sse = () => {
const eventSource = new EventSource('http://localhost:9000/service-uni-app/sse');
eventSource.onmessage = function (event) {
console.log(event.data);
sseRes.value = event.data;
};
};后端接口实现
通过持续发送消息给客户端
shell
/**
* 模拟SSE serve send event
* */
@GetMapping(value = "/sse")
public String sse(HttpServletResponse response) {
response.setContentType("text/event-stream");
response.setCharacterEncoding("utf-8");
String s = "";
while (true) {
s = "data: " + new Date() + "\n\n";
try {
PrintWriter pw = response.getWriter();
Thread.sleep(1000);
pw.write(s);
pw.flush();
} catch (Exception e) {
}
}
}Question
为什么AI流式输出场景更适合SSE?
- 单向推送:AI 只需要服务 --> 客户端输出,不用客户端频繁发请求
- 长连接保活:一次连接持续推流,不用反复握手,延迟更低
- 纯文本流:直接逐字 / 逐句发 chunk,和大模型逐 token 输出完美匹配
- 轻量简单:比 WebSocket 更轻,不用自定义协议,后端实现成本低
- 原生支持:浏览器自带 EventSource,断线自动重连,省心
为什么不用websocket?
- 场景不匹配:AI 流式只需服务端→客户端单向推,WebSocket 双向通信冗余
- 协议更重:需自定义消息格式、心跳、分包,开发与维护成本高
- 连接更贵:长连接占用资源更多,网关 / 代理配置更复杂
- 原生优势:SSE 自带断线重连,浏览器 EventSource 开箱即用
- 安全更简:同域下直接走 HTTP,无需额外处理跨域与鉴权
如果SSE断开了,前端一般如何处理
- 优先用 EventSource 原生自动重连,低成本兜底;
- 复杂场景手动实现指数退避重连,控制重试次数和间隔;
- 重连时做好用户提示 + 内容缓存,保证体验和数据完整性
SSE要发送请求头,有什么方法
- 核心方案:用 fetch + ReadableStream 替代原生 EventSource,可自定义任意请求头(Token、Cookie、自定义业务头),是生产环境首选
- 兜底方案:原生 EventSource 仅能控制 withCredentials(Cookie),无法自定义鉴权头等核心头,仅适用于无自定义头的简单场景
针对AI应用 TTFB(首字节响应时间) 指标有什么优化方案
核心是减少从用户请求到模型开始输出第一个 token 的全链路等待,覆盖请求链路、模型推理、服务架构、网络传输四大环节
AI 应用 TTFB 优化 = 前端 / 网关极简转发 + 模型轻量化 + 加速 + 缓存 + 推理服务热部署 + 弹性调度 + 网络低延迟传输 + 全链路监控
