# 并发能力优化实施计划与过程记录

## 背景

当前用户端问答链路已经接入飞书知识库检索和大模型调用。随着真实用户进入，系统会面对多个慢外部依赖：

- 飞书 Wiki / Docx / Drive 文件读取。
- 大模型接口调用。
- SSE 长连接输出。
- MySQL 聊天记录和日志写入。

如果没有并发保护，高峰期请求可能堆满后端 worker、线程池、数据库连接或外部 API 限额，最终表现为用户端长时间无响应、`Failed to fetch`、502/500 或服务整体变慢。

## 当前问题判断

根据当前代码现状，主要风险不是单纯 worker 数量不足，而是问答主链路仍有较多同步阻塞点：

1. `/chat/completions` 会先完成飞书检索和模型完整调用，再开始返回 SSE。
2. 当前 SSE 更接近“完整答案切片输出”，不是模型真实流式输出。
3. 飞书和模型调用使用同步 `httpx`，外部服务慢时会占住后端执行资源。
4. 飞书缓存是进程内缓存，多 worker 后缓存不共享。
5. 当前没有全局并发准入和排队机制，请求超过能力边界时缺少用户可理解的等待状态。

## 优化目标

一期并发优化先达成下面目标：

1. 高峰期不让请求无限进入飞书和模型链路。
2. 用户端能看到“排队中 / 生成中 / 请求过多”的明确状态。
3. 后端能通过配置控制最大并发、最大排队数和排队超时时间。
4. 为后续 async 化、真流式、Redis 缓存和多 worker 扩展留好边界。

## 实施步骤

### 阶段 1：并发准入与排队兜底

目标：先保护系统，不让过量请求直接打满飞书和模型。

实现内容：

- 后端增加问答并发管理器。
- 配置项：
  - `chat_max_active_requests`：同时进入生成链路的最大请求数。
  - `chat_max_queue_size`：允许等待的最大排队数。
  - `chat_queue_timeout_seconds`：最长排队等待时间。
- 用户端 SSE 支持状态事件：
  - `queued`：请求已进入排队。
  - `generating`：请求获得执行名额，开始生成。
  - `content`：模型内容片段。
  - `error`：排队超时、队列满或外部服务错误。
- 队列满时直接提示“当前请求过多，请稍后再试”。
- 排队时不扣每日次数；进入真实生成并落库后再按原逻辑更新。

阶段限制：

- 第一阶段可以先使用进程内并发管理器，适合当前单 worker / 本地开发。
- 多 worker 生产环境需要阶段 4 的 Redis 全局队列，否则每个 worker 只知道自己的排队状态。

### 阶段 2：模型真实流式输出

目标：用户秒见首字，减少“请求像卡死”的感觉。

实现内容：

- 模型调用支持上游 `stream=true`。
- 后端边接收模型 chunk 边通过 SSE 推给前端。
- 后端累计完整回答，生成结束后再写入 assistant 消息和 AI 请求日志。
- 用户取消时尽量关闭上游模型请求。

### 阶段 3：飞书与模型调用 async 化

目标：减少同步阻塞，提高单 worker 并发承载能力。

实现内容：

- 飞书读取改为 `httpx.AsyncClient`。
- 模型调用改为异步。
- `/chat/completions`、RAG 构建、模型服务逐步改为 async。
- 注意数据库仍需独立评估，避免在 async 链路里长时间持有同步 DB session。

### 阶段 4：Redis 全局队列与共享缓存

目标：支持多 worker / 多实例部署。

实现内容：

- Redis 存储全局并发计数、等待队列和取消标记。
- Redis 缓存飞书 token、node info、children、docx/file 文本内容。
- 多 worker 共享缓存，避免每个 worker 重复读取飞书。
- 增加缓存 TTL 和手动清理策略。

### 阶段 5：worker、连接池和压测调参

目标：基于数据确定 worker 数和连接池配置。

实现内容：

- Docker/生产启动支持配置 worker 数。
- 调整 SQLAlchemy pool、MySQL `max_connections` 和网关超时。
- 压测 10 / 50 / 100 / 200 并发，记录：
  - 首字时间。
  - 总响应时间。
  - 错误率。
  - 队列等待时间。
  - 飞书读取耗时。
  - 模型调用耗时。
  - DB 连接数。

## 当前执行计划

阶段 1 已完成，下一步进入阶段 2“模型真实流式输出”。

阶段 2 本次实施范围：

1. 先支持 OpenAI 兼容协议和 Anthropic Messages 协议的上游真实流式。
2. MiniMax、Gemini 等非主线协议暂时保持非流式调用，并通过统一事件接口降级输出。
3. 后端在接收模型 chunk 时同步通过 SSE 输出给用户端，并在结束后累计完整回答落库。
4. 流式过程中如果模型调用失败，返回 `error` 事件，并记录失败日志。
5. 用户中断或连接断开时，尽量关闭上游模型连接；已收到但未完成的回答不作为成功消息落库。

## 风险记录

1. 进程内队列不是最终生产方案，多 worker 后需要 Redis。
2. 当前模型和飞书外部 API 仍可能限流，排队只能保护本系统，不能突破外部限额。
3. 排队请求持有 SSE 连接，网关和浏览器超时时间要一起配置。
4. 真实流式前，用户端虽然能看到排队状态，但进入生成后仍要等完整模型结果才能输出内容。

## 阶段 1 实施记录

2026-07-08 开始实现第一阶段“并发准入与排队兜底”。

已完成：

1. 后端新增进程内问答队列管理器，支持最大生成并发、最大等待队列和排队超时。
2. `/chat/completions` 改为立即返回 SSE 流，并通过 SSE 事件通知用户端：
   - `queued`：请求进入排队。
   - `generating`：请求获得执行名额。
   - `content`：回答内容片段。
   - `error`：队列满、排队超时或生成失败。
3. 系统设置新增三个配置项：
   - `chat_max_active_requests`
   - `chat_max_queue_size`
   - `chat_queue_timeout_seconds`
4. 用户端 H5 支持排队状态展示，排队时在 AI 气泡中显示等待提示，进入生成后切换到正常回答。
5. 队列满时返回“当前请求过多，请稍后再试”，避免请求无限堆积。

阶段限制：

1. 当前队列是单进程内存队列，适合当前开发环境和单 worker 兜底。
2. 多 worker / 多实例部署前，必须升级为 Redis 全局队列，否则每个 worker 只会管理自己的排队状态。
3. 当前仍不是真模型流式，进入生成后首字时间仍取决于飞书检索和模型完整返回时间。

验证记录：

1. 后端 `compileall` 检查通过。
2. 用户端 H5 `npm run build` 通过。
3. 管理后台 `npm run build` 通过；仅存在第三方依赖 Rollup 注释告警，不影响构建。
4. `git diff --check` 通过。
5. Docker dev 环境已重新构建并启动：backend、user-client、admin-web、mysql 均正常运行。
6. 队列管理器验证通过：`max_active_requests=1`、`max_queue_size=1` 时，第一个请求获得执行名额，第二个请求进入排队，第三个请求被拒绝，释放名额后第二个请求恢复执行。
7. 真实 `/chat/completions` SSE 验证通过：接口先返回 `generating` 事件，随后返回连续 `content` 事件。

## 阶段 2 实施记录

2026-07-08 开始实现第二阶段“模型真实流式输出”。

设计决策：

1. 先不改动现有非流式 `ChatService.create_answer` 主逻辑，新增独立流式服务承载用户端 `/chat/completions`。
2. 流式模型调用优先覆盖 OpenAI 兼容协议和 Anthropic Messages 协议。
3. 非流式协议保留降级路径，保证模型配置多样性不被破坏。
4. 本阶段仍使用同步 `httpx` 的流式能力；真正 async 化放到阶段 3。
5. 本阶段不引入 Redis，全局多 worker 协调继续放到阶段 4。

已完成：

1. 新增 `ModelStreamService`，负责模型流式协议适配。
2. 新增 `ChatStreamService`，负责流式问答过程中的用户消息保存、模型 chunk 输出、助手消息落库和 AI 请求日志记录。
3. `/chat/completions` 已从“完整回答后切片输出”改为“边接收模型 chunk 边发送 SSE `content` 事件”。
4. OpenAI 兼容协议支持 `stream=true` 并解析 `choices[].delta.content`。
5. Anthropic Messages 协议支持 `stream=true` 并解析 `content_block_delta` 文本事件。
6. DeepSeek 等兼容协议返回的 `reasoning_content` 会被转换成 `<think>...</think>`，保持当前 H5 思考态显示逻辑可用。
7. MiniMax、Gemini 或关闭流式的模型配置会自动降级为非流式调用，再通过统一 SSE 事件输出。
8. 如果当前后端已具备历史对话/摘要能力，流式服务会自动传入历史上下文；旧版本签名不支持时自动回退。

验证记录：

1. 容器内 `compileall` 检查通过。
2. OpenAI 兼容协议模拟流式事件解析通过，输出格式为 `<think>思考</think>答案`。
3. Anthropic Messages 协议模拟流式事件解析通过，输出格式为 `<think>想</think>答`。
4. 后端健康检查通过。
5. 真实 `/chat/completions` 验证通过：接口先返回 `generating`，随后连续返回上游模型 chunk，最后返回 `[DONE]`。
6. 真实会话历史验证通过：流式完成后用户消息和助手消息均已落库。

阶段限制：

1. 本阶段仍是同步 `httpx.stream`，一个请求生成期间仍会占用当前 worker 执行资源。
2. 用户端能更快看到模型输出，但飞书检索阶段仍在首字之前完成；首字时间还会受飞书读取耗时影响。
3. 多 worker 全局排队、共享飞书缓存、异步飞书读取仍需在阶段 3 和阶段 4 继续处理。

## 阶段 3 拆分记录

2026-07-08 进入第三阶段前评估当前代码边界。

当前判断：

1. 飞书检索、RAG 构建、聊天消息落库和模型调用仍串在同一条同步链路中。
2. 当前工作区已有知识库检索相关未提交改动，包括按标题筛选文档、段落相关性截取、对话历史和摘要注入。
3. 如果直接把飞书服务整体改成 async，容易把“检索准确性改动”和“并发性能改动”混在同一个提交里，后续回滚和排查都会变难。

阶段 3 拆分为两步：

1. 阶段 3A：先异步化模型长连接流式调用，让模型生成期间不长期占用同步 worker 线程。
2. 阶段 3B：再异步化飞书读取和搜索接口，并同步梳理 RAG 构建的数据库会话边界。

阶段 3A 设计约束：

1. 不修改知识库检索排序和内容截取逻辑。
2. 不调整数据库 schema。
3. 不改变用户端 SSE 协议。
4. 保留当前队列兜底，避免 async 改造期间请求无限进入外部服务。

阶段 3B 预留事项：

1. 飞书 token、wiki node、children、docx/file 文本缓存需要与阶段 4 Redis 缓存一起设计。
2. async DB session 是否引入，需要结合 SQLAlchemy 连接池和迁移成本单独评估。
3. 如果短期不引入 async DB session，飞书/RAG 可以先使用独立的异步外部请求层，DB 读写仍保持同步但缩短持有时间。

## 阶段 3A 实施计划

目标：把模型真实流式阶段中的上游长连接调用改成异步 `httpx.AsyncClient.stream`，减少模型生成期间对同步 worker 线程的占用。

实施范围：

1. `/chat/completions` 改为 async SSE 生成器。
2. `ChatStreamService` 增加 async 流式入口，保留原同步入口作为兼容和回退。
3. `ModelStreamService` 增加 async 流式入口：
   - OpenAI 兼容协议使用 `AsyncClient.stream`。
   - Anthropic Messages 协议使用 `AsyncClient.stream`。
   - mock、未命中知识库、关闭流式、MiniMax/Gemini 等仍走安全降级输出。
4. SSE 事件格式保持不变，用户端无需改动。
5. 队列兜底先保持当前进程内逻辑不变，Redis 全局队列仍放到阶段 4。

风险控制：

1. 不修改飞书检索、RAG 排序、段落截取和知识库召回逻辑。
2. 不修改数据库 schema。
3. 不把当前工作区已有的 5 个后端未提交文件混入阶段 3A 提交。
4. 如果 async 模型流式验证失败，保留同步流式入口，便于快速回退。

## 阶段 3A 实施记录

2026-07-08 完成模型长连接异步化第一版。

已完成：

1. `/chat/completions` 的 SSE 生成器已切换为 async 生成器。
2. 排队等待改为 `asyncio.to_thread(...)`，避免排队中的请求阻塞事件循环。
3. `ChatStreamService` 新增 `stream_answer_async`，保留原同步 `stream_answer` 作为兼容入口。
4. `ModelStreamService` 新增 async 模型流式入口：
   - OpenAI 兼容协议使用 `httpx.AsyncClient.stream`。
   - Anthropic Messages 协议使用 `httpx.AsyncClient.stream`。
5. mock、未命中知识库、关闭流式、MiniMax/Gemini 等路径保留安全降级；需要同步调用模型时使用 `asyncio.to_thread(...)` 放到线程中执行。
6. SSE 事件协议未变化，用户端无需改动。

验证记录：

1. 本机 `compileall` 检查通过。
2. 容器内 `compileall` 检查通过。
3. OpenAI 兼容协议 async 模拟流解析通过，输出格式为 `<think>思考</think>答案`。
4. Anthropic Messages 协议 async 模拟流解析通过，输出格式为 `<think>想</think>答`。
5. 后端健康检查通过。
6. 真实 `/chat/completions` 验证通过：首个事件为 `generating`，随后连续返回 `content`，最后返回 `[DONE]`。
7. 真实会话历史验证通过：流式完成后用户消息和助手消息均已落库。

阶段限制：

1. 飞书检索、RAG 构建、数据库读写仍是同步逻辑；本阶段只优化模型长连接流式调用。
2. 首字时间仍会受到飞书读取和 RAG 构建耗时影响。
3. 队列仍是进程内队列，多 worker 全局并发控制需要阶段 4 Redis 队列。

## 阶段 3B 实施计划

目标：在不改动当前知识库检索脏文件的前提下，新增异步飞书读取和异步 RAG 构建路径，让用户端问答链路里的飞书搜索、Wiki 节点读取、Docx/File 下载不再使用同步 `httpx`。

实施范围：

1. 新增 `AsyncFeishuKnowledgeService`：
   - 飞书搜索接口使用 `httpx.AsyncClient.post`。
   - 飞书 tenant token 获取使用异步 HTTP。
   - Wiki node info、children、Docx blocks、Drive file download 使用异步 HTTP。
   - 复用现有进程内缓存和解析函数，避免同步/异步两套路由结果不一致。
2. 新增 `AsyncRagService`：
   - 权限范围和 Prompt 读取仍使用当前同步 DB session。
   - 外部飞书读取切到 async 服务。
   - 兼容当前工作区里已经存在的历史对话/摘要 prompt 签名；旧签名则自动回退。
3. `ChatStreamService.stream_answer_async` 切到 `AsyncRagService.build_result`。
4. 同步 `ChatStreamService.stream_answer` 保持不变，作为兼容和回退路径。

风险控制：

1. 不直接编辑当前已有未提交改动的 `feishu_service.py` 和 `rag_service.py`。
2. 不改变搜索 payload、结果解析、知识片段打分规则。
3. 不改变用户端 SSE 协议。
4. 本阶段仍不引入 Redis，全局缓存和全局队列放到阶段 4。

## 阶段 3B 实施记录

2026-07-08 完成异步飞书读取和异步 RAG 构建第一版。

已完成：

1. 新增 `AsyncFeishuKnowledgeService`：
   - 飞书搜索接口改为异步 HTTP。
   - 飞书 tenant token 获取改为异步 HTTP。
   - Wiki node info、children、Docx blocks、Drive file download 改为异步 HTTP。
   - 复用同步服务已有的缓存、搜索 payload、搜索结果解析和打分逻辑。
2. 新增 `AsyncRagService`：
   - 权限范围和 Prompt 读取仍使用当前同步 DB session。
   - 飞书外部读取切到 `AsyncFeishuKnowledgeService`。
   - 兼容当前历史对话/摘要 prompt 签名，旧签名自动回退。
3. `ChatStreamService.stream_answer_async` 已切到 `AsyncRagService.build_result`。
4. 同步 `ChatStreamService.stream_answer` 保留不变，继续作为回退路径。
5. 飞书直读多知识库时增加并发上限，当前限制为最多 3 个知识库同时读取，降低触发飞书频控的概率。
6. 飞书部分知识库读取失败但已有可用片段时，降级使用可用片段继续回答；所有知识库均失败时才返回错误。

验证记录：

1. 本机 `compileall` 检查通过。
2. 容器内 `compileall` 检查通过。
3. 后端健康检查通过。
4. 第一次真实问答验证触发飞书 `frequency limit`，据此补充了飞书直读并发上限和部分失败降级策略。
5. 第二次真实 `/chat/completions` 验证通过：首个事件为 `generating`，随后返回 `content`，最后返回 `[DONE]`。
6. 真实会话历史验证通过：流式完成后用户消息和助手消息均已落库。

阶段限制：

1. DB session 仍是同步的，权限范围、Prompt 读取、消息落库还没有切到 async DB。
2. 当前缓存仍是进程内缓存，多 worker 下不会共享缓存。
3. 飞书直读并发上限是代码内默认值，后续可在系统配置中开放。

## 阶段 4 实施计划

目标：引入 Redis，让多 worker / 多实例部署时可以共享问答排队状态和飞书读取缓存。

阶段 4 分两步实施：

1. 阶段 4A：Redis 全局问答队列。
2. 阶段 4B：Redis 飞书共享缓存。

### 阶段 4A：Redis 全局问答队列

实施范围：

1. 增加 Redis 依赖和 `REDIS_URL` 配置。
2. dev compose 增加 Redis 服务，后端通过 `redis://redis:6379/0` 连接。
3. 新增 Redis 队列管理器，使用 Redis 记录：
   - 当前正在生成的请求 token。
   - 等待队列 token。
   - active token 的过期时间，避免 worker 崩溃后 active 计数永久泄漏。
4. `/chat/completions` 优先使用 Redis 队列；Redis 不可用时自动回退进程内队列。
5. SSE 事件协议保持不变，用户端无需改动。

风险控制：

1. Redis 队列必须保留进程内回退，避免 Redis 临时不可用时问答完全不可用。
2. active token 必须带 TTL；请求异常、客户端断开、worker 崩溃都不能让队列永久卡死。
3. 不修改已有 5 个未提交后端文件。

### 阶段 4B：Redis 飞书共享缓存

实施范围：

1. 飞书 tenant token、wiki node info、children、docx/file 文本内容接入 Redis 缓存。
2. 缓存 key 按应用凭证和资源 token 隔离。
3. Redis 不可用时自动回退进程内缓存。
4. 保留当前 5 分钟缓存 TTL，后续可在系统设置中开放。
5. 本次先接入用户端 async RAG 链路；同步旧链路保持不变，避免改动当前已有未提交的 `feishu_service.py`。

风险控制：

1. 不改变知识库召回排序和 Prompt 构建。
2. 不缓存用户问题、模型回答和用户隐私信息。
3. 不把飞书读取失败结果长时间缓存，避免权限/配置修复后仍命中错误缓存。
4. Redis 缓存读写失败时只降级，不阻断问答主流程。

## 阶段 4A 实施记录

2026-07-08 完成 Redis 全局问答队列第一版。

已完成：

1. 后端增加 Redis 依赖和 `REDIS_URL` 配置。
2. dev compose 增加 `redis` 服务，后端默认连接 `redis://redis:6379/0`。
3. 新增 `RedisChatQueueManager`：
   - 使用 Redis sorted set 保存 active 请求 token 和过期时间。
   - 使用 Redis list 保存等待队列 token。
   - 使用 Lua 脚本保证申请名额、入队、队首晋升等操作的原子性。
4. 新增 `chat_queue_runtime`：
   - Redis 可用时优先使用 Redis 全局队列。
   - Redis 不可用或运行时异常时，自动回退到原进程内队列。
5. active token 增加租约过期时间，默认 `chat_active_lease_seconds=900`，避免 worker 异常退出后永久占用并发名额。
6. 管理后台系统设置新增“问答执行租约（秒）”配置。
7. 用户端 SSE 协议未变化。

验证记录：

1. 本机 `compileall` 检查通过。
2. `git diff --check` 通过。
3. Docker dev 环境已新增并启动 Redis，Redis 健康检查通过。
4. 容器内 Redis 队列行为验证通过：第一个请求获得执行名额，第二个请求进入排队，第三个请求被拒绝，释放名额后第二个请求恢复执行。
5. 后端健康检查通过。
6. 真实 `/chat/completions` 验证通过：首个事件为 `generating`，随后返回 `content`，最后返回 `[DONE]`。
7. 真实会话历史验证通过：流式完成后用户消息和助手消息均已落库。

阶段限制：

1. 当前 Redis 队列使用轮询晋升等待请求，下一步可以结合 Pub/Sub 或 blocking pop 降低等待侧轮询。
2. Redis 飞书共享缓存还未接入，将在阶段 4B 完成。
3. 生产部署需要确认 Redis 持久化、内存上限、淘汰策略和监控告警。

## 阶段 4B 实施记录

2026-07-08 完成 Redis 飞书共享缓存第一版。

已完成：

1. 新增 `redis_cache_service`，提供 Redis 文本和 JSON 缓存读写 helper。
2. 用户端 async 飞书/RAG 链路已接入 Redis 缓存：
   - tenant token。
   - Wiki node info。
   - Wiki children。
   - Docx 文本内容。
   - Drive file 文本内容。
3. 缓存 key 按飞书应用凭证 hash 和资源 token 隔离。
4. Redis 不可用或缓存读写失败时自动降级，不阻断问答主流程。
5. 保留进程内缓存作为本进程内的一级缓存，Redis 作为跨 worker / 跨实例共享缓存。

验证记录：

1. 本机 `compileall` 检查通过。
2. `git diff --check` 通过。
3. 容器内 `compileall` 检查通过。
4. 容器内 Redis 文本和 JSON 缓存读写验证通过。
5. 后端健康检查通过。
6. 真实 `/chat/completions` 验证通过：首个事件为 `generating`，随后返回 `content`，最后返回 `[DONE]`。
7. 真实会话历史验证通过：流式完成后用户消息和助手消息均已落库。
8. 真实问答后 Redis 中已生成飞书缓存 key。

阶段限制：

1. 当前 Redis 缓存 TTL 仍复用进程内缓存的 5 分钟默认值。
2. 同步旧飞书链路暂未接入 Redis 缓存，用户端 async 问答链路已接入。
3. 后续可以在系统设置开放飞书缓存 TTL、缓存清理和单知识库刷新能力。

## 阶段 5 实施计划

目标：补齐生产部署时必须可调的 worker、数据库连接池和压测工具，方便后续基于数据调参。

实施范围：

1. 后端启动支持 `BACKEND_WORKERS` 环境变量。
2. SQLAlchemy 连接池支持环境变量配置：
   - `DB_POOL_SIZE`
   - `DB_MAX_OVERFLOW`
   - `DB_POOL_TIMEOUT`
   - `DB_POOL_RECYCLE`
3. `.env.example` 和 dev compose 补齐对应配置。
4. 新增一个轻量聊天压测脚本，用于并发请求 `/chat/completions`，输出成功数、错误数、首包耗时、总耗时。
5. 文档记录默认值和调参建议。

风险控制：

1. dev 环境默认仍使用 1 个 worker，避免本地调试时多 worker 日志和热更新混乱。
2. 生产可以通过环境变量调高 worker，不需要改代码。
3. 压测脚本只作为研发/验收工具，不进入应用启动链路。

## 阶段 5 实施记录

2026-07-08 完成 worker、连接池和压测工具第一版。

已完成：

1. 后端启动支持 `BACKEND_WORKERS` 环境变量。
2. Dockerfile 启动命令支持 `uvicorn --workers ${BACKEND_WORKERS:-1}`。
3. SQLAlchemy 连接池支持环境变量配置：
   - `DB_POOL_SIZE`
   - `DB_MAX_OVERFLOW`
   - `DB_POOL_TIMEOUT`
   - `DB_POOL_RECYCLE`
4. `.env.example` 和 dev compose 已补齐对应配置。
5. 新增 `scripts/chat_load_test.py`，支持并发请求 `/chat/completions` 并输出：
   - 单请求结果。
   - `sessionId`。
   - 首事件耗时。
   - 总耗时。
   - 成功数和失败数汇总。
6. `/chat/completions` 增加后端异常日志，用户端仍保持通用错误提示，便于压测时查堆栈。

验证记录：

1. 本机 `compileall` 检查通过。
2. 压测脚本 `--help` 检查通过。
3. `git diff --check` 通过。
4. 后端镜像重建通过。
5. 后端健康检查通过。
6. 单请求压测通过：1 个请求成功，首事件约 20ms，总耗时约 11.66s。
7. 2 并发、2 请求压测暴露当前模型链路风险：两次复测均出现 1 成功、1 失败，失败请求在约 60s 返回“AI 回复生成失败”。该现象更像当前模型配置或上游模型并发/超时限制，需要后续结合后端异常日志和模型管理配置继续调参。

阶段限制：

1. 当前没有做大并发压测；阶段 5 只补齐调参能力和轻量验证脚本。
2. 生产 worker 数不能只看 CPU，需要结合模型接口限流、飞书频控、DB 连接数和 Redis 队列等待时间一起定。
3. 当前建议先把 `chat_max_active_requests` 调低到当前模型真实可承受范围，再逐步放大压测。
