来源
后端资源管理问题调研报告 (benchmark/docs/backend_resource_investigation.md)
问题一:LLM 调用越来越慢
用户体验
连续运行中,每次 LLM 调用耗时逐步增长,到第 50-100 次后额外多出 50-200ms 网络延迟。Windows 上可能出现 WSAENOBUFS(端口耗尽)导致请求直接失败。
根因
1. LLM Provider 每次请求重建,HTTP 连接池不复用 严重度:严重
DynamicLLMService(provider_factory.py:74-75)在每次 generate() 或 stream_generate() 调用时通过 _resolve_provider() 创建全新 provider 实例。每个 provider 构造时创建自己的 httpx.AsyncClient,每次调用都经历完整 TCP + TLS 握手。调用结束后 provider 变为不可达对象,httpx.AsyncClient 未被显式关闭(aclose()),内部连接延迟释放。100+ 测试中累计创建 100-300 个 httpx client 实例。
2. Anthropic 流式端点每次创建临时 httpx client 严重度:中
anthropic_provider.py:212-215 中每次流式请求通过 async with httpx.AsyncClient(...) 创建新 client,连接无法跨请求复用。
3. Gemini Provider 每次调用创建临时 client 严重度:中
gemini_provider.py:40-41 同上,每次调用创建并销毁 httpx.AsyncClient。
修复方向
- Provider 实例应缓存复用,不要每次调用重建
httpx.AsyncClient 应作为单例或长生命周期对象管理
- 提供统一的
close() / aclose() 清理接口
问题二:数据库操作延迟逐渐增大
用户体验
前半段数据库操作 <1s,后半段增长到 5s、10s 甚至超时。.wal 文件从几 KB 膨胀到数十 MB。
根因
1. WAL 文件无限增长 严重度:高
WAL checkpoint 仅在应用启动和关闭时触发。长时间运行中,主进程和守护进程并发读写,WAL 持续增长。WAL 越大读性能越差。
2. 守护进程与主进程的 SQLite 并发写竞争 严重度:高
两个进程共享同一 SQLite 数据库文件(WAL 模式),写事务不能并发,后来的写操作被阻塞等待。
3. busy_timeout=30000 导致写排队 严重度:中
写竞争时后来的操作最多等待 30 秒,高负载下延迟逐渐增加。
4. 数据库连接不关闭 严重度:高
DatabaseConnection.close() 只关闭当前线程连接,应用关闭时未调用 close()。长连接可能持有 WAL 锁,阻止 checkpoint 完成。
修复方向
- 增加定期 WAL checkpoint(如每隔 N 次写操作或定时触发)
- 应用关闭时确保所有连接正确关闭
- 考虑写操作的批量化以减少竞争
问题三:章后分析偶尔丢失
用户体验
保存章节后有时能看到分析结果,有时查不到。连续保存多个章节时问题更频繁。
根因
1. BackgroundTaskService 单线程瓶颈 严重度:中
background_task_service.py:76-79 只有一个工作线程处理所有任务。LLM 调用耗时长时后续任务被阻塞。队列满时(maxsize=200)直接丢弃新任务。
2. BackgroundTasks 串行排队 严重度:高
FastAPI 的 BackgroundTasks 在同一进程内串行。Pipeline 中 LLM 调用耗时 10-30 秒,多章节同时保存时后台任务排队堆积。
3. 每次保存章节都创建全新 Pipeline 实例 严重度:高
get_chapter_aftermath_pipeline() 未被 @lru_cache 装饰,每次 PUT 请求创建全新 Pipeline + 5 个 Repository 实例,高并发下 GC 压力显著增加。
4. TripleRepository 裸构造导致重复对象分配 严重度:高
dependencies.py 中出现 5 次以上 TripleRepository() 裸构造,每次创建新实例和额外的 SqliteKnowledgeRepository。
修复方向
- 对 Pipeline 和 Repository 工厂函数加
@lru_cache
- 增加后台任务工作线程数
- 队列满时持久化任务而非丢弃
问题四:Autopilot 写作速度越来越慢
用户体验
前几章速度可接受,写到第 20-30 章后每章生成时间明显变长。
根因
1. 守护进程每轮为每个小说创建并销毁事件循环 严重度:高
asyncio.run(daemon._process_novel(novel)) 每轮创建新事件循环。导致 TCP 连接无法复用、SSL 上下文重复创建、DNS 缓存无法利用。
2. 后台工作线程反复创建事件循环 严重度:高
background_task_service.py:157 使用 asyncio.run() 执行异步代码,每次都重新初始化 httpx 资源。
3. 守护进程高频短连接 严重度:中
StoryNodeRepository 每个方法都执行 connect → execute → commit → close 循环,连续写 100+ 章时累计创建/关闭连接数千次。
4. 后台任务重试阻塞工作线程 严重度:低
time.sleep(2 ** attempt) 阻塞工作线程,多个失败任务重试叠加阻塞队列。
修复方向
- 守护进程使用持久事件循环而非
asyncio.run()
- 数据库连接复用(连接池或长连接)
- 重试逻辑改为异步等待而非阻塞 sleep
问题五:SSE 事件流偶尔卡住或堆积
用户体验
前端重连 SSE 时可能看到旧事件堆积或连接无法建立,长时间运行后事件流响应越来越迟钝。
根因
SSE 连接无超时/断线检测 严重度:中
4 个 SSE 端点的 event_generator 使用无限循环,无最大存活时间和客户端断开检测。客户端断开后生成器清理依赖 GC,长时间运行累积大量悬空 asyncio 任务。
修复方向
- 增加 SSE 连接超时和心跳检测
- 客户端断开时主动清理资源
问题六:进程内存持续增长
用户体验
长时间运行后 Python 进程 RSS 持续增长,停止操作后内存也不回落。
根因
1. FAISS 向量索引只增不减 严重度:中
ChromaDBVectorStore 的 FAISS 索引在 delete 操作中仅从 metadata 移除记录,索引体积只增不减。
2. 临时对象反复创建 严重度:高
每次保存章节创建全新 Pipeline 和多个 Repository 实例,高并发下 GC 压力持续上升。
修复方向
- 向量索引定期重建(compact)而非仅标记删除
- Pipeline/Repository 实例复用
来源
后端资源管理问题调研报告 (
benchmark/docs/backend_resource_investigation.md)问题一:LLM 调用越来越慢
用户体验
连续运行中,每次 LLM 调用耗时逐步增长,到第 50-100 次后额外多出 50-200ms 网络延迟。Windows 上可能出现
WSAENOBUFS(端口耗尽)导致请求直接失败。根因
1. LLM Provider 每次请求重建,HTTP 连接池不复用
严重度:严重DynamicLLMService(provider_factory.py:74-75)在每次generate()或stream_generate()调用时通过_resolve_provider()创建全新 provider 实例。每个 provider 构造时创建自己的httpx.AsyncClient,每次调用都经历完整 TCP + TLS 握手。调用结束后 provider 变为不可达对象,httpx.AsyncClient未被显式关闭(aclose()),内部连接延迟释放。100+ 测试中累计创建 100-300 个 httpx client 实例。2. Anthropic 流式端点每次创建临时 httpx client
严重度:中anthropic_provider.py:212-215中每次流式请求通过async with httpx.AsyncClient(...)创建新 client,连接无法跨请求复用。3. Gemini Provider 每次调用创建临时 client
严重度:中gemini_provider.py:40-41同上,每次调用创建并销毁httpx.AsyncClient。修复方向
httpx.AsyncClient应作为单例或长生命周期对象管理close()/aclose()清理接口问题二:数据库操作延迟逐渐增大
用户体验
前半段数据库操作 <1s,后半段增长到 5s、10s 甚至超时。
.wal文件从几 KB 膨胀到数十 MB。根因
1. WAL 文件无限增长
严重度:高WAL checkpoint 仅在应用启动和关闭时触发。长时间运行中,主进程和守护进程并发读写,WAL 持续增长。WAL 越大读性能越差。
2. 守护进程与主进程的 SQLite 并发写竞争
严重度:高两个进程共享同一 SQLite 数据库文件(WAL 模式),写事务不能并发,后来的写操作被阻塞等待。
3.
busy_timeout=30000导致写排队严重度:中写竞争时后来的操作最多等待 30 秒,高负载下延迟逐渐增加。
4. 数据库连接不关闭
严重度:高DatabaseConnection.close()只关闭当前线程连接,应用关闭时未调用close()。长连接可能持有 WAL 锁,阻止 checkpoint 完成。修复方向
问题三:章后分析偶尔丢失
用户体验
保存章节后有时能看到分析结果,有时查不到。连续保存多个章节时问题更频繁。
根因
1. BackgroundTaskService 单线程瓶颈
严重度:中background_task_service.py:76-79只有一个工作线程处理所有任务。LLM 调用耗时长时后续任务被阻塞。队列满时(maxsize=200)直接丢弃新任务。2. BackgroundTasks 串行排队
严重度:高FastAPI 的
BackgroundTasks在同一进程内串行。Pipeline 中 LLM 调用耗时 10-30 秒,多章节同时保存时后台任务排队堆积。3. 每次保存章节都创建全新 Pipeline 实例
严重度:高get_chapter_aftermath_pipeline()未被@lru_cache装饰,每次 PUT 请求创建全新 Pipeline + 5 个 Repository 实例,高并发下 GC 压力显著增加。4. TripleRepository 裸构造导致重复对象分配
严重度:高dependencies.py中出现 5 次以上TripleRepository()裸构造,每次创建新实例和额外的SqliteKnowledgeRepository。修复方向
@lru_cache问题四:Autopilot 写作速度越来越慢
用户体验
前几章速度可接受,写到第 20-30 章后每章生成时间明显变长。
根因
1. 守护进程每轮为每个小说创建并销毁事件循环
严重度:高asyncio.run(daemon._process_novel(novel))每轮创建新事件循环。导致 TCP 连接无法复用、SSL 上下文重复创建、DNS 缓存无法利用。2. 后台工作线程反复创建事件循环
严重度:高background_task_service.py:157使用asyncio.run()执行异步代码,每次都重新初始化 httpx 资源。3. 守护进程高频短连接
严重度:中StoryNodeRepository每个方法都执行connect → execute → commit → close循环,连续写 100+ 章时累计创建/关闭连接数千次。4. 后台任务重试阻塞工作线程
严重度:低time.sleep(2 ** attempt)阻塞工作线程,多个失败任务重试叠加阻塞队列。修复方向
asyncio.run()问题五:SSE 事件流偶尔卡住或堆积
用户体验
前端重连 SSE 时可能看到旧事件堆积或连接无法建立,长时间运行后事件流响应越来越迟钝。
根因
SSE 连接无超时/断线检测
严重度:中4 个 SSE 端点的
event_generator使用无限循环,无最大存活时间和客户端断开检测。客户端断开后生成器清理依赖 GC,长时间运行累积大量悬空 asyncio 任务。修复方向
问题六:进程内存持续增长
用户体验
长时间运行后 Python 进程 RSS 持续增长,停止操作后内存也不回落。
根因
1. FAISS 向量索引只增不减
严重度:中ChromaDBVectorStore的 FAISS 索引在delete操作中仅从 metadata 移除记录,索引体积只增不减。2. 临时对象反复创建
严重度:高每次保存章节创建全新 Pipeline 和多个 Repository 实例,高并发下 GC 压力持续上升。
修复方向