跳转至

阶段十三:OmniRoute latest stable 原生迁移

计划 ID:phase-13-omniroute-latest-stable-migration

阶段状态:已完成并归档

计划状态:已完成

当前工作包:无;P13-6 已完成并归档

权威边界:本文件是 P13 的唯一正式计划入口。P12 已完成 102 节点纳管并归档;P13-0 至 P13-4 已完成,P13-B 已把公网入口直接切到 102,P13-C 已按用户决定取消观察等待期并删除 RR 上的 omni 数据、包、unit 与备份。102 上的官方 omniroute@3.8.51 是唯一生产权威和唯一 SQLite 写者;RR 不再保留回退点,恢复改为从 Cloudreve P13-4 快照恢复或在 102 重装。

📌 结论摘要

2026-10-01 已执行 P13-4 受控切换:RR 在切换时刻停止本地 OmniRoute 写入、生成最终备份与一致性快照,102 恢复该快照后启动 3.8.51;RR 的 2 处公网回源和 Runtime 私有代理均已切到 100.64.0.4:39200。随后 P13-B 把 MM 公网入口改为直连 102,避免继续经过 RR 共用回源网关;公网 health、模型目录、Boss/Worker Combo、Codex Responses SSE/tools、管理 API、SQLite 回读和负向鉴权均通过。依据是 RR/102/MM 现场命令输出、Cloudreve 哈希回读和 计划历史;影响是生产模型核心权威已从 RR 3.8.50 转为 102 3.8.51。

迁移还完成了一次真实回退与再次切换闭环:102 停止写入并生成清洁快照,RR 恢复该快照并执行 rollback,RR 本地服务恢复、真实调用返回精确成功文本;随后 RR 再次 freeze、生成回流快照,102 恢复并重新 activate。整个流程证明 RR 回退点可用,且最终只有一个 SQLite 写者。依据是最终快照路径、大小、SHA-256 和两轮 health/真实调用记录;影响是 P13-5 可以观察 102 稳定性,而不必重新讨论迁移是否可行。

现场发现并修复了两个会破坏长期可重复性的缺陷:102 缺少 sqlite3 会让官方快照退化为“主库 + WAL 复制”,RR systemd 255 未按预期通过 drop-in 空赋值清除 Runtime 代理对本机 OmniRoute 的依赖。前者已在部署脚本增加 sqlite3 预检并用 VACUUM INTO 做负向回归;后者已通过包外 unit 的精确两行改写、原始备份和依赖回读修复。依据是脚本版本、哈希、快照文件和 systemd 输出;影响是干净节点重装和后续回退不会再依赖人工记忆。

进入 P13-5 后又发现并修复了第三个生产缺陷:102 edge 代理的 FD 软上限仍为 1024,在长期连接累积后出现 Too many open files,导致 RR 与公网入口超时。修复脚本已升为 v0.1.2,显式设置 LimitNOFILE=65536:65536、--connections-max=4096 和失败重启,并把 FD 上限纳入 check;修复后 RR 私有入口与公网 health 均恢复 200。依据是 102 journal、进程 FD 计数、RR→102 探测和公网回归;影响是同类连接耗尽不会再只表现为“服务 active 但转发失效”。

P13-C 已取消观察等待期并完成 RR omni 全量退役:RR 上不再存在 /root/.omniroute、3.8.50 全局包、旧 service unit、cutover 备份和 omni vhost;RR 仅保留正在被本机 AI Runtime 容器使用的 172.30.70.1:39181 → 100.64.0.4:39200 私有代理,以及 RR Codex 使用的 MCP 凭据。原 P13-5 相位观察器已迁移为无阶段阻塞含义的健康观察器,继续每 15 分钟只读检查 102 生产、公网入口和 RR 退役边界。

P13 已完成最终验收、文档状态同步和 Git/CI 门禁;完整归档见 completed-phase-13-omniroute-latest-stable-migration.md。本页保留全部执行细节与稳定 URL,不再代表当前工作包。

🗂️ 目录

🧾 计划状态

项目 当前值 依据
当前阶段 已归档,后续为 P14 需求评审占位 docs/plans/state.json
阶段状态 已完成并归档 迁移、公网直连、RR 全量退役和最终门禁均已完成
计划状态 已完成 工作包、依赖、验收和回退均已冻结
当前工作包 无;P13-6 已完成并归档 后续状态变化作为新运维事件或新阶段处理
生产权威 102 官方 omniroute@3.8.51 MM 公网入口与 RR Runtime 私有代理均指向 100.64.0.4:39200
回退点 已退役 用户决定不再保留 RR 回退点;恢复以 Cloudreve P13-4 快照和 102 原生重装为准
公网入口 MM 仍为唯一 80/443 入口 MM omni.yohan.fun.conf 已改为直连 proxy_pass http://100.64.0.4:39200;(P13-B)
数据写者 仅 102 RR omni 服务、数据和包已删除,102 为唯一 SQLite 写者
健康观察器 101 每 15 分钟只读检查 102、RR 退役边界和公网 agentmeshos-omniroute-health-observation.timer

P13-0 至 P13-4 的状态如下:

工作包 状态 完成口径
P13-0 版本与回退冻结 已完成 官方 Node、npm latest、integrity、shasum、unpackedSize、Release 与 CHANGELOG 已固定
P13-1 102 一次性安装 已完成 直接安装 Node 22.23.0 与 OmniRoute 3.8.51,没有旧版中间态
P13-2 隔离恢复 已完成 从 RR 官方备份与一致性快照恢复,完成数据计数、解密、健康与 schema 核对
P13-3 切换剧本冻结 已完成 102 私有入口、RR freeze/activate/rollback、停写与哈希流程已实做
P13-4 受控切换与验收 已完成 最终快照、生产切换、全链路验收、回退演练、再次切换和文档化修复均通过
P13-5 稳定性观察 已取消等待期 用户明确取消观察等待期;长期健康检查迁移为 P13-6 的非阻塞观察器
P13-6 RR 全量退役与阶段收口 已完成并归档 RR omni 全部删除、入口与脚本统一、最终验收和归档门禁全部通过

🎯 目标、成果与验收契约

本阶段的目标是把生产 OmniRoute 从 RR 旧版本迁移到 102 官方最新稳定版,同时保持 MM、公网入口和 Runtime 调用面稳定。最终验收契约为:102 成为唯一生产写者;MM 公网入口直连 102;RR omni 数据和包全部退出;RR 仅保留本机容器所需的 Runtime 私有代理;恢复以 Cloudreve 快照和 102 原生重装为准。

项目 切换前 切换后当前值 证据
生产版本 RR 3.8.50 102 3.8.51 102 CLI 与 systemd 运行态
RR 公网上游 2 处 127.0.0.1:39180 2 处 100.64.0.4:39200;P13-B 后 MM 不再经此入口 agentmeshos-origin-gateway.conf
RR Runtime 代理 127.0.0.1:39180 100.64.0.4:39200 agentmeshos-omniroute-runtime-proxy.service.d/upstream-p13.conf
RR 本地 OmniRoute active 数据、包和 unit 已删除(P13-C) RR 路径存在性检查与 nginx -T
MM 回源 100.64.0.1:39200 P13-B 改为直连 100.64.0.4:39200 /www/server/panel/vhost/nginx/omni.yohan.fun.conf
公网 health RR 本地 102 直连(MM → 102) https://omni.yohan.fun/api/monitoring/health 返回 200
102 数据计数 隔离副本 70 连接、19 Combo、4 API Key、迁移 193 102 SQLite 只读查询

结论是:公网用户、Runtime 和现有调用方的最终后端都是 102 3.8.51。P13-4 把 RR 的最终上游从本机 3.8.50 换成 102;P13-B 进一步把 MM 公网入口从“经 RR 私有网关”改成“直连 102 私有入口”;P13-C 删除 RR 的全部 omni 数据和包,只保留 RR 本机 AI Runtime 容器正在使用的私有代理。

🌐 P13-B:公网入口直连 102,RR 退出 omni 路径

动机:RR 的 100.64.0.1:39200 是 *.yohan.fun 的共用回源网关,按域名分流到 8 个后端,其中 7 个后端就在 RR 本机,只有 omni 已被迁到 102。omni 直连 102 可以摘掉一个失败域(RR)并缩短排查链路,代价是 MM 需要为 omni 单独记住一个后端地址。

改动:MM 有两个存储必须同时改。第一是宝塔面板的反代配置源 /www/server/proxy_project/sites/omni.yohan.fun/omni.yohan.fun.json,面板列表和目标保存都以它为准;第二是渲染出来的 nginx 配置 /www/server/panel/vhost/nginx/omni.yohan.fun.conf。两处的 proxy_pass 都由 http://100.64.0.1:39200 改为 http://100.64.0.4:39200,并在面板 server_block 与 nginx 配置补齐 location = /、location = /dashboard(302 到 /login)和 location = /login(保留 auth_token 已存在时 302 到 /home 的规范化)。改动前按时间戳备份到 MM /root/omni-conf-backups/,nginx -t 通过后 reload。102 私有入口的放行来源本就是 100.64.0.1(RR)与 100.64.0.6(MM),因此直连无需改 102 防火墙。

失败教训(必须记住):第一次只改了渲染 conf,没改面板 JSON。结果是 nginx 运行态已经直连 102,但面板仍显示 100.64.0.1:39200,而且任何人从面板点保存都会按 JSON 把 conf 回写成 100.64.0.1。判据是面板 JSON 与渲染 conf 出现分歧;结论是凡经宝塔面板管理的反代,改目标必须同时改面板 JSON 与渲染 conf,并以「面板显示值 + conf 值 + 运行态 + 抓包来源」四项一致作为完成口径。

验证:公网 https://omni.yohan.fun/api/monitoring/health 返回 200、/ 返回 302 → /login、/login 返回 200;并发打公网时在 102 实时抓到 100.64.0.4:39200 ← 100.64.0.6(MM)的连接(48 个样本全部来自 MM,RR 为 0),证明公网已直连 102,不再经 RR。

回退边界更正:P13-B 之后,公网回退不再由 RR origin gateway 决定,而由 MM 面板 JSON + 渲染 conf 决定。P13-C 已删除 RR cutover 脚本,因为 RR 本地 OmniRoute 与 omni vhost 都已不存在;任何未来公网切换必须在 MM 两处配置中显式完成,不能恢复已退役脚本。

RR 清理:P13-B 先清除了 Gemini Web 补丁文件与 .omniroute-patches、PR14787 实验目录、VNC 实验目录、omni 镜像测试目录、已退役 discovery 的 unit 与 /opt、/etc 配置;P13-C 随后按用户决定删除 OmniRoute 数据、包、unit、cutover 备份与网关 vhost。RR 的 Runtime 私有代理继续保留,因为本机 AI Runtime 容器通过 172.30.70.1:39181 访问 102。

🧹 P13-C:RR omni 全量退役与入口统一

用户决定取消 P13-5 观察等待期,直接删除 RR 上全部 omni 物料。本段记录删除范围、保留项与保留理由,供后续审计。

删除:/root/.omniroute(2.1G)、/usr/lib/node_modules/omniroute(3.8.50,2.7G)、/etc/systemd/system/agentmeshos-omniroute.service 与 .d、/root/.omniroute-cutover-backups、/root/omniroute-*、/etc/agentmeshos/omniroute-core、/etc/agentmeshos/nginx-tailnet/agentmeshos-origin-gateway.conf*、/backup/agentmeshos/omniroute-*(含 discovery 与历史备份)、RR 侧 /root/agentmeshos-omniroute-cutover.sh。删除前在该备份盘留下清单与小组件归档。

保留项 保留理由(已实测)
RR agentmeshos-omniroute-runtime-proxy.service/.socket(172.30.70.1:39181 → 100.64.0.4:39200) 不是残留。RR 本机 agentmeshos-ai-runtime 容器的 AI_RUNTIME_OMNIROUTE_BASE_URL=http://172.30.70.1:39181 正在使用它;同机 39120、39184 也用同一 172.30.70.1 网关模式。容器经代理与直连 102 实测都返回 200,选择代理是因为它让容器不硬编码 Tailnet IP、后端再迁移时无需重建容器,更灵活也更一致
/var/lib/agentmeshos/swap/omniroute-install.swap(4G) 不是 omni 数据,是 active swap;RR 仅 3.8G 内存、swap 已用约 895M,删除会降低 swap 余量
RR /root/.codex/credentials/omniroute-mcp.env 与 /root/.codex/bin/omniroute-mcp-headers.sh RR 本机 Codex 通过 https://omni.yohan.fun/api/mcp/stream 调用 MCP,需要该凭据

脚本与入口统一:agentmeshos-main-origin-gateway.sh 升 v0.6.2,删除 omni server 块与 OMNIROUTE_UPSTREAM/OMNIROUTE_DISCOVERY_UPSTREAM 变量,RR 网关不再生成 omni vhost;agentmeshos-omniroute-cutover.sh 退役删除,因为 RR 本地 OmniRoute 与 RR 网关 omni 都已不存在,其 freeze/activate/rollback 已无对象,公网回退改由 MM 侧决定。

验证:RR nginx -T 中 server_name omni.yohan.fun 计数为 0;RR 网关上其余 7 个域名 docs/status/api/auth/nomad/console/mesh 全部 200/302;公网 omni health 200;RR 容器经 172.30.70.1:39181 返回 200;RR systemctl --failed 为 0;RR 根盘用量从 41G 降到 35G。

审计与影响:退役清单和小组件归档在 101 备份盘 /srv/codex-hub-backup/agentmeshos/omniroute-rr-retire-20261001T022315Z/,tar SHA-256 为 b4b4072cdd57477e64232f05411eb54de1ca1096a88720a6799737b7de4039c0。从此 RR 不再有回退点,102 故障的恢复方式变为从 Cloudreve 的 P13-4 快照恢复或在 102 重装,而不再是切回 RR。

📊 当前事实与版本差异

3.8.51 是在 P13-0 执行时重新查询到的官方 npm latest,不是把旧版本先装上再升级。下表用于说明与上一生产版本 3.8.50 的主要变化方向;具体使用仍以真实 Smoke 和权限边界为准。

变化方向 主要变化 对 AgentMeshOS 的影响 当前使用口径
路由与稳定性 分层并发准入、自适应推理强度、Provider 断路器、冷却与 429 判断修正 改善长 Responses、Worker 并发、Combo 故障切换 已随迁移启用;继续观察真实错误率
Provider 与模型目录 模型 allowlist/denylist、账号实时目录、模型别名扩充 降低目录漂移并支持更细粒度可见性 已启用现有正式目录,不因升级全量开放
Free tier 与 Radar 免费资格、isFree、限速展示和训练提示 影响免费 Combo 和额度解释 继续受“零成本优先”和隐私规则约束
可观测性 编排图、历史对比、Repeat、日志导出、首包耗时和 MCP 时间线 提升 Console 与故障复盘能力 只读验证后采用,日志正文导出默认关闭
安全加固 请求钩子隔离、IP allow/deny、内网端点拒绝、OAuth 路由保护、常量时间比较、路径穿越防护 直接影响管理面、反代和 Responses 子路径 已做未授权、错误 Token、路径穿越负向回归
媒体与上下文压缩 Video/Audio Bridge、STT、压缩线程池、可选语义缓存 对多模态和长上下文有潜在价值 暂不默认启用,后续单项评估资源与隐私
数据与迁移 schema 收敛、懒建表迁移、迁移数量与运行目录变化 影响备份恢复和版本升级 已通过最终快照恢复、quick_check 和迁移计数验证

后续使用优先级固定为:现有 Boss/Worker Combo 与 Chat Completions 第一优先;Codex Responses SSE/tools 第一优先但继续做真实回归;管理 API 和可观测性只读能力第二优先;媒体、语义缓存、日志正文导出和训练相关能力第三优先且默认关闭。

🧱 技术栈与架构选型

选型面 最终选择 选择依据 未采用方案及原因
OmniRoute 运行方式 102 官方 npm 原生安装 3.8.51 + systemd 满足用户要求的“一次性安装最新版”,不修改官方包内容;运行版本、Node 22.23.0 和 health 均有现场证据 先装旧版再升级会增加一次无必要迁移;容器迁移会改变既有宿主边界,均不采用
数据权威 102 /root/.omniroute/storage.sqlite 唯一写者 RR 最终快照恢复到 102 后,SQLite quick_check=ok,并验证 70 条连接、19 个 Combo、4 个 API Key、迁移 193 不让 RR 与 102 双写,也不手工拼接数据库;避免迁移后出现分叉或不可判定数据
公网与 Runtime 入口 MM 直连 100.64.0.4:39200,RR Runtime 私有代理也指向 102 公网不再经过 RR,RR 本机容器继续使用稳定的 172.30.70.1:39181 本地入口 不在 102 暴露公网监听,也不让容器硬编码 Tailnet IP
102 私有入口 agentmeshos-omniroute-edge.socket 监听 100.64.0.4:39200,经 raw PREROUTING guard 放行 RR 与 MM 仅允许管理链路访问,101 负向连接超时;RR 与 MM 正向访问返回 200 不开放公网监听,也不把数据库或管理端点直接暴露到 Tailnet 范围
恢复边界 Cloudreve P13-4 快照与 102 原生重装流程 回退演练已真实执行,证明切换前恢复路径可行;用户随后要求取消等待期并删除 RR 回退点 不在 RR 恢复第二写者,也不把旧 RR 路径重新当作生产入口
交付与复盘 官方备份、一致性快照、Cloudreve 哈希回读、仓库计划和脚本版本化 需要同时保留数据恢复点和可审计执行路径 不以单次 health 200 或手工命令记录代替完整验收证据

结论是:迁移采用“官方最新版一次性安装、单写者数据切换、公网直连 102、RR 全量退役”的架构。依据是 102、RR、MM 的现场运行态以及本页验收表;影响是后续只保留无阶段阻塞的健康观察,不再恢复 RR 回退路径。

🛠️ 工作包与依赖

工作包 前置依赖 完成证据 失败边界
P13-0 版本冻结 官方 npm/GitHub 可读 版本、integrity、shasum、unpackedSize、Node engines、CHANGELOG 任一漂移则停止安装
P13-1 102 安装 Node 22.23.0、目标版本明确 CLI、systemd、loopback 与 health 不允许先装旧版或修改包内容
P13-2 隔离恢复 RR 有可读官方备份和一致性快照 计数、解密、迁移、quick_check、service 出现双写或数据不一致即停止
P13-3 切换剧本 102 私有入口可用,RR 可停写 freeze、上游重写、drop-in、rollback 路径 写入者未停止时禁止 activate
P13-4 生产切换 维护窗口、最终快照、最终恢复 公网 health、模型、Combo、Responses、管理 API、SQLite、负向回归、回退与再次切换 任一必需链路失败即回退 RR
P13-5 稳定性观察 用户取消等待期 保留观察记录作为审计,但不把固定时长的 24 小时观察继续作为关闭前置 长期健康观察迁移为 P13-6 的独立运维能力
P13-6 RR 全量退役与阶段收口 P13-C 已删除 RR omni 物料 RR 路径不存在、Runtime 代理指向 102、公网 health、102 health、文档与脚本一致、全套 CI 通过 任一当前生产链路失败或文档/脚本仍依赖 RR 回退点时不得关闭

📍 执行位置与阶段关系

位置 当前职责 禁止事项
101 仓库、Git、CI、验收编排、哈希和文档同步 不运行第二套生产 OmniRoute
RR 其他 7 个业务域名的共用回源网关、Runtime 私有代理、宿主机运维 不再有 omni 数据、包、service、vhost 或 cutover 回退点
102 当前唯一生产 OmniRoute、SQLite 写者、Provider/Combo/模型权威 不允许第二写者;不绕过官方包内容边界
MM 唯一公网 80/443 入口,omni 直连 102 面板 JSON 与渲染 conf 必须同步修改,不能只改渲染文件
Runtime 通过 RR 私有代理调用 102 不保存第二套 Provider 路由或凭据

102 私有入口为 agentmeshos-omniroute-edge.socket 与 agentmeshos-omniroute-edge-guard.service。入口监听 100.64.0.4:39200,转发到 127.0.0.1:39180;raw PREROUTING guard 只放行 RR 100.64.0.1 与 MM 100.64.0.6。101 负向连接超时,RR 与 MM 正向访问返回 200。

🧪 验收与回退

验收面 结果 现场证据 影响
最终快照与恢复 通过 RR 官方备份 omniroute-backup-agentmeshos-p13-4-20260930T231204Z;一致性快照 snapshot_20260930T231257Z_p13-4-20260930T231204Z;Cloudreve AgentMeshOS-临时/P13-4/20260930T231204Z/ 102 最终生产数据来自切换时刻快照
102 服务 通过 3.8.51、health healthy、MainPID 存在、NRestarts=0、systemctl --failed 为 0 目标运行态稳定
模型目录 通过 /v1/models HTTP 200,models_count=92,Boss/Worker Combo 可见 正式 Combo 未因迁移丢失
Boss Combo 通过 命中 deepseek-ai/DeepSeek-V3,精确返回 P13_4_BOSS_OK,usage 存在 质量优先通道可用
Worker Combo 通过 首次空内容后重试命中 command-a-reasoning-08-2025,精确返回 P13_4_WORKER_RETRY_OK,usage 存在 容量池可用;健康观察继续统计上游空响应,但不再阻塞迁移关闭
Codex Responses 通过 /v1/responses SSE 200,出现 response.completed;真实 function_call 为 get_status,参数 {"scope":"p13-4-final"} Codex 工具调用子路径可用
管理 API 通过 combos=19、api_keys=4;Boss fill-first、Worker least-used,两者均有 responseValidation 路由策略与权限基线一致
Runtime 健康 通过 {"status":"ok","version":"v0.10.3","provider_core":"omniroute","omniroute_configured":true};容器 healthy、restarts 为 0 Runtime 未保留第二 Provider 路由
SQLite 回读 通过 quick_check=ok、provider_connections=70、combos=19、api_keys=4、迁移 193;日志和 usage 已回读 数据与调用事实可查
负向回归 通过 未授权 /api/keys、/api/combos 为 401;错误 Token 403;API 路径穿越 403;文件路径穿越 400;错误模型 400;101 访问 102 39200 超时、39180 拒绝 入口与鉴权边界有效
RR 宿主卫生 通过 Runtime 代理 active、NRestarts=0 且目标为 102;RR omni 数据、包、service、cutover 备份和 nginx vhost 均不存在;systemctl --failed 为空 迁移后无重复生产写者,也没有可误用的旧回退路径
102 edge FD 与连接上限 通过 FD 软上限 65536、最大连接 4096;旧态 check 因软上限 1024 失败,新态通过;修复后 too_many_after_start=0 避免连接累积后接受请求却无法转发

首次 Worker Combo 检查曾命中 claude-sonnet-4.6 但正文为空;同 Combo 重试命中 command-a-reasoning-08-2025 并返回精确文本。该事实已保留,不把单次重试成功写成上游空响应永久消失;长期观察器继续统计同类空正文、Combo 回退和 usage 写入,但它不再阻塞本次迁移关闭。

🔁 回退与再次切换

真实回退与再次切换是 P13-4 的历史验收证据,证明 RR 回退点在删除前确实可用;P13-C 删除 RR 回退点后,该流程不再作为当前运行路径。执行顺序为:

  1. 102 停止 socket、edge 和 OmniRoute,生成清洁快照 snapshot_20260930T232400Z_p13-4-rollback-clean。
  2. 清洁快照为 151302144 bytes,SHA-256 63bc1deeefa5efba14316a3e099b5faf494f1a2d0074d3ff5d1d9bb35a0c7b60,经 Cloudreve 传到 RR。
  3. RR 生成 pre-restore_20260930T233116Z 后恢复清洁快照并执行 rollback;RR 本地 127.0.0.1:39180 恢复,公网 health 200,真实调用返回 P13_4_ROLLBACK_OK。
  4. RR 再次 freeze,生成回流快照 snapshot_20260930T233238Z_p13-4-return-to-102,大小 150237184 bytes,SHA-256 4f9553f84560205bc81417f14c5381cd311f95c74bb3a8356b97ce8a8fc97655。
  5. 102 生成 pre-restore_20260930T233320Z 后恢复回流快照并重新启动;RR 再次 activate,最终回源与 Runtime 代理恢复指向 102。

Cloudreve 回读路径为 AgentMeshOS-长期/P13-4-rollback-20260930T232400Z/snapshot-storage.sqlite 与 AgentMeshOS-长期/P13-4-return-to-102-20260930T233238Z/snapshot-storage.sqlite。RR WebDAV 凭据只在受控小文件通道临时用于 102 下载,随后已从 102 删除并验证 temp_credentials_removed=true;任何凭据内容未进入仓库、日志或普通回复。

🔍 根因、修复与防复发

🧩 sqlite3 缺失导致快照语义不完整

根因:102 初始没有 sqlite3,官方 snapshot-data.sh 无法执行 VACUUM INTO,退化为复制主库和 WAL;官方 restore-data.sh 恢复时只恢复主库并删除 WAL,因此调用日志类数据不能保证完整闭环。影响:如果继续在干净节点直接部署,切换快照的完整性会依赖未验证的复制行为。

修复:102 已安装 sqlite3 3.46.1-9ubuntu0.3。负向回归快照 snapshot_20260930T233525Z_p13-4-sqlite3-regression-retry 为 150228992 bytes、无 WAL、SHA-256 b9788f0801492bb296ba3e0750d6312513c4633d9894336610b5889157ddb8b0;隔离恢复后 SHA-256、quick_check、call_logs 和 usage_history 一致。部署脚本已升为 v0.1.1,preflight() 强制要求 sqlite3,并在 usage 中说明 VACUUM INTO 依赖。

🧩 Runtime 代理曾依赖 RR 本地 OmniRoute

根因:systemd 255 在当前主机上没有按预期用 drop-in 的空 Requires= / After= 清除原 unit 依赖。复现时单独重启 Runtime 代理会把 RR 本地 3.8.50 重新拉起,破坏“RR 只保留数据回退点”的边界。

修复:原始包外 unit 已备份到 /root/.omniroute-cutover-backups/agentmeshos-omniroute-runtime-proxy.service.original,SHA-256 35a99df108bfa8c0e96e6c212ebe13cbdc4049504a7583a1a9e540e0a2f9b52b;修复后的 unit SHA-256 d387eeac4db1a0983ab90b625f40f695c46fe9a4d692bd2e866017b3a758aa68。Runtime 代理的 Requires / Wants 现在都不包含 agentmeshos-omniroute.service,RR 本地 OmniRoute 为 inactive/dead/disabled,failed unit 为 0。

当时的切换脚本已升为 v0.1.1 并完成上述修复;P13-C 随后删除该脚本和 RR 原始 unit 备份,因为 RR 本地 OmniRoute 已不存在。当前 Runtime 代理 unit 保持无本机依赖,目标固定为 100.64.0.4:39200。

🧩 edge 代理 FD 软上限导致公网超时

根因:102 的 agentmeshos-omniroute-edge.service 虽然继承了较高的硬限制,但进程实际软上限仍是 1024。长期连接累积后,systemd-socket-proxyd 的 FD 数达到 1024,journal 持续输出 Failed to accept() socket, ignoring: Too many open files;监听和 TCP 建连仍成功,但已接受的请求无法转发,因此 RR 访问 100.64.0.4:39200 超时,MM 到 RR 的公网入口也超时。

修复:agentmeshos-omniroute-edge.sh 升为 v0.1.2,生成的服务显式使用 LimitNOFILE=65536:65536,代理启动参数增加 --connections-max=4096,并增加 Restart=on-failure。check 现在会读取 LimitNOFILESoft,低于 65536 直接失败;这与健康观察器的同类门禁形成双重检查。旧态负向回归中,使用 AGENTMESHOS_OMNIROUTE_EDGE_NOFILE_LIMIT=131072 check 能准确拒绝软上限不足的节点。

修复后证据:SERVICE_SOFT_NOFILE=65536、LimitNOFILE=65536、edge FD 数降到两位或三位、服务重启后 Too many open files 计数为 0;RR→102 health 和 Runtime 代理 health 均为 200,公网 health 恢复 200。这不修改 OmniRoute 包、数据库、MM 回源或 RR 回退 unit。

🧩 分布式底座接入声明

接入结论:P13 已接入 Network、Compute、Storage、Observability 和 Nomad 状态面;Nomad 只提供既有节点状态事实,不作为迁移执行器。

使用层 P13 用途 边界
Network MM 公网入口、102 私有入口、Tailnet/UFW/raw guard 和 RR Runtime 本机代理 不把 Tailnet 当业务数据面,不扩大 102 监听
Compute 102 原生 Node、OmniRoute systemd、Docker/宿主依赖 不建立第二调度器或兼容运行目录
Storage 102 生产库、Cloudreve P13-4 恢复材料、审计归档和哈希 任意时刻只允许一个 SQLite 写者;RR 不再保存 omni 库
Observability health、模型、Combo、usage、日志、SQLite、负向测试 不导出正文、凭据或管理会话
Nomad 只核对既有 102 Client 状态 不提交迁移 Job,不承担迁移控制面
  • Adapter 归属:继续使用现有 OmniRouteAdapter 和官方 CLI/API,不新增第二套路由层。
  • 执行映射:101 负责仓库、CI 和证据,RR 负责其他域名入口与本机 Runtime 代理,102 负责当前生产运行。
  • 数据路径:完整数据和恢复材料经 Cloudreve 公网 HTTPS;控制小文件按受控例外处理。
  • 凭据路径:Provider、OAuth、API Key、Runtime Key 和 .env 只在 root-only 边界流转。
  • 生命周期:P13-0 至 P13-4、P13-B、P13-C 和 P13-6 已先后完成;健康观察不设置阶段阻塞等待期,P13 已归档。
  • 验收证据:切换材料、公网 health、模型、Combo、Responses、SQLite、负向回归、RR 退役路径检查和 systemd 状态。

💾 数据、凭据与回退边界

对象 当前状态 回退或保留策略
102 生产库 /root/.omniroute/storage.sqlite,唯一写者 由健康观察器和独立备份流程持续检查完整性
RR omni 数据与包 已删除(P13-C) 不再保留 RR 回退点;恢复以 Cloudreve P13-4 快照和 102 重装为准
RR 本机 service 与 cutover 脚本 已删除(P13-C) 不得恢复 RR 本地 OmniRoute 或 freeze/activate/rollback 旧脚本
RR origin gateway omni vhost 已删除(P13-C) RR 网关继续服务其他 7 个域名,不再生成 omni 上游
MM 回源 面板 JSON 与渲染 conf 均为 100.64.0.4:39200 以后修改必须同时同步面板源与渲染配置,并执行 nginx -t
.env 与 Provider 凭据 102 root:root 0600 不进入 Git、日志、模型上下文或普通回复
discovery 能力 RR controlled-discovery inactive、timer/service disabled 当前没有 discovery 后端;如需恢复,另立 102 部署计划

任意时刻只允许一个 SQLite 写者。当前该写者是 102。RR 已无 omni 活库;历史恢复材料只在 Cloudreve 长期归档和审计包中保留,不再作为可随时切回的运行数据。

🚀 P13-5 取消与 P13-6 健康观察

用户明确取消 P13-5 的等待期和 RR 数据保留期,P13-5 不再以“观察满固定时长”或“RR 回退点持续存在”为出口。P13-6 保留了一个无阶段阻塞含义的健康观察器,用来持续发现 102、公网入口或 RR 退役边界的真实退化;该观察能力在归档后仍独立运行。

🔧 自动观察机制

101 已安装 agentmeshos-omniroute-health-observation.timer,每 15 分钟执行只读观察脚本,记录写入 /srv/codex-hub-backup/agentmeshos/omniroute-health/observations/,最新记录软链接为 /srv/codex-hub-backup/agentmeshos/omniroute-health/latest.json。脚本路径为 scripts/maintenance/agentmeshos-omniroute-health-observation.py,安装入口为 scripts/maintenance/agentmeshos-omniroute-health-observation-install.sh。旧 omniroute-p13-5 timer 已停用并删除,历史观察记录保留在原目录。

新观察器首个通过记录为 20261001T022814Z.json,状态 pass、critical=0、warnings=0。记录包含 102 版本、服务、edge FD/连接上限、资源、SQLite 完整性和计数、RR omni 退役路径、RR Runtime 代理目标、failed unit 与公网 health。依据是 ExecMainStatus=0 和文件内容回读;影响是后续健康趋势可查,但不再要求等待固定观察期才能关闭 P13。

观察项 必须记录的证据 失败或触发条件
102 服务稳定性 health、MainPID、NRestarts、failed unit、edge FD 软上限与当前 FD 数、资源与内存峰值 多次重启、OOM、SQLite 错误、FD 上限退化或健康中断
模型与 Combo Boss/Worker 真实调用、空响应重试、Provider 故障、usage 与日志回读 同类空正文持续出现、Combo 权限漂移或费用异常
Codex Responses SSE、tools、function call、超时与上游中断 response.completed 缺失或工具调用不可执行
恢复能力 Cloudreve 的 P13-4 快照可读、102 可原生重装、恢复步骤有记录(RR 回退点已在 P13-C 退役) 快照丢失或 102 无法重装
资源边界 102 根盘、内存、swap、cgroup、SQLite 大小增长 超过安全余量或影响其他节点服务
discovery 能力 明确保持关闭或单独立项恢复 不得用旧 RR 本地数据假装新后端可用
RR 退役边界 数据、包、service 和 cutover 备份不存在;Runtime 代理 active 且目标为 102;origin gateway 无 omni vhost 任一 RR omni 运行残留重新出现,或 Runtime 代理重新依赖本机 unit

P13-6 阶段出口已经满足:102 当前健康且无重复写者;MM 面板源与渲染 conf 都直连 102;RR omni 数据、包、service、回退备份和 vhost 均不存在;RR Runtime 代理仍可访问 102;公网 health 200;健康观察器 pass;文档、脚本、Git 和 CI 状态一致;discovery、媒体、语义缓存和日志正文导出明确保持关闭或另立计划。因此 P13 已转为完成归档,没有另设等待期。

⚠️ 未决项 / 需要用户决策

事项 当前事实 需要用户决定或后续动作
RR 数据退役 已完成(P13-C):已删除,RR 不再有回退点 恢复改用 Cloudreve P13-4 快照与 102 重装
P13-B 面板配置源 宝塔面板反代目标存储在 /www/server/proxy_project/sites/omni.yohan.fun/omni.yohan.fun.json,与渲染 conf 是两个存储 已同步为 100.64.0.4:39200;以后凡改面板管理的反代,必须同时改面板 JSON 与渲染 conf
cutover 脚本边界 已退役(P13-C):agentmeshos-omniroute-cutover.sh 已删除 公网路径回退改由 MM 侧决定,不再依赖 RR 脚本
RR origin gateway omni 死配置 已删除(P13-C):生成脚本 v0.6.2 不再生成 omni vhost,RR 网关 omni 计数为 0 无;其余 7 个服务回归通过
RR Runtime 私有代理 已决定保留:RR 本机 AI Runtime 容器在用,监听 172.30.70.1:39181、上游 100.64.0.4:39200 保留本地代理(比容器直连更灵活,实测两者都通)
discovery 能力 RR controlled-discovery 已停用,切换后没有后端 保持关闭,或另立 102 discovery 部署评估
新版本可选能力 媒体、语义缓存、日志正文导出未启用 按收益、隐私、资源和回滚条件逐项评审
Worker 空响应 首测一次命中 claude-sonnet-4.6 但正文为空,重试成功后通过 健康观察继续统计;若持续出现,作为 OmniRoute 运维问题处理,不再阻塞 P13 迁移关闭
101/Home Codex 可用性 默认 Codex 会话不由 OmniRoute 承载;切换或回退演练期间只有经 OmniRoute 的模型、MCP、搜索、图片和 Runtime 调用短暂中断 后续维护窗口需继续按同一边界通知,不能把默认 Codex 会话与 OmniRoute 通道混为同一可用性
持续健康观察 101 timer 每 15 分钟记录一次;最新实时复核为 pass 异常按运维事件处理;若出现重复写者或 102 生产中断,按新的运维事件修复,不重新打开 P13