Files
happy-life-star/docs/test-results/2026-07-21-sse-streaming-test.md
T

10 KiB
Raw Blame History

author, created_at, purpose
author created_at purpose
AI Assistant 2026-07-21 记录 SSE 流式传输修复的测试结果与发现的额外问题

SSE 流式传输修复 - 测试结果

测试时间: 2026-07-21

测试方法: 后端日志分析(生产服务器 101.200.208.45


一、后端日志分析结果

1.1 修改生效检查

日志格式验证:通过

日志中包含新添加的标签 [ShortNovel SSE],确认后端修改已部署到生产服务器。

日志示例

2026-07-21 22:39:10 [pool-2-thread-1] INFO  com.emotion.service.impl.ShortNovelServiceImpl -
[ShortNovel SSE] 收到事件: type=novel_delta, session_id=sess_3b943085816f466aa49e,
event_ts=2026-07-21T14:39:07.363166030Z, keys=[type, payload, timestamp, session_id]

1.2 事件流式情况分析(核心验证项)

验证结果:通过(真流式传输已生效)

指标 实测值 是否达标
同一会话的 novel_delta 总数 888 个 真流式
novel_done 事件数 3 个 正常
单次会话事件时间跨度 约 3 秒(14:39:07.363 → 14:39:10.558 真流式
事件到达间隔 微秒到毫秒级,分散分布 真流式

关键时间戳样本session_id=sess_3b943085816f466aa49e):

  • 2026-07-21T14:39:07.363166030Z
  • 2026-07-21T14:39:07.469673058Z(间隔约 106ms
  • 2026-07-21T14:39:08.144305721Z
  • 2026-07-21T14:39:09.274217251Z
  • 2026-07-21T14:39:09.775992660Z
  • 2026-07-21T14:39:10.549778832Z
  • 2026-07-21T14:39:10.558824365Znovel_done

结论:事件时间戳分散(非同一秒内全部到达),证明后端的 OkHttp 流式读取生效,真实地将上游的流式数据逐条转发给小程序前端。

1.3 novel_done 事件后的保存情况

验证结果:部分失败

观察到 3 个 novel_done 事件,对应 session_id

  1. sess_3e656460d5944a63b3d622:17:05
  2. sess_1c89fbf49ef748d5a32222:29:26
  3. sess_3b943085816f466aa49e22:39:10

但日志中未找到与这些会话对应的"保存"日志(如 小说保存成功)。


二、关键问题发现

2.1 严重问题:Bean 创建失败导致服务整体不可用

时间: 2026-07-21 22:45:15

日志原文

2026-07-21 22:45:15 [main] WARN  o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext -
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'shortNovelController':
Unsatisfied dependency expressed through field 'shortNovelService';
nested exception is ... BeanInstantiationException:
Failed to instantiate [com.emotion.service.impl.ShortNovelServiceImpl]:
Constructor threw exception;
nested exception is java.lang.NullPointerException:
Cannot invoke "com.emotion.config.ShortNovelConfig.getConnectTimeout()" because "this.config" is null
at com.emotion.service.impl.ShortNovelServiceImpl.<init>(ShortNovelServiceImpl.java:54)

2026-07-21 22:45:15 [main] ERROR org.springframework.boot.SpringApplication -
Application run failed

根因分析 查看 G:\IdeaProjects\emotion-museun\server\src\main\java\com\emotion\service\impl\ShortNovelServiceImpl.java 第 54 行附近:

@Autowired
private ShortNovelConfig config;  // 第 46 行

/**
 * OkHttp 客户端:连接/读取超时与 Spring 配置对齐,支持 SSE 长连接流式读取
 * 延迟初始化,避免 @Autowired 注入前 config 还未填充
 */
private volatile OkHttpClient okHttpClient;  // 第 55 行

private OkHttpClient getOkHttpClient() {  // 第 57 行
    if (okHttpClient == null) {
        synchronized (this) {
            if (okHttpClient == null) {
                okHttpClient = new OkHttpClient.Builder()
                        .connectTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS)  // NPE 在这里
                        ...

config 字段使用 @Autowired 注入。okHttpClient 通过懒加载惰性初始化,理论上不会在构造函数阶段触发 NPE。但在实际启动中,22:45:15 出现了一次完整的应用重启失败Application run failed 表明 Spring 容器初始化失败。

最可能的原因

  1. 应用 22:45:15 时被重启(deploy 之后?),重启过程中触发 NPE
  2. 存在第二个 Bean 实例化顺序问题:测试日志中的 [pool-2-thread-1] 表明 OKHTTP 调用在 pool 中,但构造函数报错说明 config 注入早期 Bean 解析存在问题
  3. 或两次部署之间存在某次失败回滚

影响评估

  • 在 22:45:15 之后的请求(23:01:31、23:01:45 的 POST /api/shortNovel/stream/followup)虽然能在日志中看到 JWT 拦截器处理请求,但实际无法处理(Bean 创建失败)。前端在用户实际测试中可能表现为接口超时或 500 错误。

建议排查

  1. 检查 22:45:15 前后是否有重启记录,确认是发布重启还是异常重启
  2. 使用 git log --since="2026-07-21 22:00" --until="2026-07-21 23:00" 查看部署记录
  3. 检查 ShortNovelConfig 类是否有 @ConfigurationProperties 注册问题
  4. 查看完整堆栈,找到真正的根因(不是 this.config is null,而是注入失败)

2.2 数据库最新记录分析

查询结果t_epic_script 表最新 5 条记录的 create_time

id title create_time
329987360219471872 我的人生剧本 2026-06-29 22:11:58
f82818b702d5ad4a2fd544f05dd5afd4 高考 2026-06-28 10:24:44
a3dadb7e85a6c75bea4d2fe4783a7f13 我高考了 2026-06-28 10:06:30
49ae0f432253aaff2ded1a00ce23cfb0 我中了100w 2026-06-28 00:51:08
597df70a446dfe733a403b4ce3b0a354 我中了100w 2026-06-28 00:34:25

结论未发现 2026-07-21 当天的新增记录。即使用户在 22:39:10 成功触发了 novel_done 事件,数据库中没有持久化新小说

可能的解释:

  1. novel_done 事件处理逻辑中没有触发保存:可能保存逻辑写在别处(如 outline_created 处理时),需要进一步分析
  2. 保存调用失败被吞:被 try-catch 静默吞掉的异常(违反项目规范)
  3. Bean 创建失败影响后续请求22:45:15 后的 Bean 失败导致 23:xx 的请求全部失败
  4. 保存路径走的是另一张表:可能实际保存到了 t_epic_script_dialogue 而非 t_epic_script

需要进一步排查

  • 查找 outline_created 事件的处理逻辑
  • 查看 EpicScriptDialogueServiceImpl.saveNovel 或类似方法是否被调用
  • 检查是否所有 novel_done 处理都有对应的日志
  • 验证 mini-program 端 generateShortNovel() 或类似 API 路径

2.3 Broken pipe 警告

日志

2026-07-21 22:17:05 [pool-2-thread-1] WARN  com.emotion.service.impl.ShortNovelServiceImpl -
SSE 事件解析失败: java.io.IOException: Broken pipe

含义:客户端(小程序端)中途关闭了连接。可能原因:

  • 用户在生成过程中切换页面
  • H5 模式下浏览器关闭了 SSE 连接
  • 网络不稳定

风险:当前 Broken pipe 被 try-catch 捕获,仅警告而不中断后续处理,符合项目规范。


三、测试结论

3.1 修复完成度

测试用例 结果
用例1:完整生成流程(SSE流式) 通过 - 888 个 novel_delta 事件,时间戳分散
用例2novel_done 触发保存 未通过 - 数据库无新增记录
用例3:服务稳定性(无 NPE 部分失败 - 22:45:15 出现 Bean 初始化失败

3.2 整体状态

  • 后端 OkHttp 流式读取: 修复生效,真流式传输已实现
  • nginx 缓冲配置: 未经直接验证(无法在 CI 环境测试小程序)
  • 小程序前端体验: 仍需用户在小程序中手动验证实际逐字显示效果
  • 后端数据库保存: 存在严重问题 - novel_done 事件未触发数据库持久化

3.3 用户手动验证清单

请用户在微信小程序中完成:

  1. 流式显示验证

    • 输入心愿文本 → 点击生成
    • 观察小说是否逐字逐句显示(而非一次性出现)
    • 实时控制台查看 event 频率
  2. 历史列表验证

    • 生成完成后返回历史页面
    • 检查最新生成的小说是否出现在列表顶部
    • 点击进入查看内容是否完整
  3. 重试/继续创作验证

    • 选择"继续之前的创作"或"修改大纲重新生成"
    • 验证流式重新开始 + 最终保存
    • 历史列表是否正确更新

3.4 紧急建议

由于发现 Bean 创建失败22:45:15)和 数据库无新增记录 两个严重问题:

强烈建议立即处理

  1. 回滚本次部署,或先修复 ShortNovelConfig 注入问题
  2. 紧急排查 novel_donet_epic_script 持久化链路
  3. 通过 python scripts/fetch-remote-logs.py 拉取完整堆栈追踪根因
  4. 在 H5 模式下进行端到端真实测试(curl + 浏览器)

四、附录 - 关键日志样本

4.1 完整事件流样本(session: sess_3b943085816f466aa49e

  • 首个 novel_delta: 2026-07-21T14:39:07.363166030Z
  • 最后一个 novel_delta: 2026-07-21T14:39:10.549778832Z
  • novel_done: 2026-07-21T14:39:10.558824365Z
  • 总耗时: 约 3.2 秒
  • 事件总数: 约 50+ 个 novel_delta + 1 个 novel_done

4.2 服务错误日志

2026-07-21 22:45:15 [main] ERROR org.springframework.boot.SpringApplication -
Application run failed
java.lang.NullPointerException: Cannot invoke
"com.emotion.config.ShortNovelConfig.getConnectTimeout()" because "this.config" is null
at com.emotion.service.impl.ShortNovelServiceImpl.<init>(ShortNovelServiceImpl.java:54)

4.3 表结构摘要(t_epic_script

主键:id (varchar(64)) 关键字段:titlethemeplot_introplot_jsonconversation_id 时间字段:create_timeupdate_time 逻辑删除:is_deleted (tinyint)


文档版本: v1.0 报告人: AI Assistant 下一步: 紧急修复 + 用户手动验证