11 KiB
单机动态在线 Worker
范围与入口
管理员「设置 → 执行节点管理」配置 SSH 主机/IP、端口、账号、密码、SSH 主机指纹、源容器、Docker 网络、镜像内 Python/后端目录、节点数量、并发、队列和资源预算。也支持已有 Docker socket 挂载的本机连接,无需填写 SSH 密码。
本实现将 /api/threads/{id}/runs、runs/stream、runs/wait 的普通/智能体问答分发到固定会话所属的在线 Worker。分配后,该会话的状态、历史、停止、重连等 /api/threads/{id}/… 请求也转发到同一节点。鉴权及原有任务共享、用户隔离检查仍然执行。搜索、计数和未启用时沿用主服务。
定时任务、任务分析、研究、会商、工作流以及系统内部会话仍由唯一主服务执行;不在在线 Worker 启动它们的扫描、恢复或调度循环。无状态 /api/runs/*、专用写作接口等未纳入在线池。后台任务池尚未实现,不应将此版本描述为全业务分布式任务队列。
存储与并发
- 业务库与聊天存储独立:保留 MySQL/PostgreSQL 业务库,聊天存储支持 PostgreSQL 或 SQLite。SQLite 必须使用同机共享持久目录(不能单文件挂载或网络文件系统),开启 WAL、30 秒锁等待及跨进程初始化锁;内存存储拒绝开启。
- Worker 的运行事件使用共享业务数据库;聊天检查点沿用已有 PG/SQLite 配置,不迁移聊天记录。
- 控制器私有目录保存加密 SSH 凭证、加密密钥、实例标识和 SQLite 会话归属表。该表只保存路由,不存聊天正文。目录必须独立持久化,不能挂载给 Worker。实例标识和归属表不能单独删除或在旧容器运行时重建。
- Worker 池默认关闭。关闭时不启动控制器轮询、不申请单实例锁、不连接 Docker/SSH,也不创建亲和性或诊断数据库;原部署方式与多进程服务按原样运行。只有管理员启用 Worker 池后,控制器才申请单实例锁并开始管理容器;启用期间主服务需使用单个 Uvicorn 进程。同机同套部署的启用中主服务必须共用控制器卷。
- 执行额度绑定真实运行 Task 的生命周期;HTTP 请求结束或后台返回不提前释放额度。排队有数量和时间上限;超限返回 429/Retry-After。
- 每节点业务库连接池不允许额外溢出;检查点和 LangGraph Store 各有单独的 PG 连接池。系统按
节点数 ×(业务库池大小 + 2 × PG 池大小)校验 Worker 连接预算。该预算须预先扣除主服务及其他应用的连接额度。 - Worker 在新运行开始前检查共享技能扩展配置,启停变更会刷新本进程缓存;技能文件变更按最多五秒的检查间隔刷新目录提示。CPU、模型配置等需要重启的配置仍应先排空 Worker 后更新。
- 会话归属在扩容后保持。缩容节点停止接收新运行,等待执行、排队和代理请求结束后停止,再释放归属。不自动重放失败请求。节点失联时返回 503;可确认进程停止后才允许后续重新分配。
- 重启后的旧运行读取为中断错误,不自动重试带外部副作用的工具。系统保留存储中已完成的检查点,不能承诺从任意工具执行位置无损恢复。
部署要求
发布仓库 deerflow-offline-deployment 已为标准模板增加控制器独立卷和 SSH/加密依赖清单。必须按该仓库既有流程构建包含全部依赖的离线包并部署新前后端源码。
- Worker 池关闭时保留原部署进程数即可;启用 Worker 池后主容器使用单个 Uvicorn 进程。固定
AUTH_JWT_SECRET必须在容器环境变量中。 - 使用用户自定义 Docker 网络,主容器和新 Worker 均在该网络。数据库地址不能指向容器自身的
localhost。 - 挂载全部运行目录、上传文件、技能、配置及必要的源码覆盖目录。Worker 复用其挂载,保留 ExtraHosts/DNS;不继承宿主机端口、Docker socket或特权模式。
DEER_FLOW_WORKER_CONTROL_HOME指向独立持久卷,如/var/lib/deerflow-worker-control。该卷会被自动排除,不传给 Worker;控制目录嵌在其他共享卷内时拒绝创建。- 当前支持不依赖 Docker socket 的执行沙箱。若业务配置需要 Worker 自行创建 Docker 沙箱,须先接入独立受控沙箱服务,不得直接复制 socket 权限。
- 设置中默认保持关闭;填写连接参数和测试连接不会启动容器。管理员明确开启后才创建 Worker。标准离线镜像 Python 为
/opt/venv/bin/python,工作目录为/app/backend;其他镜像按实际路径填写。 - SSH 主机指纹可在页面读取并由管理员确认;账号需具备运行 Docker 的权限。不接受未知指纹,也不自动安装服务器软件。
容器使用源容器的精确镜像 ID,执行源码覆盖挂载与主容器相同。升级前数量设为 0,等待节点退出后升级主服务,再恢复数量;不会自动替换仍在执行的旧容器。
验证与容量
tests/test_worker_pool.py 包含凭证脱敏、模板限制、排队取消/超时、后台任务额度、归属持久化、失联不重放、缩容等待、双主进程拒绝、管理员授权,以及 70 个 HTTP 客户端分配到四个模拟 Worker 并返回 SSE 的回归。
这些是功能与模拟并发测试,不等同于真实模型、PostgreSQL、Docker 和服务器硬件的 70 人容量验收。部署后应在测试环境同时运行普通问答、文件工具和定时任务,观察首字延迟、完成时间、数据库连接数、模型限流和资源峰值;执行中的关闭浏览器、停止生成、节点重启、缩容都要验证。每节点并发数乘以节点数只是顶层运行上限,工具/子智能体仍可能产生额外模型调用,应配置模型服务总额度。
回退:将期望数量改为 0,等待全部节点消失后关闭池。主服务重新处理普通问答,聊天记录和运行目录继续保留。节点不能正常退出时不要直接删除控制器卷或归属表。
本次开发验证(2026-10-23)
- Worker 专项、账户鉴权、运行记录回收、执行线程池、完成超时和运行争用相关回归合计 136 项通过。
- 70 个模拟 HTTP 客户端进入四个模拟执行节点,分配为 18 / 18 / 17 / 17,全部收到 SSE 结束事件;另测执行额度、超时、取消及后台运行不提前释放额度。这不包含真实模型耗时。
- Python 静态检查、编译检查、改动空白检查通过;Linux 离线发布配置生成/校验通过。
- 新增前端页面及设置入口语法检查通过。全量 TypeScript 检查仍有其他模块错误,不能将前端全量检查标记为通过。
- 119 服务器检测为 32 核 CPU、128806 MB 内存;8008 实例已启动 4 个实际 Docker Worker,每节点 2 CPU / 2048 MB / 4 个同时执行额度;业务库保持 MySQL,既有聊天 SQLite 配置不变。
- 实际模型短问答:同一管理员下 70 个独立会话同时发起,70/70 完成,流式阶段约 59.59 秒;随后 70/70 历史记录读取确认回答已保存。这是短问答突发负载,不代表 70 个不同用户的复杂工具任务容量。
- Linux 上分别用 SQLite 和 PostgreSQL 执行 4 个进程各 25 次检查点/写入/Store 读写验证,各 100 次成功;PG 使用独立验收实例,未迁移业务库。
- 4→0→4 缩扩容与主服务重启后发现原有 4 个节点已验证(未重启整台服务器)。Worker 不启动定时任务调度器。
- 新增服务器探测和资源推荐:页面先读取 SSH 指纹,管理员确认后才发送密码登录;检测 Docker CPU/内存总量和其他容器资源上限,保留至少半台服务器资源,建议最多 4 个起步节点。不是实时空闲内存测量。
- 密码经 Fernet 加密保存在控制器持久卷;页面/API 不返回密码。更换服务器身份后必须重新填写密码,不能复用原服务器密码。配置和密钥卷需一起保留。
- Worker/聊天存储/跨线程数据库/资源推荐专项回归 37 项通过。
管理页面验收补充
2026-10-23 23:06 在 119:8008 实际页面完成保存并应用、测试已保存连接、读取服务器资源,三个请求均成功。截取资源推荐与四个就绪节点页面,保存在本次 .runtime/worker-deploy-119/ 验收目录。前端生产构建成功。
当前运行池使用本机 Docker Socket。SSH 指纹读取已在服务器内网地址实测;SSH 账号密码认证尚需管理员在页面填写实际凭证验证。密码密文持久化、读取不回显、更换主机不复用密码、错误指纹拒绝连接均有测试覆盖。重启验证指主服务重启,未重启宿主机。
服务器诊断与并发验收补充(2026-10-24)
管理员诊断页 /page/workspace/admin/server-diagnostics 提供按开关采集的宿主机资源、MySQL/PG 连接、HTTP/SSE 分段耗时、主容器和 Worker 状态、日志读取与归档。主后端挂载 Docker Socket 和只读 /proc、/sys,Worker 不继承这些挂载。主服务日志轮转为 20 MB × 5,Worker 为 10 MB × 3;节点删除前保存有界日志归档。采样和请求摘要保存在控制器私有卷,接口不记录聊天正文、查询参数或鉴权头。
修复 Worker 执行队列阻塞流首次连接:先注册真实运行、建立流,再等待执行额度;保留额度上限和取消、超时语义。新线程默认只写元数据,首次运行再初始化检查点,保留显式初始化兼容参数;历史查询缩短 SQLite 游标持有时间。
本轮相关回归 133 项通过。119 实际 2 节点、4 节点各执行 70 路冷启动和 70 路第二轮,共 280/280 成功,两组各 70 个会话历史和状态回读通过。4 节点冷/热整轮耗时 68.851/46.287 秒,响应头 P95 为 18.141/11.548 秒;2 节点冷/热整轮耗时 115.026/74.151 秒。此为同一管理员的独立客户端短问答,不代表复杂工具容量。验收后恢复原先保存的 2 个节点。
页面实际验证了采集开关、资源和数据库卡片、主服务/Worker/归档日志,浏览器无脚本错误。119 当时 CPU 100%,独立采样 steal 约 24.6%,内存和 MySQL 连接仍有余量;需同时排查宿主机 CPU 争抢。PG/SQLite 兼容性在独立实例验证,业务 MySQL 和原聊天配置不变。
Linux AMD64/Python 3.12 增量交付包和部署说明保存在离线发版仓库;文档 deploy/linux-docker-offline-deerflow-only/docs/14-Worker池与服务器诊断更新部署.md 包含 Docker Socket 挂载、更新排空、依赖、资源建议和回退。交付源代码基于本次 119 验收版本,配置与数据不打入包。