Spring Boot 中基于 WebClient 的 SSE 流式接口实战

—— 从 Feign 到 WebClient 的一次真实踩坑记录

一、背景:为什么我要做 SSE?

在最近的一个项目中,我负责接入一个 AI 问答服务
一开始的接口形态非常常规:

@PostMapping("/health_manager") public RespBean<HealthManagerQueryDataVO> sendQuery(...) 

客户端发请求,服务端等 AI 全部生成完内容,再一次性返回。

问题很快就暴露了:

  • AI 返回慢(10 秒甚至更久)
  • 用户页面“卡死”,体验极差
  • 其实 AI 是“边生成边返回”的,但我们完全浪费了这个能力

于是,目标就很明确了:

把原有同步接口,改造成支持 SSE(Server-Sent Events)的流式接口

二、什么是 SSE?为什么适合 AI 问答?

1️⃣ SSE 是什么?

SSE(Server-Sent Events)是一种 服务器主动推送 的 HTTP 通信方式:

  • 基于 HTTP
  • 单向(服务端 → 客户端)
  • 长连接
  • 文本流(text/event-stream

返回的数据长这样:

data: 你好 data: 我是 data: AI 

客户端可以一边接收,一边渲染


2️⃣ 为什么 SSE 特别适合 AI 场景?

技术适配度
HTTP 普通接口❌ 等全部生成
WebSocket❌ 太重
SSE✅ 天生流式

AI 的输出特征是:

  • token 级 / 句子级生成
  • 可边生成边消费
  • 用户随时可能中断

👉 SSE 几乎是最优解


三、第一个坑:Feign 不支持 SSE

项目里原本调用 AI 服务用的是 Feign

@FeignClient("mb-ai") RespBean sendQuery(...) 

一开始我尝试“硬改”,但很快发现:

Feign 本质是一次性 HTTP 调用,它不支持流式消费响应体

哪怕 AI 服务是 SSE,Feign 也会:

  • 等完整响应
  • 再反序列化
  • 流式直接失效

结论很明确:

❌ Feign 不能用于 SSE
✅ SSE 必须用 WebClient / HttpClient

四、正确姿势:WebClient + SseEmitter

1️⃣ Controller 层:返回 SseEmitter

SSE 接口和普通接口最大的不同是:
返回值不再是业务对象,而是一个“连接本身”

@PostMapping( value = "/health_manager/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE ) public SseEmitter healthManagerStream( @RequestBody HealthManagerQueryDTO request) { SseEmitter emitter = new SseEmitter(0L); // 不超时 aiService.streamQuery(request, emitter); return emitter; } 

关键点:

  • produces = text/event-stream
  • 返回 SseEmitter
  • 业务逻辑交给 Service

2️⃣ Service 层:WebClient 真正消费 AI 流

webClient.post() .uri("/health_manager") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.TEXT_EVENT_STREAM) .bodyValue(request) .retrieve() .bodyToFlux(String.class) .subscribe( data -> emitter.send(data), error -> emitter.completeWithError(error), emitter::complete ); 

这段代码的含义是:

  • AI 每吐一段数据
  • 我就 emitter.send()
  • 前端立刻收到

真正实现了“边生成、边返回、边渲染”


五、第二个大坑:UnknownHostException: mb-ai

代码写完,一跑,直接报错:

java.net.UnknownHostException: mb-ai 

第一反应:

“不对啊,Feign 一直是能调用 mb-ai 的”

原因分析

  • Feign:自动走注册中心(Nacos / Eureka)
  • WebClient:只认 DNS
.baseUrl("http://mb-ai") 

在 WebClient 看来:

mb-ai 就是一个普通域名
但 DNS 根本不认识它

六、正确解法:WebClient 接入服务发现

1️⃣ 引入 LoadBalancer

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> 

2️⃣ 给 WebClient.Builder 加 @LoadBalanced

@Configuration public class WebClientConfig { @Bean @LoadBalanced public WebClient.Builder webClientBuilder() { return WebClient.builder(); } } 

3️⃣ baseUrl 继续用服务名

.baseUrl("http://mb-ai") 

此时调用链变成:

WebClient → LoadBalancer → Nacos → 真实 IP:PORT 

UnknownHostException 到此彻底解决


七、最终依赖组合(最小可用)

<!-- WebClient / SSE --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!-- 服务发现 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> <!-- Nacos(项目里一般已有) --> spring-cloud-starter-alibaba-nacos-discovery 
⚠️ 不会把项目变成 WebFlux
只是“在 MVC 项目里用 WebClient”

八、架构上的最终形态(我现在的做法)

Feign └── 普通同步接口(兼容老系统) WebClient └── SSE 流式接口(AI 问答) 

接口层设计成:

POST /health_manager // 非流式 POST /health_manager/stream // SSE 

前端可以按需选择。


九、一些实战踩坑总结

❌ Feign 强行做 SSE

→ 行不通

❌ WebClient 不加 LoadBalanced

→ 必炸 UnknownHostException

❌ 忘了 produces

→ 前端收不到流

❌ AI 实际没返回 text/event-stream

→ 你这边再对也没用


十、写在最后

这次改造最大的收获不是“把 SSE 跑通了”,而是更清楚地理解了:

  • Feign 和 WebClient 的边界
  • 同步接口和流式接口在架构层面的本质差异
  • AI 场景对交互模型的倒逼

如果你现在也在做:

  • AI 问答
  • 长文本生成
  • 实时推送

那么,SSE 几乎是绕不开的一步

Read more

【AIGC】大模型面试高频考点19:常见的17种RAG方案

【AIGC】大模型面试高频考点19:常见的17种RAG方案

RAG技术全景解析:从基础分块到自适应多模态检索 * 一、基础分块与语义优化 * 1. Simple RAG(简单切块) * 2. Semantic Chunking(语义切块) * 3. Context Enriched Retrieval(上下文增强检索) * 4. Contextual Chunk Headers(上下文标题) * 二、检索优化与重排序 * 1. Document Augmentation(文档增强) * 2. Query Transformation(查询转换) * 3. Reranker(重排序) * 4. RSE(Re-ranking with Semantic Expansion) * 三、智能路由与自反思机制 * 1. Feedback Loop(反馈闭环) * 2. Adaptive RAG(

蓝耘智算 + 通义万相 2.1:为 AIGC 装上 “智能翅膀”,翱翔创作新天空

蓝耘智算 + 通义万相 2.1:为 AIGC 装上 “智能翅膀”,翱翔创作新天空

1. 引言:AIGC 的崛起与挑战 在过去几年中,人工智能生成内容(AIGC)技术突飞猛进。AIGC 涉及了文本生成、图像创作、音乐创作、视频制作等多个领域,并逐渐渗透到日常生活的方方面面。传统的内容创作方式已经被许多人类创作者所推崇,但随着时间的推移,人工智能的出现使得创作的边界变得更加模糊。 然而,尽管人工智能技术取得了巨大进展,如何高效地将 AI 模型与计算平台结合,以便为 AIGC 提供更加高效、智能的支持,仍然是一个关键问题。蓝耘智算与通义万相 2.1 的结合为解决这一问题提供了新的方向。这种创新的技术融合使得 AIGC 可以不仅仅依赖于数据处理的能力,还可以实现智能化的生成和创作,推动内容创作的未来。 2. 蓝耘智算:为 AIGC 提供智能支持 2.1 蓝耘智算简介 蓝耘智算是一种综合性计算平台,专注于为大规模人工智能应用提供优化计算资源。在过去几年中,蓝耘智算不断发展壮大,已成为许多行业中的顶尖计算平台之一,广泛应用于机器学习、

AI写作大师Qwen3-4B部署:本地开发环境配置

AI写作大师Qwen3-4B部署:本地开发环境配置 1. 引言 1.1 学习目标 本文将详细介绍如何在本地开发环境中部署 Qwen3-4B-Instruct 模型,构建一个功能完整的 AI 写作与代码生成系统。通过本教程,读者将掌握从环境准备到服务启动的全流程操作,最终实现基于 CPU 的高性能推理应用。 完成本教程后,您将能够: * 成功部署 Qwen3-4B-Instruct 模型 * 启动并访问集成 WebUI 的交互界面 * 执行复杂任务如 Python 程序生成、长文本创作等 * 理解模型在 CPU 环境下的优化策略 1.2 前置知识 建议读者具备以下基础: * 基本的命令行操作能力(Linux/macOS/Windows) * 对 Docker 或 Python 虚拟环境有一定了解 * 了解大语言模型的基本概念(如 token、inference、

云开发 Copilot ——让开发变得更简单

云开发 Copilot ——让开发变得更简单

声明:本篇博客为云开发 Copilot体验文章,非广告 目录 前言: 游客体验 云开发 Copilot实战: 一、图片生成需求 二、云开发 Copilot实现需求 三、AI生成低代码页面 Copilot 的亮点功能 使用场景 云开发 Copilot开发的前景展望 前言: 在云开发AI+中,腾讯云提供一系列与 AI 相关的功能,如大模型接入、 Agent 等,帮助开发者为自己的小程序、web 或者应用快速接入 AI 能力,同时也提供了云开发 Copilot,来加速用户的开发,帮助用户更快构建自己的应用。下面博主将会为大家实战使用云开发 Copilot来助力开发。 云开发 Copilot是云开发推出的一款 AI 开发辅助工具,可以帮助用户快速生成多种类型的应用功能,包括低代码应用、页面、组件、数据模型、