Skip to content

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 优化 = 前端 / 网关极简转发 + 模型轻量化 + 加速 + 缓存 + 推理服务热部署 + 弹性调度 + 网络低延迟传输 + 全链路监控

By Modify.