-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Description
例行检查
- 我已确认目前没有类似 issue
- 我已完整查看过项目 README,以及项目文档
- 我使用了自己的 key,并确认我的 key 是可正常使用的
- 我理解并愿意跟进此 issue,协助测试和提供反馈
- 我理解并认可上述内容,并理解项目维护者精力有限,不遵循规则的 issue 可能会被无视或直接关闭
你的版本
- 公有云版本
- 私有部署版本, 具体版本号: V4.9.4
- 部署方式:docker-compose 单实例部署(FastGPT 仅 1 个实例)
- MongoDB 版本:5.0.18
- Mongo 连接方式:本地 docker-compose 中的 Mongo 服务(无分片、无复制集)
- Mongo 连接串参数:无特殊参数(无显式设置 maxPoolSize 等,如果需要我可以补充)
问题描述, 日志截图,配置文件等
问题现象:
在 同一个对话会话(同一个 chatId)较短时间内收到两条消息 时,FastGPT 更新会话历史(chats 集合)时会触发 MongoDB 的 WriteConflict,导致接口报错,前端 / 调用方拿到错误响应。
FastGPT 日志示例(docker-compose 部署环境):
[Warn] 2025-11-25 16:21:07 Request finish /api/v1/chat/completions, time: 72454ms
[Error] 2025-11-25 16:21:07 update chat history error
{
message: 'WriteConflict error: this operation conflicted with another operation. Please retry your operation or multi-document transaction.',
stack: 'MongoServerError: WriteConflict error: this operation conflicted with another operation. Please retry your operation or multi-document transaction.\n' +
' at O.sendCommand (/app/projects/app/.next/server/chunks/50290.js:4:65866)\n' +
' at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n' +
' at async O.command (/app/projects/app/.next/server/chunks/50290.js:4:66485)\n' +
' at async y.command (/app/projects/app/.next/server/chunks/50290.js:5:85007)\n' +
' at async a.executeCommand (/app/projects/app/.next/server/chunks/50290.js:5:26534)\n' +
' at async a.execute (/app/projects/app/.next/server/chunks/50290.js:5:61566)\n' +
' at async a.execute (/app/projects/app/.next/server/chunks/50290.js:5:61852)\n' +
' at async d (/app/projects/app/.next/server/chunks/50290.js:5:37622)\n' +
' at async h (/app/projects/app/.next/server/chunks/50290.js:5:35598)\n' +
' at async $.updateOne (/app/projects/app/.next/server/chunks/50290.js:4:105165)'
}
MongoDB 日志中在对应时间点附近,可以看到连接数短时间内增加,以及比较长耗时的事务写入(示例为脱敏后的片段):
{"t":{"$date":"2025-11-25T16:21:02.648+00:00"},"s":"I","c":"NETWORK","id":22943,"ctx":"listener",
"msg":"Connection accepted",
"attr":{
"remote":"192.168.0.2:55390",
"connectionId":57679,
"connectionCount":47
}}
{"t":{"$date":"2025-11-25T16:21:02.670+00:00"},"s":"I","c":"TXN","id":51802,"ctx":"conn57655",
"msg":"transaction",
"attr":{
"parameters":{
"lsid":{"id":{"$uuid":"4710d7b0-a6d3-4795-bbdd-fc40360494f2"}},
"txnNumber":2,
"autocommit":false,
"readConcern":{"level":"local"}
},
"ninserted":2,
"keysInserted":11,
"terminationCause":"committed",
"durationMillis":8734
}}- 触发冲突的对象是
chats集合中某个会话文档(含variables.historyList等字段)。当同一个会话在短时间内有多条消息 / 多次重试时,会同时对这条文档进行更新; - MongoDB 侧并没有抛出其他错误,只是正常的文档级
WriteConflict。目前 FastGPT 对WriteConflict没有自动重试机制,错误直接抛到了上层。
我的理解是:同一会话在短时间内存在“并发写同一条 chats 文档”的情况(例如 historyList 的追加),导致 Mongo 返回 WriteConflict。在单实例 FastGPT 环境下,这种冲突应该可以通过应用层串行化 / 重试来避免对用户的直接影响。
如果需要,我可以提供更完整的 Mongo 日志片段和 chats 文档结构(脱敏后)供分析。
复现步骤
目前我这边的复现方式大致如下(在 V4.9.4、docker-compose、Mongo 5.0.18 环境):
-
启动单实例 FastGPT(docker-compose),连接本地 Mongo 5.0.18;
-
创建一个应用 / 对话机器人,使用默认的会话存储方式(
chats+chatitems),历史上下文配置使用默认值或较大的轮数; -
打开同一个对话(同一个 chatId),在短时间内对这个会话发送多条消息:
- 比如第一条提问还在处理中(还没完全返回 / history 写入还没结束)的时候,再快速点击发送第二条消息;
- 或在回答过程中多次点击“重试 / 重新生成”;
-
在某些情况下,请求会在几十秒后报错(例如
Request finish /api/v1/chat/completions, time: 72454ms这样较长处理时间),同时后端日志出现:[Error] update chat history error MongoServerError: WriteConflict error: this operation conflicted with another operation... -
对应时间点在 MongoDB 日志中也可看到相关的写事务和连接活动。
(注:目前复现并不是 100% 稳定,但在“同一会话快速连续发送 / 重试”的情况下,偶尔会出现上述报错。)
预期结果
- 在同一个会话(同一个 chatId)存在并发写入时,希望 FastGPT 能够通过合理的并发控制或重试机制,避免
WriteConflict直接暴露给最终用户; - 建议:
- 服务端对单个
chatId的会话更新做串行化处理,避免同时对同一条chats文档进行写操作; - 在写
chats(或相关会话文档)时,对 MongoDB 的WriteConflict进行有限次数的自动重试(带简单退避),而不是直接抛出; - 或基于 version 字段 / updatedAt 做乐观锁与幂等更新,确保会话更新在并发情况下可恢复、可重试。
- 服务端对单个