SpringBoot 2.x 接入非标准SSE格式大模型流式响应实践
在 Spring Boot 2.x 中接入非标准 SSE(Server-Sent Events)格式的大模型流式响应时,需要注意处理数据流的分块传输、响应格式适配和客户端交互。以下是分步骤的实践指南:
一、理解非标准 SSE 的特点
假设大模型的响应流具有以下非标准特征:
-
数据块 不以
data:
开头 -
数据格式可能为 非结构化文本 或 自定义 JSON 结构
-
缺少标准的 SSE 事件分隔符(如
\n\n
)
二、服务端实现
1. 添加依赖
确保 spring-boot-starter-web
已包含:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. 创建 SSE 控制器
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@RestController
public class StreamController {
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter streamData() {
SseEmitter emitter = new SseEmitter(60_000L); // 60秒超时
// 异步处理流式响应
CompletableFuture.runAsync(() -> {
try {
// 模拟调用大模型流式接口
InputStream stream = callModelStreamAPI();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = reader.readLine()) != null) {
// 处理非标准法律格式(示例转换)
String processedData = processNonStandardData(line);
// 发送SSE格式数据
emitter.send(SseEmitter.event()
.data(processedData)
// .id("") // 可选ID
// .name("") // 可选事件名
);
}
emitter.complete();
} catch (Exception e) {
emitter.completeWithError(e);
}
});
return emitter;
}
private String processNonStandardData(String raw) {
// 示例:将非标准数据包装成标准 SSE 格式
return "data: " + raw + "\n\n";
}
}
3. 流式客户端实现(使用 WebClient)
private InputStream callModelStreamAPI() throws IOException {
WebClient webClient = WebClient.create("https://your-model-api.com");
return webClient.get()
.uri("/stream-endpoint")
.accept(MediaType.APPLICATION_STREAM_JSON)
.retrieve()
.bodyToFlux(DataBuffer.class)
.map(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
return new String(bytes, StandardCharsets.UTF_8);
})
.toStream()
.reduce((a, b) -> a + b)
.map(s -> new ByteArrayInputStream(s.getBytes()))
.orElseThrow();
}
三、处理非标准格式的常见场景
场景 1:JSON 包装的非标准响应
假设大模型返回:
{"chunk": "Hello", "seq": 1}
{"chunk": " World", "seq": 2}
处理方式:
ObjectMapper mapper = new ObjectMapper();
while (...) {
String line = reader.readLine();
JsonNode node = mapper.readTree(line);
String text = node.get("chunk").asText();
emitter.send(text);
}
场景 2:无分隔符的连续流
使用缓冲区管理:
StringBuilder buffer = new StringBuilder();
int braceCount = 0;
while ((ch = stream.read()) != -1) {
buffer.append((char) ch);
if ((char) ch == '{') braceCount++;
if ((char) ch == '}') braceCount--;
if (braceCount == 0 && !buffer.isEmpty()) {
processCompleteChunk(buffer.toString());
buffer.setLength(0);
}
}
四、客户端适配(前端示例)
const eventSource = new EventSource('/stream');
eventSource.onmessage = (e) => {
// 处理非标准数据
const rawData = e.data;
appendToOutput(rawData);
};
eventSource.onerror = (e) => {
console.error("Stream error:", e);
eventSource.close();
};https://www.hefeilaws.com/
五、关键配置优化
1. 调整 Tomcat 配置(application.yml)
server:
tomcat:
max-threads: 200 # 增加并发处理能力
max-connections: 10000
2. SSE 超时控制
SseEmitter emitter = new SseEmitter(180_000L); // 3分钟超时
// 心跳保持连接
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
try {
emitter.send(SseEmitter.event().comment("heartbeat"));
} catch (IOException e) {
scheduler.shutdown();
}
}, 0, 30, TimeUnit.SECONDS);
六、异常处理增强
emitter.onTimeout(() -> {
log.warn("SSE timeout");
// 关闭大模型连接
});
emitter.onCompletion(() -> {
log.info("SSE completed");
// 释放资源
});
七、测试验证
使用 curl 测试:
curl -N http://localhost:8080/stream
预期看到:
data: Hello\n\n data: World\n\n
八、性能注意事项
-
使用 背压(Backpressure) 控制数据流速
-
考虑使用 Project Reactor 响应式编程优化资源使用
-
监控 SSE 连接数避免内存泄漏
通过以上实践,即可在 Spring Boot 2.x 中有效接入非标准 SSE 格式的流式响应,同时保持系统的稳定性和可扩展性。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律