Spring Boot + LangChain4j 流式调用大模型生产实践:从首 Token 延迟到百万级会话架构设计
2026/6/12 10:06:01 网站建设 项目流程

Spring Boot + LangChain4j 流式调用大模型生产实践:从首 Token 延迟到百万级会话架构设计

面向对象:有 Spring Boot、微服务、高并发系统经验,希望把 AI 对话、AI 助手、AI Copilot 从“能跑 Demo”升级为“可在线上稳定承载”的工程团队。

很多团队第一次接入大模型时,代码往往是这样的:

String answer = chatModel.chat(userMessage); return ResponseEntity.ok(answer);

在功能验证阶段,这样写没有问题;但一旦进入真实业务,问题会迅速暴露:

  1. 用户要等模型完整生成后才能看到结果,首屏感知很差。
  2. 一个请求会长时间占住线程,QPS 一上来线程池就被打满。
  3. 超长输出、弱网取消、限流、审计、追踪、会话记忆、多模型切换都没有治理点。
  4. 当对话服务从单机演进到多实例部署时,本地会话上下文、SSE 长连接和弹性扩缩容之间会互相牵扯。

所以,流式调用的价值从来不只是“打字机效果”,而是把 AI 服务从一次性阻塞 RPC,升级为一条可观测、可治理、可扩展的实时输出链路。

本文不只讲 LangChain4j 的调用方法,而是从协议、线程模型、架构分层、工程治理、生产代码、容量规划几个层面,完整讲清楚:

  1. 为什么流式输出是 AI 应用的基础设施能力。
  2. Spring Boot 中为什么 WebFlux 比传统 Servlet 更适合此类场景。
  3. LangChain4j 的流式回调如何正确桥接为 Reactor 流。
  4. 高并发下如何处理限流、背压、取消、超时、熔断、会话记忆和审计。
  5. 如何把一套 Demo 升级成可上线的生产级方案。

一、为什么 AI 对话必须流式化

1.1 用户感知的核心不是总耗时,而是 TTFT

在传统同步调用模式下,用户必须等待完整答案生成结束后才能看到响应。假设一次回答总耗时 8 秒,哪怕答案质量很高,用户主观感受依然会认为系统“卡住了”。

而流式模式下,系统可以在 300ms 到 1200ms 内把首个 token 推给前端。这里最关键的指标不是总时长,而是:

  1. TTFT:Time To First Token,首 token 延迟。
  2. Tokens/s:流式输出吞吐。
  3. Completion Ratio:请求发起后最终成功完成的比例。
  4. Cancel Ratio:用户中途取消比例。

对 AI 聊天产品来说,TTFT 往往比总耗时更决定体验。因为一旦用户看到内容开始输出,就认为系统“已经在工作”。

1.2 从资源模型看,流式比阻塞式更适合高并发

传统阻塞式接口的问题不只是慢,而是资源利用方式错误。

当你使用 chatModel.chat() 阻塞等待结果时:

  1. 业务线程被占住。
  2. 网关连接被长时间持有。
  3. 下游模型接口在慢速返回时,上游线程只能空等。
  4. 当并发上升时,线程数、上下文切换、堆内对象和连接池都会一起膨胀。

这类链路本质上是“外部 I/O 主导型”场景,真正消耗 CPU 的时间远少于等待模型返回 token 的时间。因此,事件驱动 + 非阻塞 I/O 才是更合理的运行模型。


二、流式大模型调用到底发生了什么

2.1 底层并不是“模型一次次回调”,而是 HTTP 分块传输

大部分模型服务商在开启流式输出后,本质都是基于 HTTP chunked transfer 或 SSE 持续返回增量内容。整体链路可以抽象成下面这样:

Browser / App | | POST /api/ai/chat/stream v AI Gateway / Chat Service | | stream=true v LLM Provider | | chunk-1: "你" | chunk-2: "好" | chunk-3: ",下面" | chunk-4: "我来解释" v AI Gateway / Chat Service | | SSE / text-event-stream v Browser incremental render

也就是说,模型不是等全部文本生成完才返回,而是边解码、边通过网络向上游推送增量结果。后端要做的事情,不是“等待所有结果后统一返回”,而是把这条增量流安全地向前端透传,并在链路两侧补上治理能力。

2.2 LangChain4j 在这个过程中扮演什么角色

LangChain4j 的价值不是替代 Spring,而是把模型调用、消息结构、记忆、工具调用等能力抽象成 Java 生态可组合的接口。

在流式场景里,最关键的是它提供的 StreamingChatModel。它会把下游模型返回的增量结果,通过回调持续通知业务代码。

这意味着:

  1. LangChain4j 解决了“如何和模型流式交互”。
  2. Spring WebFlux 解决了“如何把这条流稳定地暴露给客户端”。
  3. 你的业务代码要解决“如何治理这条流”。

2.3 为什么不建议把流式理解成“边输出边拼字符串”

很多 Demo 的思路是:每来一个 token,就 append 到 StringBuilder,然后直接返回给前端。

这只是最表层的实现。线上真正要处理的是:

  1. 某个 token 到达很慢,是否算超时。
  2. 前端断开连接后,是否继续让模型生成。
  3. 流式过程中是否要记录审计日志和成本指标。
  4. 长文本输出时如何避免内存无限增长。
  5. 多租户配额、模型路由、故障切换如何嵌入流式链路。

所以,流式调用的正确视角不是“字符串流”,而是“受治理的实时事件流”。


三、生产级架构应该怎么设计

3.1 推荐的分层结构

对于 AI 对话、AI 客服、AI 助手一类场景,推荐采用下面这套分层:

接入层 - Web / App / 小程序 / BFF 输出层 - SSE / HTTP streaming 会话层 - Session 管理 - 用户上下文 - 消息编排 - 取消控制 推理层 - LangChain4j - Prompt 组装 - Tool Calling - RAG 检索 - Multi-model routing 治理层 - 限流 - 熔断 - 重试 - 降级 - 审计 - 成本控制 状态层 - Redis 会话记忆 - Kafka 审计事件 - MySQL/PostgreSQL 对话元数据 - Metrics / Trace / Log

这里最容易被忽略的是治理层与状态层。很多项目直接把 LangChain4j 嵌在 Controller 里,功能能通,但业务一放量就会暴露出治理缺口。

3.2 为什么 Spring Boot 场景推荐 WebFlux

如果接口是典型的“CPU 计算型短请求”,Servlet 模型完全够用。但 AI 流式输出不是这种场景,它具有三个特点:

  1. 请求持续时间长。
  2. 大量时间消耗在等待外部模型返回。
  3. 每个请求会产生多次增量输出。

在这种场景下,如果还用阻塞式线程模型,一个请求往往会长期占住一个工作线程,系统容量会被线程数而不是 CPU 算力限制。

WebFlux 的价值在于:

  1. 用更少的线程承载更多长连接。
  2. 把输出建模成 Flux,天然适合表达 token 流、事件流、完成信号和错误信号。
  3. 更容易做超时、取消、背压和链路观测。

这里不是说 Servlet 绝对不能做流式,而是从高并发和治理成本看,WebFlux 更顺手,也更接近流式 AI 服务的资源模型。

3.3 为什么大多数 AI 输出场景优先选 SSE

如果你的场景是“用户发起一次提问,服务端持续返回结果”,那优先选 SSE。

因为 SSE 有几个非常现实的优点:

  1. 基于标准 HTTP,代理层和网关层更容易兼容。
  2. 语义清晰,天然就是单向事件推送。
  3. 前端接入简单,很多平台都能较低成本支持。
  4. 对 AI 输出这类“服务端连续推送”模式足够合适。

只有在以下情况才更建议 WebSocket:

  1. 需要客户端随时插入控制命令,例如暂停、继续、切换模式。
  2. 需要双向实时协作,例如实时语音、多人协同。
  3. 需要在一条连接里承载大量不同类型事件。

大多数文本生成场景中,SSE 的复杂度更低,工程性更强。


四、从 Demo 到线上,核心链路应该怎样落地

下面给出一套更接近生产的实现骨架。示例以 Spring Boot + WebFlux + LangChain4j 为主,重点不在于逐行 API,而在于系统边界和治理位置。

4.1 Maven 依赖

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> </dependencies>

如果你的项目已经采用企业统一 SDK 或私有模型网关,那么 LangChain4j 的 provider 依赖应替换成对应适配器,不要强绑某一家模型厂商。

4.2 基础配置

server: port: 8080 spring: application:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询