引言
在实时交互应用中,流式输出技术能够显著提升用户体验。本文将通过一个实际的AI问答场景,深入探讨如何使用Java实现高效的流式输出。我们将分析一个基于SSE(Server-Sent Events)技术的完整实现方案,该方案用于实时推送AI生成的答案。
一、核心场景:AI问答的流式响应
在慧教学系统中,AI生成的答案需要实时推送给前端用户。由于AI处理时间较长,传统的同步响应会导致用户长时间等待。流式输出将答案分割成多个片段,逐步推送给客户端,让用户能够即时看到部分结果。
二、SSE技术简介
SSE(Server-Sent Events)是HTML5规范的一部分,允许服务器主动向客户端推送数据。相比WebSocket,SSE更简单、更轻量,特别适合服务器向客户端的单向数据推送场景。
SSE的核心优势:
-
简单易用:基于HTTP协议,无需复杂握手
-
自动重连:浏览器自动处理连接断开和重连
-
文本友好:天然支持UTF-8文本数据
三、实现方案详解
1. SSE端点创建
java
@GetMapping("/stream-qa-answer")
public SseEmitter streamQaAnswer(@RequestParam("uuid") String uuid) {
SseEmitter emitter = new SseEmitter(180000L); // 3分钟超时
// ... 流式处理逻辑
}
设置合理的超时时间(3分钟)是关键,既要保证长连接稳定性,又要避免资源长期占用。
2. 异步流式处理架构
java
CompletableFuture.runAsync(() -> {
try {
// 流式处理主逻辑
} catch (Exception e) {
log.error("流式输出异常", e);
emitter.completeWithError(e);
}
});
状态追踪设计:
-
lastSentIndex:记录最后发送的索引,避免重复发送 -
retryCount:控制重试次数,防止无限循环 -
isFinished:标记流程完成状态
3.智能数据发送策略
java
// 检查缓存重置情况
if (lastSentIndex >= answers.size()) {
lastSentIndex = -1; // 重置索引
}
// 增量发送新数据
for (int i = lastSentIndex + 1; i < answers.size(); i++) {
String answer = answers.get(i);
// 解析并发送数据...
// 发送数据
emitter.send(SseEmitter.event()
.data(data)
.id(String.valueOf(i)) // 使用索引作为ID
.name("message"));
lastSentIndex = i;
Thread.sleep(50); // 模拟流式效果
}
4.完成状态识别与最终推送
java
if ("AI_FINISHED".equals(lastJsonObject.get("AIStatus"))) {
// 发送最终完整数据
Map<String, Object> finalData = buildTeachFinalResult(lastJsonObject);
emitter.send(SseEmitter.event()
.data(finalData)
.name("message"));
isFinished = true;
}
5.错误处理
java
// 超时处理
if (retryCount >= maxRetryCount && !isFinished) {
emitter.send(SseEmitter.event()
.data(Collections.singletonMap("error", "请求超时"))
.name("timeout"));
}
// 回调处理
emitter.onCompletion(() -> log.info("SSE连接完成"));
emitter.onTimeout(() -> {
log.info("SSE连接超时");
AiAnswerStreamCache.remove(uuid); // 清理资源
});
emitter.onError((throwable) -> {
log.error("SSE连接错误", throwable);
AiAnswerStreamCache.remove(uuid);
});
四、与其他技术的对比
| 技术 | 适用场景 | 复杂度 | 双向通信 |
|---|---|---|---|
| SSE | 服务器向客户端推送 | 低 | 单向 |
| WebSocket | 双向实时通信 | 高 | 双向 |
| 长轮询 | 兼容性要求高 | 中 | 单向 |
五、总结
SSE为Java开发者提供了一个简单而强大的实时数据推送解决方案。在AI问答、实时通知等场景中,它能够以较低的成本实现良好的用户体验。通过合理的架构设计(如异步处理、状态管理、错误恢复),SSE方案既保证了实时性,又确保了系统的稳定性和可维护性。
对于需要双向通信或更高频交互的场景,建议考虑WebSocket;对于简单的服务器推送需求,SSE是更轻量、更易实现的选择。