流式通信基础与应用场景

理解流式通信的核心概念、技术选型考虑,掌握 SSE 等流式通信协议的特点和适用场景

发布于:
更新于:
阅读时间:

2.1.1 流式通信基础与应用场景

学习目标: 理解流式通信的核心概念、技术选型考虑,掌握 SSE 等流式通信协议的特点和适用场景


一、引言:理解两种通信范式

对于熟悉传统 Web 开发的工程师来说,我们日常使用的 RESTful API 调用都遵循着一种"请求-等待-返回"的通信模式。这种模式被称为非流式通信(Non-Streaming Communication):

1
2
3
非流式通信 (Request-Response)
客户端 ──请求──→ 服务器
客户端 ←──完整响应──── 服务器 (连接关闭)

然而,在基于大模型技术开发的应用中,我们面临着全新的挑战:

  • 响应时间长:大模型推理可能耗时数十秒甚至数分钟
  • 需要实时反馈:用户希望看到 AI 的"思考过程"
  • 中间结果有价值:Agent 需要持续输出执行步骤和中间结果

这时,传统的"一问一答"模式就显得力不从心了。流式通信(Streaming Communication)恰好完美契合了大模型的输出特点。它允许服务器在处理请求的同时,持续地、分段地将生成的数据实时推送给客户端——就像打开水龙头让水源源不断地流出,而不必等待水缸装满后才一次性倒出:

1
2
3
4
5
6
流式通信 (Streaming)
客户端 ──请求──→ 服务器
客户端 ←──数据流1──── 服务器 (连接保持)
客户端 ←──数据流2──── 服务器 (连接保持)
客户端 ←──数据流3──── 服务器 (连接保持)
客户端 ←──数据流n──── 服务器 (完成后关闭)

1.1 两种通信范式对比

对比维度 非流式通信 流式通信
连接方式 短连接,请求后立即关闭 长连接
响应方式 一次性返回完整结果 持续推送数据片段
数据可见性 等待 → 显示完整结果 即时反馈 → 逐步显示
典型场景 RESTful API、表单提交 AI 对话、实时日志、视频流
AI 适用性 ❌ 长时间等待,体验差 ✅ 实时反馈,体验好

事实上,流式通信技术并不新鲜——聊天应用、实时协作、视频流媒体、大文件下载、实时日志推送等场景早已广泛使用。但在 AI 应用中,这项技术展现出了前所未有的重要性,成为了构建良好用户体验的关键技术基础

1.2 流式通信在 AI 应用中的核心价值

1. 实时性:即产即推,无需等待

  • 数据一产生即可传输给客户端
  • 用户立即看到 AI 处理结果
  • 支持增量更新和渐进式展示 典型场景:ChatGPT 式的"打字机"效果,让用户感受到 AI 正在思考和生成内容。

2. 用户体验:从"黑盒等待"到"透明过程"

  • 提供实时的执行状态反馈
  • 减少用户等待的焦虑感
  • 支持早期取消和中断操作 典型场景:复杂任务执行时显示"正在搜索资料…"、“正在分析数据…“等中间状态。

3. 资源效率:减少内存占用,优化带宽利用

  • 减少服务器内存占用(无需缓存完整结果)
  • 避免大量数据的积压
  • 支持背压控制(Backpressure),防止数据过载 典型场景:生成长篇文章或报告时,边生成边传输,而不是等全部生成完再返回。

4. 系统可靠性:更好的扩展性和容错能力

  • 更好地支持高并发场景
  • 降低服务器负载峰值
  • 支持负载均衡和水平扩展
  • 连接异常时可以断点续传 典型场景:多用户同时使用 AI 服务时,流式传输可以更平滑地分配资源。

二、 流式通信基础

在现代网络应用中,实现流式通信有多种传输技术方案可选:

常见的流式通信技术对比:

技术方案 连接模型 双向通信 适用场景 复杂度
TCP Socket 长连接 全双工 底层网络编程、实时游戏
WebSocket 长连接 全双工 实时聊天、协作编辑
HTTP 流式传输 半持久连接 单向(服务端 → 客户端) AI 生成、数据推送
轮询(Polling) 短连接 模拟实时 兼容性要求高的场景

为什么 AI 应用普遍选择 HTTP 流式传输? 尽管 WebSocket 和 Socket 提供了更强大的双向通信能力,但HTTP 流式传输已经成为 AI 应用开发的主流选择,主要原因包括:

  1. 单向通信足够用:AI 应用的典型交互模式是"请求-响应”,客户端发送问题,服务端流式返回答案,不需要频繁的双向实时通信
  2. 生态系统成熟
    • 所有主流 AI 服务商(OpenAI、Anthropic、Google 等)都采用 HTTP 流式 API
    • 丰富的客户端库和工具链支持
    • 前端框架(React、Vue 等)有成熟的 HTTP 流处理方案
  3. 基础设施友好
    • 无需特殊的代理或负载均衡器配置
    • CDN、防火墙、企业网关等网络设备普遍支持
    • 更容易通过现有的安全策略和监控体系
  4. 开发成本低
    • 基于标准 HTTP 协议,学习曲线平缓
    • 可以复用现有的 HTTP 中间件和认证机制
    • 调试工具丰富(浏览器开发者工具、Postman 等)
  5. 可靠性保障
    • HTTP/2 和 HTTP/3 提供了内置的多路复用和流控制
    • 断线重连机制简单明了
    • 易于实现幂等性和重试逻辑

因此,接下来我们将重点介绍 HTTP 流式传输的实现机制,这是掌握 AI 应用开发的基础技能。

2.1 HTTP 流式(HTTP Streaming)传输机制

2.1.1 第一种:HTTP/1.1 分块传输编码(Chunked Transfer Encoding)

技术定义: 分块传输编码将内容封装为一系列数据块进行传输,每个数据块都带有自己的大小指示器,后面可选地跟随包含尾部字段的 trailer 区域。分块编码使得未知大小的内容流能够以长度分隔的缓冲区序列形式传输,这样发送方可以保持连接持久性,接收方也能知道何时接收到完整消息。 实现机制: HTTP/1.1 标准(RFC 2616)中定义的机制,通过响应头 Transfer-Encoding: chunked 声明。响应体被分割为多个数据块(chunk),每个块包含:

  • 块大小:十六进制表示的字节数
  • 块数据:实际的数据内容
  • 结束标记:以 0\r\n\r\n 标记传输结束

2.1.2 第二种:HTTP/2 和 HTTP/3 数据流(Stream)

“流”(Stream)概念: HTTP/2 中的"流"是在单个 HTTP/2 连接内,客户端和服务器之间交换的 独立、双向的帧序列。流具有以下几个重要特性:

  1. 多路复用:单个 HTTP/2 连接可以包含多个并发打开的流,任一端点都可以交错发送来自多个流的帧
  2. 灵活建立:流可以由任一端点单方面建立和使用,也可以由双方共享
  3. 双向关闭:流可以由任一端点关闭
  4. 顺序保证:帧的发送顺序很重要,接收方按照接收顺序处理帧。特别是 HEADERS 帧和 DATA 帧的顺序在语义上具有重要意义
  5. 唯一标识:每个流通过整数 ID 进行标识,流标识符由发起流的端点分配

HTTP Stream 实现机制:

HTTP/2 标准(RFC 7540)采用二进制分帧层,主要包含以下关键机制:

  • 帧结构:所有通信都分解为更小的消息和帧,并采用二进制格式编码。每个帧包含:
    • 帧头(9 字节):长度、类型、标志、流 ID
    • 帧负载:实际数据内容
  • 流 ID 分配规则
    • 客户端发起的流使用奇数 ID(1, 3, 5, …)
    • 服务器发起的流使用偶数 ID(2, 4, 6, …)
    • ID 必须递增,不可重用
  • 关键帧类型
    • HEADERS:发送 HTTP 头部信息
    • DATA:传输 HTTP 消息体
    • RST_STREAM:终止流
    • SETTINGS:配置连接参数
    • PRIORITY:设置流优先级
  • HTTP 头部与 Content-Type
    • 在 HTTP/2 中,所有 HTTP 头部(包括Content-Type)都通过HEADERS帧传输
    • Content-Type用于声明响应体的媒体类型格式,对于流式通信场景尤为重要:
      • 分块传输编码:Content-Type: application/json 或其他应用数据类型
      • SSE 事件流:Content-Type: text/event-stream(下文将详细介绍)
      • 普通文本流:Content-Type: text/plain
    • HTTP/2 使用 HPACK 算法对头部进行压缩,减少传输开销,这使得频繁发送包含Content-Type的头部信息更加高效
  • 流状态机:流在生命周期中经历多个状态(idle → open → half-closed → closed),确保数据传输的有序性和可靠性 HTTP/3 Stream 与 HTTP/2 Stream 几乎完全相同。它们的主要区别在于基于 QUIC 或 TCP 之上的功能的技术实现。在此不再赘述,感兴趣的读者可以查阅相关资料。

三、 从传输协议到文本协议:理解协议栈的分层价值

在理解了 HTTP1.1 分块传输编码和 HTTP/2 的多路复用和流式传输的底层机制之后,我们需要认识到:虽然他们提供了强大的传输能力,但直接使用这些底层传输协议对开发者来说并不友好。这就引出了文本协议的价值——它们在 HTTP1.1、 HTTP/2、HTTP/3 等传输协议之上,提供了更加简洁、标准化的接口和语义,让开发者无需关心底层的帧控制、流量管理等复杂细节。

接下来我们将介绍一种建立在 HTTP 协议之上的应用层流式文本协议。这种协议充分利用了 HTTP 的流式传输能力,同时为特定场景提供了更高层次的抽象和更易用的编程接口。它们与底层 HTTP 协议的关系就像应用程序与操作系统的关系——底层提供能力,上层提供便利性和专业化。

四、 Server-Sent Events (SSE) 文本协议

技术定义:

Server-Sent Events(SSE)是 HTML5 标准定义的一种服务器向客户端单向推送实时数据的文本协议。它基于 HTTP 流式传输机制,允许服务器持续向客户端推送文本格式的事件流,一般客户端通过浏览器原生的 EventSource API 接收和处理这些事件。SSE 特别适合服务器需要主动推送数据、而客户端无需频繁响应的场景。

核心特点:

  • 单向通信:数据只能从服务器流向客户端,客户端不能通过 SSE 连接向服务器发送数据(需要通过其他 HTTP 请求实现双向交互)
  • 事件驱动:服务器可以发送包含不同类型事件的数据,客户端可以针对不同事件类型注册监听器并做出相应处理
  • 基于 HTTP 协议:使用标准的 HTTP 协议,易于实现、调试和部署,支持 HTTP/1.1、HTTP/2、HTTP/3
  • 低资源消耗:与 WebSocket 相比,SSE 的连接建立和维护消耗更少的资源,更适合单向数据推送场景
  • 自动重连机制
    • 连接断开后,浏览器自动重连(默认间隔 3 秒)
    • 重连时自动发送 Last-Event-ID 头,服务器可据此恢复数据推送进度
    • 服务器可通过 retry 字段自定义重连间隔时间

SSE 实现机制: SSE 标准定义了一套简单的文本协议格式和浏览器 API:

  • HTTP 响应头设置

    • Content-Type: text/event-stream:声明这是一个事件流
    • Cache-Control: no-cache:禁止缓存响应内容
    • Connection: keep-alive:保持长连接状态
  • 事件数据格式(纯文本,UTF-8 编码):

    1
    2
    3
    4
    5
    6
    
    event: eventName     # 可选:事件类型名称
    data: message        # 必需:事件数据内容(可多行)
    id: 1               # 可选:事件ID,用于断线重连时恢复
    retry: 10000        # 可选:重连间隔时间(毫秒)
    
    (空行表示一个完整事件结束)
    
  • 连接管理

    • 客户端可通过 eventSource.close() 主动关闭连接
    • 服务器端关闭连接时,客户端会自动尝试重连

跨语言支持: 虽然 SSE 在 HTML5 规范中被标准化并提供了浏览器原生的 EventSource API,但它本质上是基于 HTTP 的文本协议,因此:

  • 任何支持 HTTP 的客户端都可以实现 SSE 接收
  • 不依赖于浏览器环境,可在服务端到服务端的通信中使用

4.1 SSE 的两种使用模式

4.1.1 模式一:直接发起 SSE 的 GET 请求(无参数或 URL 参数)

适用于订阅公共数据流或参数简单的场景。使用浏览器原生 EventSource API:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 无参数订阅
const eventSource = new EventSource('/api/notifications');

// URL参数订阅
const eventSource = new EventSource('/api/stock-price?symbol=AAPL');

eventSource.onmessage = (event) => {
  console.log('收到数据:', event.data);
};

eventSource.onerror = (error) => {
  console.error('连接错误:', error);
};

// 关闭连接
eventSource.close();

局限性

  • 原生 EventSource 只支持 GET 请求
  • 无法自定义请求头(如 Authorization)
  • 无法发送请求体(复杂参数需放在 URL 中,不够优雅)

4.1.2 模式二:通过 HTTP POST 发起请求+ 处理 SSE 协议格式的流式响应

针对原生 EventSource 的诸多局限性,社区开发了基于底层 HTTP 能力的第三方库(例如:@microsoft/fetch-event-sourcesse.js等)来突破这些限制。这类库的核心思路是:

  • 利用底层 HTTP API:基于 fetchXMLHttpRequest 等实现可控的流式请求
  • 传递复杂参数:通过 HTTP POST 等方法发起请求并传递复杂参数、认证信息等
  • 手动解析 SSE 协议:直接处理流式响应的文本格式
  • 模拟事件驱动模型:提供与原生 EventSource 兼容的 API 接口
  • 增强控制能力:支持自定义请求方法、请求头、请求体等
  • 完善错误处理:提供更灵活的重连策略和错误处理机制

例如,目前前端最常用的是微软开源的 @microsoft/fetch-event-source 库,它特别适合 AI 应用等需要传递复杂参数和认证信息的场景:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import { fetchEventSource } from '@microsoft/fetch-event-source';

await fetchEventSource('/api/ai/chat', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer your-token-here'
  },
  body: JSON.stringify({
    messages: [
      { role: 'user', content: '请帮我写一段Python代码' }
    ],
    model: 'gpt-4',
    temperature: 0.7
  }),

  onmessage(event) {
    // 处理每条消息
    console.log('收到数据:', event.data);
    const data = JSON.parse(event.data);
    // 更新UI显示
  },

  onerror(error) {
    console.error('连接错误:', error);
    throw error; // 抛出错误会停止重连
  },

  onclose() {
    console.log('连接已关闭');
  },

  // 配置选项
  openWhenHidden: true, // 页面隐藏时保持连接
});

// 使用 AbortController 主动取消连接
const controller = new AbortController();
fetchEventSource('/api/ai/chat', {
  signal: controller.signal,
  // ... 其他配置
});

// 取消请求
controller.abort();

fetch-event-source 的核心优势

  • ✅ 支持 POST 请求,可传递复杂 JSON 参数
  • ✅ 支持自定义请求头(认证、跨域等)
  • ✅ 提供更强的错误处理和重连控制
  • ✅ 支持通过 AbortController 优雅地取消请求
  • ✅ 更好的浏览器兼容性和边界情况处理

在 AI 应用中的实践: 因为 AI 应用对话需要传递完整的对话历史、系统提示词、参数配置等复杂数据,同时需要携带用户认证信息保证安全性,因此这样的 HTTP POST 方法发起请求 + 处理 SSE 协议格式的流式响应的模式在 AI 应用开发中得到了广泛的应用。

其他语言 SSE 客户端的技术选型:

其他的开发语言中同样有丰富的 SSE 客户端库可供选择,例如:

  • Pythonsseclient-pyaiohttp-sse-client
  • Java:Spring WebFlux 的 WebClient
  • gor3labs/sse

在实际项目中,开发者既可以直接使用现有的 SSE 客户端库,也可以根据特定需求自行实现。例如在京东的 JoyAgent-JDGenie 项目中,团队选择基于 OkHttp 自定义实现 SSE 客户端,以便更好地控制连接管理、错误处理和性能优化等细节。理解这些流式通信的底层原理和协议机制,是灵活应对各种技术选型和实现方案的关键基础。

五、MCP 协议 与 Streamable HTTP

5.1 什么是 MCP?

MCP(Model Context Protocol,模型上下文协议)是由 Anthropic 公司于 2024 年 11 月开源的一种标准化通信协议,旨在解决大型语言模型(LLM)与外部数据源及工具之间的无缝集成需求。

核心特性:

  • 统一接口 - 提供标准化的 API 接口,简化 AI 与各种上下文信息之间的交互。
  • 无缝集成 - 轻松集成到现有开发工作流程中,无需复杂适配。
  • 多源数据支持 - 支持从多个来源检索上下文信息,包括代码仓库、文档等。
  • 智能上下文管理 - 优化上下文信息的传输,提升 AI 模型理解和生成的质量。
  • 可扩展设计 - 灵活的架构允许添加新的数据源和功能。

传输层演进:

  • 初始版本(2024.11):基于 HTTP + SSE 作为默认传输方式
  • 重大更新(2025.03.26):引入 Streamable HTTP 替代原先的 HTTP+SSE,成为新的默认传输方式

5.2 什么是 Streamable HTTP?

Streamable HTTP 是一个相对较新的概念,是 MCP 协议在 2025 年 3 月引入的改进传输机制。它是一种结合普通 HTTP 请求和流式传输能力的混合机制,允许客户端通过标准的 POST/GET 请求与服务端交互,同时支持服务端根据需要将响应升级为 SSE 流,实现灵活的实时数据传输。

核心工作流程:

  1. 会话初始化

    • 客户端发送初始化请求到 /message 端点
    • 服务器可选择生成会话 ID 并返回给客户端
    • 会话 ID 用于后续请求中标识和维护会话状态
  2. 客户端到服务器通信

    • 所有消息通过 HTTP POST 请求发送到 /message 端点
    • 请求中包含会话 ID(如果已建立会话)
    • 支持发送结构化的上下文数据和工具调用请求
  3. 服务器响应方式(按需选择)

    • 普通响应:直接返回标准 HTTP 响应,适合简单的请求-响应交互
    • 流式响应:升级连接为 SSE 流,发送一系列事件后关闭连接
    • 长连接模式:维持 SSE 连接持续发送事件,适合长时间交互
  4. 主动建立 SSE 流

    • 客户端可发送 GET 请求到 /message 端点主动建立 SSE 流
    • 服务器通过该流主动推送通知、状态更新或请求响应
  5. 连接恢复与容错

    • 连接中断时,客户端可使用之前的会话 ID 重新连接
    • 服务器可恢复会话状态,继续之前未完成的交互
    • 支持断点续传和状态同步

核心优势:

  • 按需流式传输:服务器可根据响应数据的特点,灵活选择返回普通 HTTP 响应还是升级为 SSE 流,兼顾简单性和实时性
  • 会话持久化:通过会话 ID 机制,支持长时间的有状态交互,适合 AI 应用的多轮对话场景
  • 双向灵活交互
    • 客户端可通过 POST/GET 请求发送数据到服务器(如调用工具、发送消息)
    • 客户端可主动发送请求到服务端端点建立 SSE 流,接收服务器推送
    • 服务器在响应任何 HTTP 请求时,都可以根据需要将响应升级为 SSE 流,实现实时数据推送

SSE vs Streamable HTTP 技术对比:

维度 Server-Sent Events (SSE) Streamable HTTP
协议定义 HTML5 标准定义的专用协议,具有明确的格式和事件处理机制 基于 HTTP 协议的使用模式,不是专门定义的新协议
数据格式 固定的文本格式(eventdataidretry 字段) 灵活的数据格式,完全由应用层定义(通常为 JSON)
连接管理 始终保持单一持久连接,通过该连接发送多个事件 灵活选择持久连接或一次性连接,按需升级为 SSE
灵活性 固定的单向流式模式 可在普通 HTTP 和流式 SSE 之间动态切换 ,支持双向流式模式

技术意义:

Streamable HTTP 代表了 MCP 协议在传输层的重要进化。它通过结合 HTTP 和 SSE 的优点,同时克服二者的局限性,为 AI 应用的通信提供了更灵活、更可靠的解决方案。从技术本质上看,它是对 SSE 协议的创新性扩展,实现了"按需流式"与"双向交互"的有机统一。特别适合需要:

  • 既有简单请求-响应,又有实时流式推送的混合场景
  • 长时间有状态交互的 AI 对话应用
  • 需要会话恢复和容错能力的企业级应用

6. 小结

本章从流式通信的基础概念出发,系统地介绍了流式通信在 AI 应用开发中的核心地位和技术实现。

实践启示:

  • 流式通信不是可选项,而是 AI 应用的必备基础能力
  • 选择技术方案时,要从应用场景、团队能力、基础设施等多维度综合考虑
  • 深入理解底层原理,才能在面对复杂需求时灵活应对,甚至自定义实现
  • 关注协议演进趋势,新技术的出现往往是为了解决实践中的真实痛点

掌握了流式通信的原理和实现后,接下来的章节将深入探讨服务端如何设计流式响应架构,以及客户端如何优雅地处理流式数据,构建完整的端到端流式通信解决方案。

记录技术成长与生活点滴
使用 Hugo 构建
主题 StackJimmy 设计