当前位置: 首页 > news >正文

简单学习 --> SSE

我们使用AI时,AI对我们说的话不会一次性把全部内容弹出来,而是会像流水一样,一点点吐出来,那么这种丝滑的交互体验,背后的核心就是SSE (Server-Sent Events)

什么是 SSE?

SSE(Server-Sent Events,服务器发送事件)是一种基于 HTTP 协议的通信技术,它允许服务器在有新数据时,主动且持续地将数据“推”送到客户端(通常是浏览器)。

简单来说,SSE 是实现“流式输出”的一种标准协议。如果把“流式输出”比作信息传递的模式,SSE 就是实现这一模式的具体通信方案。

SSE 的前世今生

SSE 最初由 HTML5 标准的主要编辑者伊恩·希克森(Ian Hickson)定义。它的出现,是为了解决传统 Web 通信在实时性上的痛点。

SSE 的历史可以追溯到 2004 年左右,它的发展经历了以下几个阶段:

  • Opera 软件公司提出原型:最早由 Opera 浏览器公司在 2004 年提出,当时名为“Server-Sent DOM Events”。其初衷是希望浏览器能有一种比“轮询(Polling)”更高效的方式来获取服务器数据。

  • 纳入 HTML5 草案:随后,这项技术被纳入了正在制修订的HTML5 标准之中。

  • W3C 与 WHATWG 标准化

    • WHATWG(网页超文本应用技术工作小组)负责 HTML 生活标准(Living Standard)的维护。

    • W3C(万维网联盟)曾将其作为独立的 API 规范进行管理。

为什么在 SSE 出现之前很痛苦?

在 SSE 之前,网页要获取服务器的实时更新,只能依靠:

  • 轮询 (Polling):浏览器每隔几秒问一次服务器“有新消息吗?”,这极大地浪费带宽和 CPU。

  • 长轮询 (Long Polling):服务器挂起请求,直到有数据才返回。虽然效率略高,但每次连接仍需重新握手,开销巨大。

SSE 的诞生正是为了提供一种轻量、高效、基于 HTTP 的单向实时通信方案,完美规避了轮询的弊端。

SSE 的核心工作原理

SSE 建立的是一个单向的通信通道。其流程如下:

  1. 客户端发起请求:浏览器发送一个普通的 HTTP 请求,并在 Header 中设置Accept: text/event-stream

  2. 服务器保持连接:服务器不立即关闭请求,而是将响应头Content-Type设置为text/event-stream,并保持该 HTTP 连接。

  3. 持续推送:一旦有新数据(例如 AI 生成的新 Token),服务器便按照 SSE 规定的格式源源不断地发送数据块。

SSE 的数据格式(规范)

为了保证传输的稳定性,SSE 要求传输的数据必须是纯文本,且遵循特定的行格式:

  • data:开头:后接实际内容。

  • \n\n结尾:两个换行符表示一条消息的结束。

  • 可选字段:支持id:(用于断线重连)或event:(定义自定义事件)。

标准示例:

data: {"content": "你"}

data: {"content": "好"}

data: [DONE]

SSE 和 WebSocket

SSE 和 WebSocket的区别

维度SSEWebSocket
通信方向单向(服务器 -> 客户端)双向(全双工)
协议基础HTTPHTTP 升级协议
开发难度低(浏览器原生支持)高(需要复杂握手/管理)
防火墙友好非常好(HTTP 长连接)有时会被代理拦截

为什么 AI 聊天都选 SSE?核心原因在于“简单即是力量”。AI 对话通常是客户端发问,服务器流式返回,SSE 这种轻量化的 HTTP 协议完全满足需求,无需额外的复杂配置,且在防火墙穿透性上更有优势。

SSE 就像是专门用来发送流水线货物的“传送带”。当我们需要将一份完整的数据像挤牙膏一样一点点运送给用户时,SSE 是目前最标准、最易用的选择。

使用 FastAPI 实现 SSE

from fastapi import FastAPI from fastapi.responses import StreamingResponse import asyncio app = FastAPI() async def event_generator(): words = ["天", "气", "真", "好", "呀"] for word in words: # 必须严格遵守 data: 内容 \n\n 的格式 yield f"data: {word}\n\n" await asyncio.sleep(0.5) # 模拟 AI 生成的延迟 yield "data: [DONE]\n\n" @app.get("/stream") async def stream(): return StreamingResponse(event_generator(), media_type="text/event-stream")
http://www.zskr.cn/news/1383756.html

相关文章:

  • CANN生产环境最佳实践——从实验室到量产的避坑指南(完整版)
  • 深入Linux内核:软件如何“冒充”硬件?揭秘fixed-link背后的虚拟MDIO总线设计
  • 告别书签混乱:3个步骤让你的浏览器收藏夹重获新生
  • Ubuntu 22.04 LTS下,腾达U9 USB网卡驱动安装保姆级教程(解决内核6.5+编译问题)
  • Java NIO.2 异步调度中枢:AsynchronousChannelGroup 源码深度剖析与线程池契约
  • Unity Timeline信号(Signal)系统实战:告别硬编码,实现灵活的事件驱动交互
  • 别再刷高并发概念了,这 5 个“复杂级”全栈垂直平台带你死磕底层业务
  • 如何快速突破原神60帧限制:面向PC玩家的完整帧率解锁指南
  • VideoDownloadHelper终极指南:三步掌握全网视频下载的完整教程
  • 网盘限速终结者:LinkSwift直链下载助手终极指南
  • 2026年杭州电商公司实力大比拼:哪家更值得信赖?
  • 告别旧版PlayerInput!UE5.1.1 EnhancedInput保姆级配置流程(从Action创建到C++绑定)
  • 律所案件管理系统选型:主流工具的功能、价格与适用场景对比
  • Unity Timeline信号(Signal)轨道实战:告别硬编码,实现灵活的事件驱动交互
  • 【华为OD机试真题 新系统】993、小学英语老师批改作文 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)
  • PentestGPT:Kali本地部署的AI渗透测试协作者
  • Adobe-GenP 3.0:轻松激活Adobe全家桶的完整指南
  • InVideo插件深度解析:如何在Unreal Engine中实现高效视频流播放与录制
  • Amphenol ICC DRPC21A005540线束解析
  • UE5.2 PCG实战:像搭积木一样组合关卡!用PCGSettings实现模块化场景设计与高效复用
  • 基于NodeMCU与RC522的物联网门禁系统:从硬件连接到云端管理
  • 从Disney到Filament:手把手教你将Substance Painter导出的贴图正确导入游戏引擎
  • 别再傻傻分不清!UE5材质里ActorPosition和ObjectPosition到底用哪个?附实战避坑指南
  • Unity/Unreal开发者必看:用手机和陀螺仪实验,5分钟搞懂万向节死锁(附避坑指南)
  • 告别手写公式烦恼:用Snipaste+SimpleTex.cn,5分钟搞定截图转LaTeX(保姆级教程)
  • 别再手动测模型了!用Simulink Test Manager实现自动化测试(附Excel表格配置详解)
  • Unity项目DrawCall降不下来?试试用Mesh Baker合并贴图集,保姆级图文教程
  • Unity Addressable + CCD 实战:手把手教你配置云端资源分发,告别本地打包烦恼
  • QMCDecode:3步解锁QQ音乐加密文件,让你的音乐重获自由 [特殊字符]
  • 从零开始:免费开源Cherry MX键帽3D模型打造个性化机械键盘终极指南