Compare commits
36 Commits
658f87b745
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
215a364891 | ||
|
|
7cbde2aa78 | ||
|
|
e0406b5d0e | ||
|
|
c33f4f194b | ||
|
|
451d0f75f0 | ||
|
|
66f55d880a | ||
|
|
4dcbf8ecb3 | ||
|
|
3a55db94f8 | ||
|
|
6c4e995f84 | ||
|
|
cfff515c03 | ||
|
|
ad513211e6 | ||
|
|
74dc009c3d | ||
|
|
1adfeed1ab | ||
|
|
b9c29481b5 | ||
|
|
246838ae4c | ||
|
|
bd6bcb240f | ||
|
|
0e096947fc | ||
|
|
fe87c7b343 | ||
|
|
1921318c25 | ||
|
|
dc34a4e294 | ||
|
|
954a6a2c65 | ||
|
|
d3223a75a4 | ||
|
|
3cc36a054c | ||
|
|
f4b4ed0afe | ||
|
|
602ab10590 | ||
|
|
e9c0a75b8f | ||
|
|
25d36c9d4b | ||
|
|
0d8c0b4aed | ||
|
|
ff79f5c13d | ||
|
|
6ed4a99143 | ||
|
|
9aa0d87c4a | ||
|
|
a48a4131c9 | ||
|
|
0295f7d06d | ||
|
|
e64c23a021 | ||
|
|
ebf632e651 | ||
|
|
ff32aa50bf |
35
.gitignore
vendored
35
.gitignore
vendored
@@ -21,8 +21,11 @@ dist/
|
||||
|
||||
# Logs and runtime data
|
||||
*.log
|
||||
logs/
|
||||
runtime/
|
||||
*.pid
|
||||
/runtime/
|
||||
/diagnostics/
|
||||
/domain-api/runtime/
|
||||
!/domain-web/src/views/runtime/
|
||||
|
||||
# Build and release artifacts
|
||||
release/
|
||||
@@ -31,19 +34,45 @@ release/
|
||||
|
||||
# Local data and generated files
|
||||
uploads/
|
||||
exports/
|
||||
/logs/
|
||||
/exports/
|
||||
tmp/
|
||||
*.sqlite3
|
||||
*.pkl
|
||||
domains.txt
|
||||
credentials.json
|
||||
!/domain-web/src/views/logs/
|
||||
!/domain-web/src/views/exports/
|
||||
|
||||
# Local deploy config copies
|
||||
domain-api/deploy/multi-region/*.conf
|
||||
!domain-api/deploy/multi-region/*.conf.example
|
||||
|
||||
# domainCheck local runtime / bundled tools
|
||||
domainCheck/tools/node-v20.19.4-win-x64/
|
||||
domainCheck/app/credentials.json
|
||||
domainCheck/credentials.json
|
||||
domainCheck/runtime/
|
||||
domainCheck/**/*.pkl
|
||||
domainCheck/domains.txt
|
||||
thread_count.json
|
||||
node_thread_counts.json
|
||||
runtime_settings.json
|
||||
runtime/runtime_settings.json
|
||||
runtime/sensitive_words.json
|
||||
|
||||
# Ops center generated night-run artifacts
|
||||
docs/ops_center_runtime/night_runs/night_run_*/
|
||||
docs/ops_center_runtime/night_runs/night_run_*_summary.json
|
||||
docs/ops_center_runtime/night_runs/*.log
|
||||
docs/ops_center_runtime/night_runs/*.pid
|
||||
docs/ops_center_runtime/night_runs/step_mix_*/
|
||||
docs/ops_center_runtime/chinaz_gray_runs/
|
||||
docs/_tmp_regression/
|
||||
|
||||
# Local probe / backup artifacts
|
||||
.codex-release-probe.txt
|
||||
*.bak_*
|
||||
|
||||
# OS / editor
|
||||
.DS_Store
|
||||
|
||||
97
README.md
97
README.md
@@ -6,13 +6,24 @@
|
||||
- 新版后端服务 `domain-api/`
|
||||
- 新版 Web 管理后台 `domain-web/`
|
||||
- 全套交付与部署文档 `docs/`
|
||||
- Windows 本地启动、打包、验包脚本
|
||||
- Windows / Linux 启动、打包、验包脚本
|
||||
|
||||
如果你是第一次打开这个仓库,建议先看:
|
||||
|
||||
- [docs/12_domainCheck_导航索引.md](./docs/12_domainCheck_导航索引.md)
|
||||
- [docs/04_domainCheck_WebLinux改造总体方案.md](./docs/04_domainCheck_WebLinux改造总体方案.md)
|
||||
|
||||
如果你当前已经进入“海外单脑控制面 / 多机联调 / 准备上线”阶段,建议直接从下面 4 份开始:
|
||||
|
||||
1. [docs/25_domainCheck_海外单脑控制面上线收口总表.md](./docs/25_domainCheck_海外单脑控制面上线收口总表.md)
|
||||
2. [docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md](./docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md)
|
||||
3. [docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md](./docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md)
|
||||
4. [docs/schemas/ops_driver_contract.md](./docs/schemas/ops_driver_contract.md)
|
||||
|
||||
如果已经接近正式发布,建议再补一份:
|
||||
|
||||
- [docs/26_domainCheck_发布前运行验证与交付模板.md](./docs/26_domainCheck_发布前运行验证与交付模板.md)
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
@@ -25,10 +36,14 @@
|
||||
├─ start_*.ps1 Windows 启动脚本
|
||||
├─ stop_*.ps1 Windows 停止脚本
|
||||
├─ smoke_test_stack.ps1 本地整栈自测
|
||||
├─ package_domain_release.ps1 交付打包
|
||||
├─ verify_domain_release.ps1 交付包校验
|
||||
├─ prepare_final_release.ps1 最终发布准备
|
||||
└─ show_latest_release.ps1 查看最新交付包
|
||||
├─ package_domain_release.ps1 Windows 交付打包
|
||||
├─ verify_domain_release.ps1 Windows 交付包校验
|
||||
├─ prepare_final_release.ps1 Windows 最终发布准备
|
||||
├─ show_latest_release.ps1 Windows 查看最新交付包
|
||||
├─ package_domain_release.sh Linux / 海外主机交付打包
|
||||
├─ verify_domain_release.sh Linux / 海外主机交付包校验
|
||||
├─ prepare_final_release.sh Linux / 海外主机最终发布准备
|
||||
└─ show_latest_release.sh Linux / 海外主机查看最新交付包
|
||||
```
|
||||
|
||||
## 各目录用途
|
||||
@@ -118,6 +133,15 @@
|
||||
- [verify_domain_release.ps1](./verify_domain_release.ps1)
|
||||
- [prepare_final_release.ps1](./prepare_final_release.ps1)
|
||||
- [show_latest_release.ps1](./show_latest_release.ps1)
|
||||
- [package_domain_release.sh](./package_domain_release.sh)
|
||||
- [verify_domain_release.sh](./verify_domain_release.sh)
|
||||
- [prepare_final_release.sh](./prepare_final_release.sh)
|
||||
- [show_latest_release.sh](./show_latest_release.sh)
|
||||
|
||||
补充说明:
|
||||
|
||||
- `show_latest_release.ps1 / .sh` 现在会校验 `final_release_report.json` 是否真的对应当前 `latest_release.*`
|
||||
- 不是“目录里有 final report 就算已经完成最终签收”
|
||||
|
||||
## 当前状态
|
||||
|
||||
@@ -142,6 +166,69 @@ Linux 阶段建议先看:
|
||||
- [docs/11_domainCheck_Linux联调输入清单.md](./docs/11_domainCheck_Linux联调输入清单.md)
|
||||
- [docs/12_domainCheck_导航索引.md](./docs/12_domainCheck_导航索引.md)
|
||||
|
||||
如果当前已经切到“海外单脑控制面 + 大陆托管节点 + 发布 / Rollout / 驾驶舱首屏”阶段,建议改为:
|
||||
|
||||
1. [docs/25_domainCheck_海外单脑控制面上线收口总表.md](./docs/25_domainCheck_海外单脑控制面上线收口总表.md)
|
||||
2. [docs/22_domainCheck_海外Codex驾驶员与OpsCenter落地路线.md](./docs/22_domainCheck_海外Codex驾驶员与OpsCenter落地路线.md)
|
||||
3. [docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md](./docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md)
|
||||
4. [docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md](./docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md)
|
||||
5. [docs/schemas/ops_stack_diagnosis_contract.md](./docs/schemas/ops_stack_diagnosis_contract.md)
|
||||
6. [docs/schemas/ops_driver_contract.md](./docs/schemas/ops_driver_contract.md)
|
||||
|
||||
如果当前已经进入“海外主机集中运维 / 多机联调 / Release Hub”阶段,最直接的统一入口是:
|
||||
|
||||
- [domain-api/deploy/multi-region/drive_ops_center.sh](./domain-api/deploy/multi-region/drive_ops_center.sh)
|
||||
- [domain-api/deploy/multi-region/drive_release_hub.sh](./domain-api/deploy/multi-region/drive_release_hub.sh)
|
||||
- [domain-api/deploy/multi-region/drive_ops_action.sh](./domain-api/deploy/multi-region/drive_ops_action.sh)
|
||||
- [domain-api/deploy/multi-region/init_ops_center_config.sh](./domain-api/deploy/multi-region/init_ops_center_config.sh)
|
||||
|
||||
其中:
|
||||
|
||||
- `drive_ops_center.sh`
|
||||
用于海外控制面统一调度检查、Release Hub 和 Driver 动作
|
||||
- `drive_release_hub.sh`
|
||||
用于直接从命令行走 Release / Rollout 标准接口
|
||||
- `drive_ops_action.sh`
|
||||
用于直接从命令行走 `ops/driver-actions/execute`
|
||||
- `init_ops_center_config.sh`
|
||||
用于初始化 `/etc/default/domaincheck-ops-center`
|
||||
|
||||
现在 `drive_ops_center.sh` 还额外收进了本机发布链:
|
||||
|
||||
- `release-package`
|
||||
- `release-verify`
|
||||
- `release-show`
|
||||
- `release-launchpad`
|
||||
- `release-prepare`
|
||||
- `release-preview`
|
||||
- `release-preview-smart`
|
||||
|
||||
当前如果要用一条最短路径判断“现在能不能继续收口、能不能继续发布”,推荐先跑:
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/getDomain
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-check http://127.0.0.1:8100 http://127.0.0.1:8100 summary
|
||||
```
|
||||
|
||||
然后再按:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh stack-diagnosis
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh driver-feed
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh codex-brief
|
||||
```
|
||||
|
||||
继续下钻。
|
||||
|
||||
如果要把这轮检查直接导出成一整包上线证据,也可以直接执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-export
|
||||
```
|
||||
|
||||
它会把 `go-live / stack-diagnosis / driver-feed / codex-brief / release-launchpad / doctor-*`
|
||||
统一导出到 `domain-api/runtime/ops-center-reports/go-live-bundles/` 下,并生成一份 `manifest.json`。
|
||||
|
||||
## Git 提交建议
|
||||
|
||||
建议提交:
|
||||
|
||||
@@ -1,90 +1,231 @@
|
||||
# 07 domainCheck Web/Linux 发布验收清单
|
||||
|
||||
## 一、基础连通
|
||||
## 一、文档定位
|
||||
|
||||
- `domain-api` 已启动
|
||||
- `domainCheck Worker` 已启动
|
||||
- `http://服务器IP:8100/health` 返回 `status=ok`
|
||||
- `runtime/preflight` 返回 `ok=true`
|
||||
本文档用于回答两个问题:
|
||||
|
||||
## 二、Web 后台
|
||||
1. 当前这套 Web/Linux 方案,到底哪些项已经验过
|
||||
2. 发布前还需要按什么维度再核一遍
|
||||
|
||||
阅读建议:
|
||||
|
||||
- 想看测试服真实联调结果,优先看 `docs/13_domainCheck_Linux测试服交接文档.md`
|
||||
- 想看正式上线前最后一次操作顺序,优先看 `docs/14_domainCheck_正式上线前最终检查单.md`
|
||||
|
||||
本文档更适合作为“发布验收维度总表”。
|
||||
|
||||
## 二、基础连通验收
|
||||
|
||||
以下项目应视为发布验收的第一层:
|
||||
|
||||
- `domaincheck-api` 已启动
|
||||
- `domaincheck-worker` 已启动
|
||||
- `http://127.0.0.1:8100/health` 返回 `status=ok`
|
||||
- `/health` 返回 `worker_mode=linux-systemd`
|
||||
- `/api/v1/runtime/preflight` 返回 `ok=true`
|
||||
- `/api/v1/runtime/status` 返回 `worker.running=true`
|
||||
|
||||
当前测试服状态:
|
||||
|
||||
- 已验证通过
|
||||
|
||||
## 三、Web 后台验收
|
||||
|
||||
### 1. 运行与展示
|
||||
|
||||
- 登录正常
|
||||
- 顶部可看到 `API / Worker / 运行模式`
|
||||
- 概览页能正常读取统计
|
||||
- 运行中心能正常读取:
|
||||
- 顶部状态可展示 `API / Worker / 运行模式`
|
||||
- 概览页可正常读取统计
|
||||
- 运行中心可正常读取:
|
||||
- API 版本
|
||||
- API 前缀
|
||||
- PID
|
||||
- Worker 进程数
|
||||
- 自检结果
|
||||
|
||||
## 三、配置能力
|
||||
### 2. 配置能力
|
||||
|
||||
- 系统设置能正常读取
|
||||
- 线程数修改后可保存
|
||||
- 系统设置可正常读取
|
||||
- 线程数可修改并保存
|
||||
- 检测顺序可调整并保存
|
||||
- 代理池列表可编辑并保存
|
||||
- `worker_mode / service_name` 可保存
|
||||
- `worker_mode / worker_service_name / api_service_name` 可保存
|
||||
- 可手动创建配置备份
|
||||
- 可下载配置备份
|
||||
- 可导出配置快照
|
||||
- 可导入配置快照
|
||||
- 导入配置时会自动生成导入前备份
|
||||
|
||||
## 四、业务能力
|
||||
当前测试服状态:
|
||||
|
||||
- 核心接口与配置链路已验证通过
|
||||
|
||||
## 四、业务能力验收
|
||||
|
||||
发布前建议至少覆盖下面 5 类能力:
|
||||
|
||||
- 导入
|
||||
- 列表筛选
|
||||
- 批量更新
|
||||
- 导出
|
||||
- 日志与诊断
|
||||
|
||||
### 1. 导入链路
|
||||
|
||||
- 导入任务可创建
|
||||
- 导入任务列表可刷新
|
||||
- 导入任务失败时可重试
|
||||
- 域名筛选可查询
|
||||
- 批量更新可执行
|
||||
- 导出记录可生成
|
||||
- 导出文件可下载
|
||||
- 日志诊断页可查看日志
|
||||
- 诊断包可下载
|
||||
- 导入结果统计正确
|
||||
- 导入成功后会写入 `domains`
|
||||
- 导入成功后会自动创建 `detect_tasks`
|
||||
|
||||
## 五、Linux 特有项
|
||||
当前测试服状态:
|
||||
|
||||
- 已使用样本 TXT 实际验证通过
|
||||
- 当前已确认:
|
||||
- 总数 `5`
|
||||
- 有效 `3`
|
||||
- 新增 `3`
|
||||
- 无效 `2`
|
||||
|
||||
### 2. 列表与筛选
|
||||
|
||||
- 域名列表可查询
|
||||
- 筛选项接口正常返回
|
||||
- 页面结果与数据库记录一致
|
||||
|
||||
当前测试服状态:
|
||||
|
||||
- 已验证通过
|
||||
|
||||
### 3. 批量更新
|
||||
|
||||
- 批量更新接口可执行
|
||||
- 页面展示与数据库字段一致
|
||||
- 关联检测字段会同步更新
|
||||
|
||||
当前测试服状态:
|
||||
|
||||
- 已验证通过
|
||||
- 已确认 `backlink_count_gt_10` 可随批量更新同步生效
|
||||
|
||||
### 4. 导出链路
|
||||
|
||||
- 导出任务可创建
|
||||
- 导出记录可查看
|
||||
- 导出文件可下载
|
||||
- TXT / CSV 至少一种格式已回归
|
||||
|
||||
当前测试服状态:
|
||||
|
||||
- TXT、CSV 均已验证通过
|
||||
|
||||
### 5. 日志与诊断
|
||||
|
||||
- 日志接口可正常读取
|
||||
- 诊断包可正常导出
|
||||
|
||||
当前测试服状态:
|
||||
|
||||
- 已验证通过
|
||||
- 当前已生成正式服务态诊断包:
|
||||
- `/opt/domaincheck/diagnostics/diag_20260416_134923.tar.gz`
|
||||
|
||||
## 五、Linux 特有项验收
|
||||
|
||||
以下项目是 Web/Linux 交付里最容易在正式环境出问题的部分:
|
||||
|
||||
- `domaincheck-api.service` 可正常启动/停止
|
||||
- `domaincheck-worker.service` 可正常启动/停止
|
||||
- `journalctl` 可查看两边日志
|
||||
- Nginx 反代正常
|
||||
- Web 静态文件 `dist` 已正确发布
|
||||
- 运行中心可调用 `start_worker / stop_worker / restart_api`
|
||||
- Worker 以 `QT_QPA_PLATFORM=offscreen` 正常运行
|
||||
- API 自重启不会再因为同步等待自身停机而误报 `500`
|
||||
|
||||
## 六、建议发布前命令
|
||||
当前测试服状态:
|
||||
|
||||
### 1. 运行 API 自测
|
||||
- 已验证通过
|
||||
|
||||
## 六、数据库与权限验收
|
||||
|
||||
Linux 新环境发布前,下面两项必须显式确认:
|
||||
|
||||
### 1. 数据库初始化
|
||||
|
||||
如果 PostgreSQL 使用的是新库,必须先执行:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
python deploy/linux/smoke_test.py --base-url http://127.0.0.1:8100
|
||||
cd /opt/domaincheck/domainCheck
|
||||
python3 init_database.py
|
||||
```
|
||||
|
||||
否则至少这些接口会直接失败:
|
||||
|
||||
- `/api/v1/dashboard/overview`
|
||||
- `/api/v1/detect/status`
|
||||
- `/api/v1/imports/summary`
|
||||
|
||||
### 2. 服务用户写权限
|
||||
|
||||
正式 `systemd` 服务用户必须可写:
|
||||
|
||||
- `domain-api/runtime/`
|
||||
- `domainCheck/detect_worker.log`
|
||||
|
||||
否则可能出现:
|
||||
|
||||
- `/api/v1/imports/upload` 返回 `500`
|
||||
- Worker 循环重启
|
||||
|
||||
当前测试服状态:
|
||||
|
||||
- 两项都已实际踩坑并修复
|
||||
|
||||
## 七、发布前建议命令
|
||||
|
||||
### 1. 健康检查
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8100/health
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/preflight
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/status
|
||||
```
|
||||
|
||||
### 2. systemd 状态
|
||||
|
||||
```bash
|
||||
systemctl status domaincheck-api --no-pager -l
|
||||
systemctl status domaincheck-worker --no-pager -l
|
||||
```
|
||||
|
||||
### 3. smoke test
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api/deploy/linux
|
||||
python3 smoke_test.py --base-url http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
如需同时校验 Web 首页:
|
||||
|
||||
```bash
|
||||
python deploy/linux/smoke_test.py --base-url http://127.0.0.1:8100 --web-url http://127.0.0.1
|
||||
python3 smoke_test.py --base-url http://127.0.0.1:8100 --web-url http://127.0.0.1
|
||||
```
|
||||
|
||||
### 2. 查看 API 健康状态
|
||||
### 4. 诊断包导出
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8100/health
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/preflight
|
||||
cd /opt/domaincheck/domain-api/deploy/linux
|
||||
bash collect_diagnostics.sh /opt/domaincheck
|
||||
```
|
||||
|
||||
### 3. 查看 systemd 状态
|
||||
## 八、当前发布验收结论
|
||||
|
||||
```bash
|
||||
systemctl status domaincheck-api
|
||||
systemctl status domaincheck-worker
|
||||
```
|
||||
|
||||
## 七、当前结论
|
||||
|
||||
如果以上检查项全部通过,则可以认为:
|
||||
结合当前 Linux 测试服已经完成的联调结果,可以给出下面的结论:
|
||||
|
||||
- Web 管理后台已达到可交付状态
|
||||
- Linux 部署环境已达到可联调状态
|
||||
- 可以进入真实服务器联调或灰度上线阶段
|
||||
- Linux 正式 `systemd` 服务态已验证通过
|
||||
- 核心业务链路已完成最小闭环回归
|
||||
- 当前剩余工作主要是正式环境发布、灰度观察和持续稳定性观察
|
||||
|
||||
一句话结论:
|
||||
|
||||
> 当前项目已经通过 Web/Linux 发布所需的核心验收项,后续重点不再是功能开发,而是正式环境收口与上线后观察。
|
||||
|
||||
@@ -120,3 +120,10 @@ python deploy/linux/smoke_test.py --base-url http://127.0.0.1:8100
|
||||
- Linux 实机联调
|
||||
- 上线前复测
|
||||
- 真实服务器灰度验证
|
||||
|
||||
如果当前已经进入“海外单脑控制面 + 多机联调 + 准备发布”阶段,建议改为按下面顺序执行:
|
||||
|
||||
1. `docs/25_domainCheck_海外单脑控制面上线收口总表.md`
|
||||
2. `bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-export`
|
||||
3. `bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-review`
|
||||
4. `docs/26_domainCheck_发布前运行验证与交付模板.md`
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 一、用途
|
||||
|
||||
用于在 Windows 本地把当前可交付内容整理成一份压缩包,便于:
|
||||
用于在 Windows 或 Linux 上把当前可交付内容整理成一份发布包,便于:
|
||||
|
||||
- 发给运维或部署同事
|
||||
- 存档版本快照
|
||||
@@ -16,31 +16,60 @@
|
||||
- `verify_domain_release.ps1`
|
||||
- `prepare_final_release.ps1`
|
||||
- `show_latest_release.ps1`
|
||||
- `package_domain_release.sh`
|
||||
- `verify_domain_release.sh`
|
||||
- `prepare_final_release.sh`
|
||||
- `show_latest_release.sh`
|
||||
|
||||
执行方式:
|
||||
Windows 执行方式:
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\package_domain_release.ps1
|
||||
```
|
||||
|
||||
Linux / 海外主机执行方式:
|
||||
|
||||
```bash
|
||||
bash ./package_domain_release.sh
|
||||
```
|
||||
|
||||
如需一键完成“打包 + 验包 + 生成最终准备报告”:
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\prepare_final_release.ps1
|
||||
```
|
||||
|
||||
```bash
|
||||
bash ./prepare_final_release.sh
|
||||
```
|
||||
|
||||
如需快速查看当前最新交付物:
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\show_latest_release.ps1
|
||||
```
|
||||
|
||||
```bash
|
||||
bash ./show_latest_release.sh
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
- `show_latest_release.*` 现在不只是“显示最近一次 final report 是否存在”
|
||||
- 它会额外校验 `final_release_report.json` 是否真的对应当前 `latest_release.*`
|
||||
- 只有 `final_release_report_matches_latest=true` 时,`final_release_ok=true` 才有意义
|
||||
- `final_release_gate_decision / blocked_reasons / verify_ok / smoke_test_ok` 用于解释“为什么当前能签 / 不能签”
|
||||
- Ops Center 里的“直接创建 Release / 一键 Worker 灰度 / 一键 Control 发布”
|
||||
- 现在会硬性依赖 `final_release_ok=true`
|
||||
- 如果 final report 缺失、过期或门禁未 ready,前端会禁用按钮,后端接口也会拒绝执行
|
||||
|
||||
## 三、输出位置
|
||||
|
||||
打包后会生成:
|
||||
|
||||
- `release/domaincheck_release_时间戳/`
|
||||
- `release/domaincheck_release_时间戳.zip`
|
||||
- `release/domaincheck_release_时间戳.tar.gz`
|
||||
- `release/domaincheck_release_时间戳.sha256.txt`
|
||||
- `release/latest_release.txt`
|
||||
- `release/latest_release.json`
|
||||
@@ -50,6 +79,7 @@ powershell -ExecutionPolicy Bypass -File .\show_latest_release.ps1
|
||||
|
||||
- `docs/`
|
||||
- `scripts/`
|
||||
- `scripts/` 中会同时带上 PowerShell 和 Shell 版发布脚本
|
||||
- `domain-api/`
|
||||
- `app`
|
||||
- `deploy`
|
||||
@@ -89,6 +119,10 @@ powershell -ExecutionPolicy Bypass -File .\show_latest_release.ps1
|
||||
powershell -ExecutionPolicy Bypass -File .\verify_domain_release.ps1
|
||||
```
|
||||
|
||||
```bash
|
||||
bash ./verify_domain_release.sh
|
||||
```
|
||||
|
||||
5. Windows 联调先跑 `scripts/smoke_test_stack.ps1`
|
||||
6. Linux 部署前阅读:
|
||||
- `docs/05_domainCheck_Linux部署清单.md`
|
||||
@@ -106,6 +140,18 @@ powershell -ExecutionPolicy Bypass -File .\verify_domain_release.ps1
|
||||
|
||||
这样更适合交付、存档和迁移。
|
||||
|
||||
Windows 默认产物为 `.zip`,Linux 默认产物为 `.tar.gz`;两者都会生成同结构的 `release_manifest.json / .sha256.txt / latest_release.*`,便于海外控制面统一管理。
|
||||
|
||||
`latest_release.txt / latest_release.json` 用于快速定位“当前最新一份交付包”,避免人工翻目录。
|
||||
|
||||
若打包目录本身是 Git 仓库,脚本还会自动写入 `commit_sha / commit_ref`;海外控制面在创建 Release 时可以直接回填提交号,减少人工抄写出错。
|
||||
|
||||
`final_release_report.json` 用于记录最近一次“打包 + 验包”的最终状态。
|
||||
|
||||
`show_latest_release.*` 读取这个报告时,还会校验:
|
||||
|
||||
- `package_name`
|
||||
- `archive_path` / `zip_path`
|
||||
- `sha256`
|
||||
|
||||
也就是说,即使目录里留着一份旧的 `final_release_report.json`,只要它不是给当前最新包签出的,`final_release_ok` 也不会误报为 `true`。
|
||||
|
||||
@@ -55,13 +55,22 @@
|
||||
- 上线前灰度发布
|
||||
- 发布后观察期
|
||||
|
||||
补充说明:
|
||||
|
||||
- Linux 测试服基础联调已完成
|
||||
- 正式 `systemd` 服务态已验证通过
|
||||
- 当前进入的是“正式上线前最后检查与观察”阶段
|
||||
|
||||
## 五、建议下一步
|
||||
|
||||
1. 把最新交付包发送到目标 Linux 服务器
|
||||
2. 按 `docs/05`、`docs/07`、`docs/08` 的顺序执行部署与验收
|
||||
3. 部署完成后再做一次真实环境 smoke test
|
||||
4. 进入灰度上线
|
||||
2. 按 `docs/05`、`docs/13`、`docs/14` 的顺序执行部署、核对与收口
|
||||
3. 如果当前已经进入海外单脑控制面阶段,再按 `docs/25` 执行统一收口
|
||||
4. 用 `docs/26` 完成发布前运行验证、证据导出与最终交付结论
|
||||
5. 部署完成后再做一次正式服务态 `smoke test`
|
||||
6. 导出一份最终诊断包
|
||||
7. 进入灰度上线
|
||||
|
||||
## 六、最终判断
|
||||
|
||||
当前这套项目,已经达到“工程交付完成,待真实环境上线联调”的状态。
|
||||
当前这套项目,已经达到“工程交付完成,Linux 测试服联调闭环,待正式环境上线收口”的状态。
|
||||
|
||||
@@ -16,6 +16,75 @@
|
||||
|
||||
- `docs/11_domainCheck_Linux联调输入清单.md`
|
||||
|
||||
### 4. Linux 测试服交接文档
|
||||
|
||||
- `docs/13_domainCheck_Linux测试服交接文档.md`
|
||||
|
||||
### 5. 正式上线前最终检查单
|
||||
|
||||
- `docs/14_domainCheck_正式上线前最终检查单.md`
|
||||
|
||||
### 6. 多机检测与跨地域部署设计
|
||||
|
||||
- `docs/16_domainCheck_多机检测与跨地域部署设计.md`
|
||||
|
||||
### 7. 全流程部署实操手册
|
||||
|
||||
- `docs/17_domainCheck_全流程部署实操手册.md`
|
||||
|
||||
### 8. CentOS9 一键复制部署与更新文档
|
||||
|
||||
- `docs/18_domainCheck_CentOS9一键复制部署与更新文档.md`
|
||||
|
||||
### 9. 临时海外控制面联调清单
|
||||
|
||||
- `docs/20_domainCheck_临时海外控制面联调清单.md`
|
||||
|
||||
### 10. 海外主机集中运维与自动化方案
|
||||
|
||||
- `docs/21_domainCheck_海外主机集中运维与自动化方案.md`
|
||||
|
||||
### 11. 海外控制面统一入口
|
||||
|
||||
- `domain-api/deploy/multi-region/drive_ops_center.sh`
|
||||
- `domain-api/deploy/multi-region/export_go_live_bundle.sh`
|
||||
- `domain-api/deploy/multi-region/check_env_drift.sh`
|
||||
- `domain-api/deploy/multi-region/drive_release_hub.sh`
|
||||
- `domain-api/deploy/multi-region/drive_ops_action.sh`
|
||||
- `domain-api/deploy/multi-region/init_ops_center_config.sh`
|
||||
- `domain-api/deploy/multi-region/check_ops_center_stack.sh`
|
||||
- `domain-api/deploy/multi-region/check_ops_contracts.sh`
|
||||
|
||||
### 12. 海外 Codex 驾驶员与 Ops Center 落地路线
|
||||
|
||||
- `docs/22_domainCheck_海外Codex驾驶员与OpsCenter落地路线.md`
|
||||
|
||||
### 13. 终局运维架构设计:海外单脑控制面
|
||||
|
||||
- `docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md`
|
||||
|
||||
### 14. Node Agent 协议与 Release Hub 设计
|
||||
|
||||
- `docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md`
|
||||
|
||||
### 15. 运维 Contract Schema
|
||||
|
||||
- `docs/schemas/ops_agent_protocol.md`
|
||||
- `docs/schemas/release_hub_contract.md`
|
||||
- `docs/schemas/ops_driver_contract.md`
|
||||
- `docs/schemas/ops_job_contract.md`
|
||||
- `docs/schemas/ops_playbook_contract.md`
|
||||
- `docs/schemas/ops_observability_contract.md`
|
||||
- `docs/schemas/ops_stack_diagnosis_contract.md`
|
||||
|
||||
### 16. 海外单脑控制面上线收口总表
|
||||
|
||||
- `docs/25_domainCheck_海外单脑控制面上线收口总表.md`
|
||||
|
||||
### 17. 发布前运行验证与交付模板
|
||||
|
||||
- `docs/26_domainCheck_发布前运行验证与交付模板.md`
|
||||
|
||||
## 二、文档阅读顺序
|
||||
|
||||
### 1. 先看总体方案
|
||||
@@ -28,6 +97,25 @@
|
||||
- `docs/05_domainCheck_Linux部署清单.md`
|
||||
- `docs/07_domainCheck_WebLinux发布验收清单.md`
|
||||
- `docs/09_domainCheck_交付打包说明.md`
|
||||
- `docs/13_domainCheck_Linux测试服交接文档.md`
|
||||
- `docs/14_domainCheck_正式上线前最终检查单.md`
|
||||
- `docs/16_domainCheck_多机检测与跨地域部署设计.md`
|
||||
- `docs/17_domainCheck_全流程部署实操手册.md`
|
||||
- `docs/18_domainCheck_CentOS9一键复制部署与更新文档.md`
|
||||
- `docs/20_domainCheck_临时海外控制面联调清单.md`
|
||||
- `docs/21_domainCheck_海外主机集中运维与自动化方案.md`
|
||||
- `docs/22_domainCheck_海外Codex驾驶员与OpsCenter落地路线.md`
|
||||
- `docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md`
|
||||
- `docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md`
|
||||
- `docs/25_domainCheck_海外单脑控制面上线收口总表.md`
|
||||
- `docs/26_domainCheck_发布前运行验证与交付模板.md`
|
||||
- `docs/schemas/ops_agent_protocol.md`
|
||||
- `docs/schemas/release_hub_contract.md`
|
||||
- `docs/schemas/ops_driver_contract.md`
|
||||
- `docs/schemas/ops_job_contract.md`
|
||||
- `docs/schemas/ops_playbook_contract.md`
|
||||
- `docs/schemas/ops_observability_contract.md`
|
||||
- `docs/schemas/ops_stack_diagnosis_contract.md`
|
||||
|
||||
### 3. 如果要回溯历史需求与问题
|
||||
|
||||
@@ -58,6 +146,14 @@
|
||||
- `domain-api/deploy/systemd/domain-api.service`
|
||||
- `domain-api/deploy/systemd/domain-worker.service`
|
||||
- `domain-api/deploy/linux/README.md`
|
||||
- `domain-api/deploy/multi-region/README.md`
|
||||
- `domain-api/deploy/multi-region/drive_ops_center.sh`
|
||||
- `domain-api/deploy/multi-region/drive_release_hub.sh`
|
||||
- `domain-api/deploy/multi-region/drive_ops_action.sh`
|
||||
- `domain-api/deploy/multi-region/check_ops_contracts.sh`
|
||||
- `domain-api/deploy/multi-region/init_ops_center_config.sh`
|
||||
- `domain-api/deploy/multi-region/bootstrap_overseas.sh`
|
||||
- `domain-api/deploy/multi-region/bootstrap_mainland.sh`
|
||||
- `domain-api/deploy/linux/smoke_test.py`
|
||||
- `domain-api/deploy/linux/collect_diagnostics.sh`
|
||||
|
||||
@@ -76,6 +172,8 @@
|
||||
- 配置迁移与备份
|
||||
- 打包与验包
|
||||
- 最终发布准备
|
||||
- 海外单脑控制面协议收口
|
||||
- Ops Center / Codex / CLI 驾驶 contract 收口
|
||||
|
||||
剩余工作只在真实 Linux 环境:
|
||||
|
||||
|
||||
431
docs/13_domainCheck_Linux测试服交接文档.md
Normal file
431
docs/13_domainCheck_Linux测试服交接文档.md
Normal file
@@ -0,0 +1,431 @@
|
||||
# 13 domainCheck Linux 测试服交接文档
|
||||
|
||||
## 一、文档目的
|
||||
|
||||
本文档用于把当前 `domainCheck` 项目的 Linux 测试服联调状态,完整交接给后续接手的开发、运维或 Linux 上的 Codex。
|
||||
|
||||
目标是回答 4 个问题:
|
||||
|
||||
1. 当前到底完成到了什么程度
|
||||
2. 这次 Linux 测试服已经验证通过了哪些内容
|
||||
3. 还有哪些事情没有做完
|
||||
4. 后续继续收口时,应该按什么顺序做
|
||||
|
||||
## 二、当前结论
|
||||
|
||||
当前项目状态可以明确分成两部分:
|
||||
|
||||
### 1. 已完成
|
||||
|
||||
- 本地 Windows 开发与联调已完成
|
||||
- `domain-api` 与 `domain-web` 已完成主要功能开发
|
||||
- Web/API 本地整栈自测已通过
|
||||
- 交付包、验包、SHA256、最新交付指针已完成
|
||||
- Linux 测试服数据库初始化问题已定位并修复
|
||||
- Linux 测试服在“临时 API 进程 + 已初始化数据库”的模式下,`smoke test` 已通过
|
||||
- Linux 测试服已经完成正式 `systemd` 服务化联调,`domaincheck-api` 与 `domaincheck-worker` 均已拉起
|
||||
- 正式服务态下 `/health` 已确认 `worker_mode = linux-systemd`
|
||||
- 正式服务态 `smoke test` 已通过
|
||||
- 已补做一轮真实导入回归,确认“导入域名 -> 写入 `domains` -> 自动创建 `detect_tasks`”链路正常
|
||||
|
||||
### 2. 未完全完成
|
||||
|
||||
- Linux 测试服虽然已完成正式服务化联调,但仍属于“测试服验证通过”,不等于生产观察期已经完成
|
||||
- Worker 当前通过 `QT_QPA_PLATFORM=offscreen` 运行,属于“无头 Qt 托管态”,后续仍建议继续观察稳定性
|
||||
- 真实业务网络环境下的长时检测、代理池质量、Wayback 首次全量列表耗时,还需要继续压测和观察
|
||||
- 当前数据库里仅导入了少量回归样本,不代表真实大批量数据已完成验收
|
||||
|
||||
一句话结论:
|
||||
|
||||
> 功能、数据库和正式服务化都已经打通;后续工作转入真实业务回归、稳定性观察和上线前优化。
|
||||
|
||||
## 三、这次 Linux 测试服已验证通过的内容
|
||||
|
||||
### 1. 数据库初始化问题已确认根因
|
||||
|
||||
本次 Linux 测试服最初失败的根因是:
|
||||
|
||||
- PostgreSQL 可连接
|
||||
- 但业务库是空库
|
||||
- 缺少 `domains` 等核心表
|
||||
- 导致这些 API 因 `psycopg2.errors.UndefinedTable` 直接 `500`
|
||||
|
||||
受影响接口至少包括:
|
||||
|
||||
- `/api/v1/dashboard/overview`
|
||||
- `/api/v1/detect/status`
|
||||
- `/api/v1/imports/summary`
|
||||
|
||||
### 2. 正确修复方式已确认
|
||||
|
||||
在 Linux 测试服执行:
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/getDomain/domainCheck
|
||||
python init_database.py
|
||||
```
|
||||
|
||||
执行后,核心业务表已成功创建/补齐:
|
||||
|
||||
- `domains`
|
||||
- `detect_tasks`
|
||||
- `domain_blacklist`
|
||||
- `sensitive_words`
|
||||
- `domain_detections`
|
||||
|
||||
数据库核查结果为:
|
||||
|
||||
- `table_count = 5`
|
||||
- `domains_count = 0`
|
||||
|
||||
说明:
|
||||
|
||||
- 库结构已正常
|
||||
- 只是当前还没有正式业务数据导入
|
||||
|
||||
### 3. 临时验证态 smoke test 已通过
|
||||
|
||||
新版 `smoke test` 结果:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true
|
||||
}
|
||||
```
|
||||
|
||||
这说明在当前测试服条件下:
|
||||
|
||||
- API 主服务逻辑可用
|
||||
- PostgreSQL 连接可用
|
||||
- Redis 连接可用
|
||||
- 缺表问题已解除
|
||||
|
||||
### 4. 临时验证态诊断包已导出
|
||||
|
||||
本次测试服诊断产物:
|
||||
|
||||
- 目录:`/www/wwwroot/getDomain/diagnostics/diag_20260416_133701`
|
||||
- 压缩包:`/www/wwwroot/getDomain/diagnostics/diag_20260416_133701.tar.gz`
|
||||
|
||||
可用于后续继续排障或归档。
|
||||
|
||||
## 四、正式服务态已补验证通过
|
||||
|
||||
在后续继续收口过程中,已经额外完成了正式 `systemd` 服务态验证,结果如下:
|
||||
|
||||
### 1. 正式服务已落地
|
||||
|
||||
已安装并启用:
|
||||
|
||||
- `domaincheck-api`
|
||||
- `domaincheck-worker`
|
||||
|
||||
并已确认两者为 `active (running)`。
|
||||
|
||||
### 2. 运行模式已切换成功
|
||||
|
||||
正式服务态下接口返回已确认:
|
||||
|
||||
- `/health` 中 `worker_mode = linux-systemd`
|
||||
- `/api/v1/runtime/preflight` 中 `worker_mode = linux-systemd`
|
||||
- `/api/v1/runtime/status` 中:
|
||||
- `api.service_name = domaincheck-api`
|
||||
- `worker.service_name = domaincheck-worker`
|
||||
- `worker.running = true`
|
||||
- `process_count = 1`
|
||||
|
||||
### 3. 正式服务态 smoke test 已通过
|
||||
|
||||
正式服务态下再次执行:
|
||||
|
||||
```bash
|
||||
python smoke_test.py --base-url http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
结果仍为:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 正式服务态诊断包已导出
|
||||
|
||||
正式服务态诊断产物:
|
||||
|
||||
- 目录:`/opt/domaincheck/diagnostics/diag_20260416_134923`
|
||||
- 压缩包:`/opt/domaincheck/diagnostics/diag_20260416_134923.tar.gz`
|
||||
|
||||
### 5. 正式服务态中已确认的兼容与权限问题
|
||||
|
||||
本轮继续联调还确认并处理了两类真实 Linux 问题:
|
||||
|
||||
- `detect/jucha.py`、`detect/juming.py` 中存在 Windows 专属 `subprocess.STARTUPINFO()` 写法,已改为跨平台兼容处理
|
||||
- 若曾以 `root` 手工运行过 API/Worker,可能会留下 `root` 所有者的运行文件,导致正式 `systemd` 服务用户无法写入
|
||||
|
||||
其中已实际踩到并修复的权限点包括:
|
||||
|
||||
- `domain-api/runtime/` 目录权限
|
||||
- `domainCheck/detect_worker.log` 文件权限
|
||||
|
||||
这个问题的表现是:
|
||||
|
||||
- `/api/v1/imports/upload` 因无法创建 `runtime/imports/` 返回 `500`
|
||||
- Worker 因无法写 `detect_worker.log` 进入循环重启
|
||||
|
||||
### 6. 运行中心控制链路已补通
|
||||
|
||||
本轮继续验证后,运行中心里的 Linux 控制动作也已经打通:
|
||||
|
||||
- Worker `start` / `stop` 已可通过 `sudo -n systemctl` 正常执行
|
||||
- API 自重启已改为 `systemctl --no-block restart domaincheck-api`
|
||||
|
||||
这样处理后,`systemd` 会异步接管重启流程,接口可以先返回成功,避免出现“服务其实已经重启成功,但调用方因为等待自身停机而收到 `500`”的误导性现象。
|
||||
|
||||
### 7. 服务态日志噪音已进一步收敛
|
||||
|
||||
本轮还额外处理了两类不会阻断功能、但会影响正式服务观察体验的日志噪音:
|
||||
|
||||
- Redis 配置订阅从阻塞 `listen()` 改为短轮询 `get_message()`,Linux 空闲时不再每分钟刷 `Redis订阅失败: Timeout reading from socket`
|
||||
- `offscreen` 模式下去掉 Qt 不支持的按钮样式属性,Worker 启动时不再刷 `Unknown property transition/transform/box-shadow`
|
||||
- Worker 图标资源定位改为优先使用 `detect_worker.py` 同目录,Linux 服务态不再误报 `/opt/new_logo.svg`、`/opt/favicon2.ico` 不存在
|
||||
- 付费检测器改为按需初始化,默认关闭 `detect_jucha` / `detect_juziseo` 时,不再在启动阶段报 cookie 文件缺失
|
||||
- Redis 未加载 Bloom 模块时保留为降级说明,继续使用普通缓存,不再作为故障级告警处理
|
||||
|
||||
这几项修改的结果是:
|
||||
|
||||
- `domaincheck-worker` 仍保持 `active (running)`
|
||||
- `/api/v1/runtime/status` 中 `worker.running = true`
|
||||
- 正式测试服日志更适合持续观察和上线前留档
|
||||
|
||||
## 五、这次联调后已经明确固化的部署规则
|
||||
|
||||
后续无论谁再部署到 Linux,新环境都必须遵守下面这条:
|
||||
|
||||
> 如果 PostgreSQL 使用的是新库,必须先执行 `domainCheck/init_database.py` 初始化数据库结构。
|
||||
|
||||
否则至少这些接口会直接失败:
|
||||
|
||||
- `/api/v1/dashboard/overview`
|
||||
- `/api/v1/detect/status`
|
||||
- `/api/v1/imports/summary`
|
||||
|
||||
这个规则已经同步补入:
|
||||
|
||||
- [05_domainCheck_Linux部署清单.md](./05_domainCheck_Linux部署清单.md)
|
||||
- [domain-api/deploy/linux/README.md](../domain-api/deploy/linux/README.md)
|
||||
|
||||
## 六、当前已完成项清单
|
||||
|
||||
以下内容可以视为“已经完成”:
|
||||
|
||||
### 1. 代码与仓库层
|
||||
|
||||
- `domainCheck` 已并入外层总仓库,不再是子模块指针
|
||||
- 根目录总 `README.md` 已补齐
|
||||
- `.gitignore` 已补强
|
||||
- 本地敏感文件、cookies、本地 Node runtime 已从 git 中移除
|
||||
|
||||
### 2. Web/API 层
|
||||
|
||||
- `domain-web` 主要页面已完成
|
||||
- `domain-api` 主要接口已完成
|
||||
- 运行中心、系统设置、导入、导出、日志诊断、自检、自测均已具备
|
||||
- 正式 `systemd` 服务态下 `/health`、`/runtime/preflight`、`/runtime/status`、`smoke test` 已全部通过
|
||||
|
||||
### 3. 交付层
|
||||
|
||||
- 交付包已生成
|
||||
- SHA256 校验已生成
|
||||
- 验包脚本可用
|
||||
- 发布准备报告可用
|
||||
- 最新交付指针可用
|
||||
|
||||
### 4. Linux 文档层
|
||||
|
||||
- Linux 部署清单已完成
|
||||
- Linux 诊断采集脚本已完成
|
||||
- Linux 联调输入清单已完成
|
||||
- 导航索引文档已完成
|
||||
|
||||
### 5. 真实业务回归层
|
||||
|
||||
- 已通过 API 上传样本 TXT
|
||||
- 已确认导入结果:
|
||||
- 总数 `5`
|
||||
- 有效 `3`
|
||||
- 新增 `3`
|
||||
- 无效 `2`
|
||||
- 已确认 `domains_total = 3`
|
||||
- 已确认 `detect_tasks_total = 3`
|
||||
- 已确认导入后会自动创建 `detect_tasks`
|
||||
|
||||
## 七、当前未完成项清单
|
||||
|
||||
以下内容仍属于“后续要做”:
|
||||
|
||||
### 1. Worker 真实联动验证
|
||||
|
||||
还应继续确认:
|
||||
|
||||
- Worker 在线状态
|
||||
- Worker 进程数
|
||||
- 检测控制页读取是否正常
|
||||
- `detect_worker.log` 是否正常写入
|
||||
|
||||
### 2. 导入更多真实数据后的业务复测
|
||||
|
||||
当前已经完成一轮小样本回归,不再是空库空表态。
|
||||
|
||||
后续应至少补一次真实业务复测:
|
||||
|
||||
- 导入更接近真实业务规模的域名样本
|
||||
- 查看 `domains` 持续增长
|
||||
- 查看 `detect_tasks` 持续生成
|
||||
- 再验证筛选与导出
|
||||
|
||||
### 3. 长时间运行与代理池观察
|
||||
|
||||
仍建议继续验证:
|
||||
|
||||
- Worker 长时运行稳定性
|
||||
- Redis 订阅超时后的重连是否持续稳定
|
||||
- 国内网络环境下代理池真实可用率
|
||||
- Wayback 首次全量快照列表的耗时表现
|
||||
|
||||
## 八、后续继续收口的推荐顺序
|
||||
|
||||
建议 Linux 上的下一位接手人严格按下面顺序执行。
|
||||
|
||||
### 第一步:确认目录完整
|
||||
|
||||
确认至少存在:
|
||||
|
||||
- `/opt/domaincheck/domainCheck`
|
||||
- `/opt/domaincheck/domain-api`
|
||||
- `/opt/domaincheck/domain-web`
|
||||
|
||||
### 第二步:确认数据库结构
|
||||
|
||||
如果是新库,先执行:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domainCheck
|
||||
python3 init_database.py
|
||||
```
|
||||
|
||||
然后确认:
|
||||
|
||||
```sql
|
||||
select tablename
|
||||
from pg_tables
|
||||
where schemaname = 'public'
|
||||
order by tablename;
|
||||
```
|
||||
|
||||
### 第三步:落 systemd
|
||||
|
||||
使用这些模板:
|
||||
|
||||
- `domain-api/deploy/systemd/domain-api.service`
|
||||
- `domain-api/deploy/systemd/domain-worker.service`
|
||||
|
||||
如果此前用 `root` 手工跑过 API 或 Worker,建议先确认下面这些路径对正式服务用户可写:
|
||||
|
||||
- `domain-api/runtime/`
|
||||
- `domainCheck/detect_worker.log`
|
||||
|
||||
### 第四步:启动正式服务
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable domaincheck-api
|
||||
sudo systemctl enable domaincheck-worker
|
||||
sudo systemctl start domaincheck-api
|
||||
sudo systemctl start domaincheck-worker
|
||||
```
|
||||
|
||||
### 第五步:检查服务状态
|
||||
|
||||
```bash
|
||||
systemctl status domaincheck-api --no-pager -l
|
||||
systemctl status domaincheck-worker --no-pager -l
|
||||
journalctl -u domaincheck-api -n 200 --no-pager
|
||||
journalctl -u domaincheck-worker -n 200 --no-pager
|
||||
```
|
||||
|
||||
### 第六步:检查 API 状态
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8100/health
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/preflight
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/status
|
||||
```
|
||||
|
||||
### 第七步:做一轮导入回归
|
||||
|
||||
至少验证:
|
||||
|
||||
- `/api/v1/imports/upload`
|
||||
- `/api/v1/imports/tasks`
|
||||
- `/api/v1/imports/summary`
|
||||
- `domains` 增长
|
||||
- `detect_tasks` 自动创建
|
||||
|
||||
目标是确认:
|
||||
|
||||
- `status = ok`
|
||||
- `worker_mode = linux-systemd`
|
||||
|
||||
### 第七步:运行 smoke test
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api/deploy/linux
|
||||
python3 smoke_test.py --base-url http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
### 第八步:如异常则导出诊断包
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api/deploy/linux
|
||||
bash collect_diagnostics.sh /opt/domaincheck
|
||||
```
|
||||
|
||||
## 九、后续交接给 Linux 上 Codex 时,最该提供的材料
|
||||
|
||||
如果后续换一位 Linux 上的 Codex 接手,优先给他这些:
|
||||
|
||||
### 1. 当前关键结论
|
||||
|
||||
- 当前最大已修复问题:数据库未初始化
|
||||
- 当前最大未收口问题:正式 `systemd` 服务态还没完全落定
|
||||
|
||||
### 2. 当前最关键文件
|
||||
|
||||
- `domainCheck/.env`
|
||||
- `api_health_curl.txt`
|
||||
- `api_preflight_curl.txt`
|
||||
- `api_runtime_curl.txt`
|
||||
- 诊断包:
|
||||
- `diag_20260416_133701.tar.gz`
|
||||
|
||||
### 3. 必看文档
|
||||
|
||||
- [12_domainCheck_导航索引.md](./12_domainCheck_导航索引.md)
|
||||
- [11_domainCheck_Linux联调输入清单.md](./11_domainCheck_Linux联调输入清单.md)
|
||||
- [05_domainCheck_Linux部署清单.md](./05_domainCheck_Linux部署清单.md)
|
||||
- [08_domainCheck_交付说明.md](./08_domainCheck_交付说明.md)
|
||||
|
||||
## 十、最终交接结论
|
||||
|
||||
当前项目不再是“开发未完成”,而是:
|
||||
|
||||
> 开发已完成,Linux 测试服联调已完成第一轮关键打通,剩余工作集中在正式服务化部署与上线前最后复测。
|
||||
|
||||
因此,对下一位接手者的要求不是“继续开发功能”,而是:
|
||||
|
||||
- 完成正式 Linux 服务落地
|
||||
- 跑正式服务态 smoke test
|
||||
- 如有异常,基于诊断包继续排障
|
||||
- 最终完成上线前收口
|
||||
278
docs/14_domainCheck_正式上线前最终检查单.md
Normal file
278
docs/14_domainCheck_正式上线前最终检查单.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# 14 domainCheck 正式上线前最终检查单
|
||||
|
||||
## 一、使用场景
|
||||
|
||||
本文档用于正式上线前最后一次收口。
|
||||
|
||||
适用前提:
|
||||
|
||||
- 代码已更新到最新版本
|
||||
- Linux 测试服已完成基础联调
|
||||
- PostgreSQL 已执行过 `domainCheck/init_database.py`
|
||||
- `domaincheck-api` 与 `domaincheck-worker` 已按 `systemd` 托管
|
||||
|
||||
如果当前仍处于“新机器首次部署”,请先回看:
|
||||
|
||||
- `docs/05_domainCheck_Linux部署清单.md`
|
||||
- `domain-api/deploy/linux/README.md`
|
||||
- `docs/13_domainCheck_Linux测试服交接文档.md`
|
||||
|
||||
如果后续进入“国外控制面 + 大陆执行面 + 多 Worker 扩容”阶段,请直接补充阅读:
|
||||
|
||||
- `docs/16_domainCheck_多机检测与跨地域部署设计.md`
|
||||
- `domain-api/deploy/multi-region/README.md`
|
||||
|
||||
如果当前已经进入“大陆 controller + 海外 control”双地域正式联调,还应额外确认:
|
||||
|
||||
- 大陆 `controller` 节点的 `/etc/default/domaincheck-worker`
|
||||
- `NODE_ROLE=control`
|
||||
- 大陆 `domaincheck-sync-agent`
|
||||
- 已启动并稳定运行
|
||||
- 海外控制面 `runtime/sync-summary`
|
||||
- 能看到 `detect_result_batches`
|
||||
|
||||
如果当前已经切到“海外单脑控制面统一驾驶”模式,建议同时配套阅读:
|
||||
|
||||
- `docs/25_domainCheck_海外单脑控制面上线收口总表.md`
|
||||
- `docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md`
|
||||
- `docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md`
|
||||
|
||||
## 二、上线前必须确认的结论
|
||||
|
||||
上线前至少要确认下面这些结论同时成立:
|
||||
|
||||
- `domaincheck-api` 为 `active (running)`
|
||||
- `domaincheck-worker` 为 `active (running)`
|
||||
- `/health` 返回 `worker_mode=linux-systemd`
|
||||
- `/api/v1/runtime/preflight` 返回 `ok=true`
|
||||
- `smoke test` 返回 `ok=true`
|
||||
- 运行中心里的 `start_worker / stop_worker / restart_api` 控制链路可用
|
||||
- 导入、筛选、批量更新、导出四条核心业务链路至少各回归一次
|
||||
- 诊断包可正常导出
|
||||
|
||||
## 三、正式上线前执行顺序
|
||||
|
||||
### 0. 先跑一遍统一上线总检
|
||||
|
||||
如果当前已经进入“海外单脑控制面 + 多地域 / Node Agent”这条正式链路,建议先跑:
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/getDomain/domain-api
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-check http://127.0.0.1:8100 http://152.53.37.118:8100 summary
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- `go_live_status` 为 `ready` 或至少没有新的 `blocking_reasons`
|
||||
- `stack_status` 不为 `blocked`
|
||||
- `route_surface_complete=true`
|
||||
- `launchpad_status` 不为 `blocked`
|
||||
- 如果当前已经纳管执行节点,则 `remote_access_ready` 不应长期为 `0`
|
||||
- `next_step_action_code` / `operator_title` 应能直接说明当前第一优先动作
|
||||
- 如果 `log_sync_enabled=true`,则要额外看 `log_sync_state`、`log_sync_covered_nodes`
|
||||
|
||||
如果这里已经出现 `bootstrap_run / run_acceptance`,说明当前上线前仍有节点接管缺口,应先收口首个缺口节点,再继续下面的业务核验。
|
||||
|
||||
建议这样理解总检输出:
|
||||
|
||||
- `blocking_reasons` 只放真正会阻断上线的项,例如 `remote_agent_ready=0`
|
||||
- `warnings` 表示还能继续联调,但现在还不适合直接宣称“全部收口”
|
||||
- `recommended_commands.next_step` 就是当前最值得优先执行的一条命令
|
||||
- `recommended_commands.log_sync_logs` / `recommended_commands.log_sync_inspection` 用来补远端参与节点的日志观测
|
||||
|
||||
### 1. 核对服务状态
|
||||
|
||||
```bash
|
||||
systemctl status domaincheck-api --no-pager -l
|
||||
systemctl status domaincheck-worker --no-pager -l
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- 两个服务都为 `active (running)`
|
||||
- `domaincheck-worker` 不再循环重启
|
||||
|
||||
如果当前是大陆 controller 节点,还要补一条:
|
||||
|
||||
```bash
|
||||
systemctl status domaincheck-sync-agent --no-pager -l
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- `domaincheck-sync-agent` 为 `active (running)`
|
||||
- 不循环重启
|
||||
|
||||
### 2. 核对健康接口
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8100/health
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/preflight
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/readiness
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/status
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- `/health` 返回 `status=ok`
|
||||
- `/health` 返回 `worker_mode=linux-systemd`
|
||||
- `/runtime/preflight` 返回 `ok=true`
|
||||
- `/runtime/readiness` 不应返回 `blocking`
|
||||
- `/runtime/status` 返回 `worker.running=true`
|
||||
|
||||
如果当前已经接入跨地域同步,还建议补看:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/sync-summary
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- 返回里能看到 `detect_result_batches`
|
||||
- 至少能区分:
|
||||
- `synced`
|
||||
- `projected`
|
||||
- `failed`
|
||||
- 若大陆 `sync-agent` 已接上,则最近执行过的检测任务不应长期停留在 `projected`
|
||||
|
||||
当前 `runtime/preflight` 还会额外展示:
|
||||
|
||||
- RedisBloom 是否安装,若未安装会明确提示“降级为普通缓存”
|
||||
- `detect_jucha` / `detect_juziseo` 是否启用
|
||||
- 若启用了付费检测,对应本地 cookie 文件是否已就绪
|
||||
|
||||
当前 `detect/status` / `runtime/status` 还会明确展示代理运行态:
|
||||
|
||||
- `代理正常`
|
||||
- `降级直连`
|
||||
- `等待代理`
|
||||
|
||||
解释:
|
||||
|
||||
- `降级直连` 表示代理池暂时无可用代理,但当前允许直连兜底,任务不会因此中断
|
||||
- `等待代理` 表示代理池无可用代理,且当前未允许直连,这会直接影响检测吞吐或导致步骤失败
|
||||
|
||||
当前还补充了两类更细的诊断语义:
|
||||
|
||||
- `proxy_runtime_reason=supplier_empty_pool`
|
||||
- 表示代理源最近都返回了正常 HTTP 响应,但原始代理数为 `0`
|
||||
- 这类问题更偏向供应侧空池,不是程序拉取失败
|
||||
- `dependency_alerts`
|
||||
- 表示外部依赖站点当前存在可观测异常
|
||||
- 例如 `web.archive.org` 拒连、超时、连接池异常等
|
||||
|
||||
当前免费检测链路中的外部依赖异常还采用了“降级继续”策略:
|
||||
|
||||
- 例如 `时光机 / 站长之家 / 爱站 / 百度 / 360` 这类外部站点出现明显网络波动、拒连、超时
|
||||
- 系统会优先记录为步骤级 `degraded`
|
||||
- 并将域名置为 `待人工复核`
|
||||
- 同时继续执行后续检测步骤,避免把整条任务链路直接污染成 `检测失败`
|
||||
|
||||
### 3. 跑正式服务态 smoke test
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api/deploy/linux
|
||||
python3 smoke_test.py --base-url http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
如需把 Web 首页一起纳入检查:
|
||||
|
||||
```bash
|
||||
python3 smoke_test.py --base-url http://127.0.0.1:8100 --web-url http://127.0.0.1
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- 输出中 `ok=true`
|
||||
|
||||
### 4. 回归运行中心控制动作
|
||||
|
||||
建议至少各执行一次:
|
||||
|
||||
- `start_worker`
|
||||
- `stop_worker`
|
||||
- `restart_api`
|
||||
|
||||
期望:
|
||||
|
||||
- `stop_worker` 后,`runtime/status` 中 `worker.running=false`
|
||||
- `start_worker` 后,`runtime/status` 中 `worker.running=true`
|
||||
- `restart_api` 调用返回成功,随后 API 能重新恢复
|
||||
|
||||
说明:
|
||||
|
||||
- 当前 Linux 正式服务态已改为 `systemctl --no-block restart domaincheck-api`
|
||||
- 因此 `restart_api` 会先返回成功,再由 `systemd` 异步完成 API 切换
|
||||
|
||||
### 5. 回归核心业务链路
|
||||
|
||||
建议至少确认下面 4 条:
|
||||
|
||||
- 导入域名成功,且会落到 `domains`
|
||||
- 导入后自动创建 `detect_tasks`
|
||||
- 筛选接口 `/api/v1/domains` 返回正常
|
||||
- 批量更新后数据库字段与页面展示一致
|
||||
- 导出任务可创建、导出文件可下载
|
||||
|
||||
如果时间紧,最小回归顺序建议为:
|
||||
|
||||
1. 导入一份小样本
|
||||
2. 查看导入任务结果
|
||||
3. 查看域名列表
|
||||
4. 执行一次批量更新
|
||||
5. 生成一次 TXT 或 CSV 导出
|
||||
|
||||
## 四、建议保留的上线证据
|
||||
|
||||
正式上线前,建议至少保留下面这些结果:
|
||||
|
||||
- `systemctl status domaincheck-api --no-pager -l`
|
||||
- `systemctl status domaincheck-worker --no-pager -l`
|
||||
- `journalctl -u domaincheck-api -n 200 --no-pager`
|
||||
- `journalctl -u domaincheck-worker -n 200 --no-pager`
|
||||
- `systemctl status domaincheck-sync-agent --no-pager -l`
|
||||
- `journalctl -u domaincheck-sync-agent -n 200 --no-pager`
|
||||
- `/health` 返回
|
||||
- `/api/v1/runtime/preflight` 返回
|
||||
- `/api/v1/runtime/sync-summary` 返回
|
||||
- `smoke_test.py` 输出
|
||||
- 一份最新诊断包
|
||||
|
||||
诊断包导出命令:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api/deploy/linux
|
||||
bash collect_diagnostics.sh /opt/domaincheck
|
||||
```
|
||||
|
||||
## 五、当前可接受的非阻断项
|
||||
|
||||
以下项目目前已确认不会阻断正式服务运行:
|
||||
|
||||
- Redis 未安装 Bloom 模块时,会降级为普通缓存
|
||||
- `worker` 在 `QT_QPA_PLATFORM=offscreen` 下无头运行
|
||||
- 付费检测默认关闭时,不要求本机预置 `jucha` / `juziseo` cookie 文件
|
||||
|
||||
这些项可以在后续优化阶段继续增强,但不应再作为当前上线阻塞条件。
|
||||
|
||||
## 六、仍建议继续观察的项
|
||||
|
||||
以下内容不属于当前功能阻断,但上线后建议继续观察:
|
||||
|
||||
- 真实代理池可用率
|
||||
- 代理为空时是否长期停留在 `降级直连`
|
||||
- Wayback 首次全量检测耗时
|
||||
- 长时间运行下的 Worker 稳定性
|
||||
- 真实业务数据量上升后的数据库与导出耗时
|
||||
|
||||
## 七、最终上线判定
|
||||
|
||||
如果下面三类检查都通过,就可以视为已经具备正式上线条件:
|
||||
|
||||
- 服务状态检查通过
|
||||
- 核心接口与 `smoke test` 通过
|
||||
- 核心业务链路回归通过
|
||||
|
||||
一句话判定:
|
||||
|
||||
> 当前项目已经完成开发、Linux 测试服联调、正式服务态验证和关键日志降噪;剩余工作主要是正式环境发布与上线后观察,不再是功能性大修。
|
||||
59
docs/15_domainCheck_Web对齐旧桌面功能核对表.md
Normal file
59
docs/15_domainCheck_Web对齐旧桌面功能核对表.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# domainCheck Web 对齐旧桌面功能核对表
|
||||
|
||||
更新时间:2026-04-16
|
||||
|
||||
## 一、旧桌面主标签页对齐
|
||||
|
||||
| 旧桌面标签 | Web 当前状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 聚名爬取 | 已补齐 | 已支持聚名账号密码登录、聚查自动联名、过期删除/一口价采集、Cookie 兜底上传 |
|
||||
| 域名筛选 | 已补齐主干 | 已补“全部”默认选项,支持查询、分页、批量更新、筛选页导出范围,并继续补回旧桌面明细列 |
|
||||
| 域名导入 | 已补齐主干 | 已支持 TXT 上传导入,也已补回手工粘贴域名创建导入任务 |
|
||||
| 敏感词配置 | 已补齐 | 本轮新增独立页面,支持加载、编辑、导入、导出、保存 |
|
||||
| 系统设置 | 已补齐主干 | 已补桔子SEO 登录入口;聚名登录入口放在“聚名采集”页 |
|
||||
|
||||
## 二、旧桌面登录能力对齐
|
||||
|
||||
| 能力 | Web 当前状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 聚名账号密码登录 | 已补齐 | 位于 `#/juming` |
|
||||
| 聚查联名登录 | 已补齐 | 聚名登录后自动执行,同时提供手动“重新联名登录聚查” |
|
||||
| 桔子SEO 登录 | 已补齐 | 位于 `#/settings` 的“第三方登录”卡片 |
|
||||
|
||||
## 三、已确认补齐的体验项
|
||||
|
||||
- 域名筛选下拉框显式提供“全部”
|
||||
- 桔子SEO 不再遗漏登录入口
|
||||
- 敏感词配置不再缺页
|
||||
- 聚查不只依赖自动联名,也可手动重试
|
||||
- 域名导入已补回“粘贴域名后直接导入”
|
||||
- 筛选页已补回“当前页 / 导出几页 / 全部”的导出范围能力
|
||||
- 筛选页已补回旧桌面常用明细列:过期时间、单位性质、百度历史、百度Site、中文标题、360 Site、Google Site
|
||||
- 批量更新已补回上述检测明细字段的人工修正入口
|
||||
- CSV / Excel 导出已补回旧桌面常用明细列,避免导出结果比桌面版缩水
|
||||
- 聚名页面已显式展示“已保存账号 / 聚名登录态 / 聚查联名状态”,避免运营误判
|
||||
- 系统设置页已显式展示“已保存桔子SEO账号 / Cookie 就绪状态”,并同步持久化到本地与 Redis
|
||||
- 聚名采集、域名导入、检测控制三条长任务链路均已统一为“任务中心”形态,支持阶段态、日志常驻、切页后回看
|
||||
- 检测控制页已补齐更细的阶段态展示,可识别“准备检测 / 刷新代理池 / 取任务中 / 建线程中 / 检测中 / 批次完成 / 完成归档”
|
||||
- 检测控制页已补齐阶段切换时间线,便于回看长任务在何时进入哪个阶段
|
||||
- 聚名采集页已补齐中文状态标签、当前采集阶段与任务概览卡片,避免运营面对英文状态误判
|
||||
- 域名导入页已补齐“选中文件预估行数”和“当前导入阶段/任务概览”摘要,更接近旧桌面即时反馈体验
|
||||
- 域名导入页已补齐“前 10 行本地预览”和“大文件任务提示”,降低误传错文件的概率
|
||||
- 域名导入页已补齐提交前本地预检,可即时展示“有效 / 重复 / 非法”统计
|
||||
- 域名导入页已补齐“来源类型”选择与任务展示,导入记录可区分 TXT 导入 / 手工录入 / 其它
|
||||
- 域名筛选页已补齐“单位性质”筛选,进一步对齐旧桌面常用条件
|
||||
- 域名筛选页已补齐“来源类型”筛选;导入页完成后可一键跳转到筛选页查看对应来源结果
|
||||
- 聚名采集、域名导入、检测控制三页的任务中心文案已统一,均按“阶段 / 摘要 / 日志 / 回看”同一口径表达
|
||||
|
||||
## 四、下一轮继续核对的次级项
|
||||
|
||||
- 旧桌面导入页的少量细节交互,是否还需要补更细的批次说明
|
||||
- 旧桌面检测控制页的少量状态提示文案,是否还需要继续压词统一
|
||||
- 旧桌面批量筛选中的少量边缘筛选项,是否还有遗漏
|
||||
|
||||
## 五、当前可直接验证的页面
|
||||
|
||||
- `http://152.53.37.118:3201/#/juming`
|
||||
- `http://152.53.37.118:3201/#/domains`
|
||||
- `http://152.53.37.118:3201/#/settings`
|
||||
- `http://152.53.37.118:3201/#/sensitive-words`
|
||||
796
docs/16_domainCheck_多机检测与跨地域部署设计.md
Normal file
796
docs/16_domainCheck_多机检测与跨地域部署设计.md
Normal file
@@ -0,0 +1,796 @@
|
||||
# 16 domainCheck 多机检测与跨地域部署设计
|
||||
|
||||
## 一、目标
|
||||
|
||||
本文档用于固化 `domainCheck` 的正式多机落地方案,满足下面这些约束:
|
||||
|
||||
- Web 后台、管理 API 必须部署在国外机器
|
||||
- 检测执行、代理、Redis、运行态存储部署在大陆机器
|
||||
- 最终结果、配置、归档、备份以国外机器为主
|
||||
- 初期部署不复杂,支持从 `国外 1 台 + 大陆 1 台` 起步
|
||||
- 后期不够时,优先横向增加大陆 Worker,不推翻整体架构
|
||||
|
||||
一句话原则:
|
||||
|
||||
> 国外负责“管、看、存、备份”,大陆负责“跑、调度、抢任务、贴近代理资源”。
|
||||
|
||||
## 二、当前落地状态
|
||||
|
||||
截至 `2026-04-16`,第一阶段多机运行骨架已经完成,当前代码已具备:
|
||||
|
||||
- 控制面节点注册与心跳
|
||||
- 执行面节点注册与心跳
|
||||
- 运行库骨架表自动初始化
|
||||
- 集群节点快照接口
|
||||
- 国外/大陆两套部署脚手架
|
||||
|
||||
当前已落地的运行态表:
|
||||
|
||||
- `detect_worker_nodes`
|
||||
- `detect_jobs`
|
||||
- `detect_job_items`
|
||||
- `detect_run_events`
|
||||
- `detect_sync_records`
|
||||
|
||||
当前可直接验证的接口:
|
||||
|
||||
- `GET /api/v1/runtime/status`
|
||||
- `GET /api/v1/runtime/readiness`
|
||||
- `GET /api/v1/runtime/cluster`
|
||||
- `GET /api/v1/detect/job/active`
|
||||
- `GET /api/v1/detect/jobs`
|
||||
- `GET /api/v1/detect/queue-summary`
|
||||
|
||||
当前 `runtime/cluster` 还补充了 `summary` 摘要,至少会返回:
|
||||
|
||||
- `status_counts`
|
||||
- `role_counts`
|
||||
- `region_counts`
|
||||
- `online_worker_nodes`
|
||||
- `online_control_nodes`
|
||||
- `busy_nodes`
|
||||
- `stale_nodes`
|
||||
- `offline_nodes`
|
||||
|
||||
当前还补充了同步观测骨架:
|
||||
|
||||
- `GET /api/v1/runtime/sync-summary`
|
||||
- `GET /api/v1/runtime/sync-records`
|
||||
|
||||
可用于提前观察:
|
||||
|
||||
- 当前节点是否启用同步推送
|
||||
- 源地域 / 目标地域配置是否正确
|
||||
- `detect_sync_records` 最近状态分布
|
||||
|
||||
当前代码还补了一层“运行态自动投影”:
|
||||
|
||||
- 控制面在读取 `runtime/status` 时,会把当前运行摘要按去重策略写入 `detect_sync_records`
|
||||
- 当前记录类型为:
|
||||
- `runtime_projection`
|
||||
- 当前还新增了“结果摘要投影”:
|
||||
- `detect_result_projection`
|
||||
- 用于把当前活跃任务的摘要、最近阶段事件、任务收敛进度先沉淀到统一同步面板
|
||||
- 其作用不是替代后续真正的 `sync-service`
|
||||
- 而是先保证跨地域部署阶段已经有统一可观察的“同步记录面板”
|
||||
|
||||
当前还补上了正式同步最小闭环骨架:
|
||||
|
||||
- 大陆执行面可通过 `SYNC_TARGET_API_BASE_URL` 指向国外控制面
|
||||
- 若 `SYNC_PUSH_ENABLED=true`,应由大陆 `domaincheck-sync-agent` 按轮询间隔自动推送最新运行态投影
|
||||
- 国外控制面通过:
|
||||
- `POST /api/v1/runtime/sync-ingest`
|
||||
接收投影
|
||||
- 若配置了 `SYNC_SHARED_TOKEN`,接收端会校验:
|
||||
- `X-Domaincheck-Sync-Token`
|
||||
|
||||
因此当前虽然还没有完整业务结果同步服务,但“同步协议、发送端、接收端、记录面板、独立同步代理”都已经有了第一版可运行骨架
|
||||
|
||||
当前同步骨架已经支持的记录类型包括:
|
||||
|
||||
- `runtime_projection`
|
||||
- `runtime_ingest`
|
||||
- `detect_result_projection`
|
||||
- `detect_result_ingest`
|
||||
- `runtime_push`
|
||||
|
||||
当前这一轮还补上了“结果批次同步可观测”能力:
|
||||
|
||||
- `GET /api/v1/runtime/sync-summary` 现在会额外返回:
|
||||
- `detect_result_batches`
|
||||
- 可直接按最近检测任务查看:
|
||||
- 是否已生成结果投影
|
||||
- 是否已推送
|
||||
- 是否已被目标地域接收
|
||||
- 最近一次失败原因
|
||||
- 当前同步策略也已细化为:
|
||||
- `runtime_projection`
|
||||
只推最新一条,避免把历史运行态投影整批补传
|
||||
- `detect_result_projection`
|
||||
按批次补推,确保检测结果积压可以自动追平
|
||||
- 大陆 `controller` 的环境模板也已固定为:
|
||||
- `NODE_ROLE=control`
|
||||
避免把 controller 误注册成普通 Worker,导致运行中心和 sync-agent 承载判断失真
|
||||
|
||||
当前这一轮还额外补齐了“检测会话追踪”能力:
|
||||
|
||||
- `POST /api/v1/detect/start` 会生成本轮 `cycle_token`
|
||||
- `cycle_token` 会进入 Worker 控制指令
|
||||
- Worker 心跳元数据会回写 `cycle_token / job_id / job_code`
|
||||
- `domain_started / domain_completed / domain_failed` 事件会附带 `cycle_token`
|
||||
- `GET /api/v1/detect/job/active` 已支持按当前 `cycle_token` 聚合“本轮事件”
|
||||
|
||||
当前运行态还补齐了“代理执行语义”:
|
||||
|
||||
- 代理可用时显示 `代理正常`
|
||||
- 代理暂时不可用但允许直连时显示 `降级直连`
|
||||
- 代理暂时不可用且不允许直连时显示 `等待代理`
|
||||
- 当代理源全部 `HTTP 200` 但 `raw_items=0` 时,会额外标记为“供应池为空”,避免误判成程序异常
|
||||
|
||||
当前阶段的准确表述应为:
|
||||
|
||||
> 多机运行骨架已经落地,分布式调度与跨地域结果同步进入下一阶段。
|
||||
|
||||
截至当前这一轮代码,最小任务闭环也已经接上:
|
||||
|
||||
- `POST /api/v1/detect/start` 会先创建 `detect_jobs`
|
||||
- Worker 会优先从 `detect_job_items` 领取任务
|
||||
- 运行中心已能显示当前活跃任务摘要
|
||||
- 节点状态里已能反映 `busy / current_load`
|
||||
- Worker 已支持小批量领取、任务续租、过期租约回收
|
||||
- API 控制面节点已支持定时心跳,避免集群视图把控制面误判为离线
|
||||
- 活跃任务接口已支持节点分布、进度百分比和最近事件回看
|
||||
- Worker 进程重启后会主动回收当前节点遗留的 `running / claimed` 运行态,避免后台出现“进程已重启但旧任务仍显示运行中”的残影
|
||||
|
||||
这意味着后续新增第二台大陆 Worker 时,已经不再是“完全从零设计”的状态,而是可以在现有骨架上继续细化调度策略。
|
||||
|
||||
当前最小联调命令也已经固定为:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/check_cluster.sh http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
这条命令会连续检查:
|
||||
|
||||
- `/health`
|
||||
- `/api/v1/runtime/cluster`
|
||||
- `/api/v1/detect/status`
|
||||
- `/api/v1/detect/job/active`
|
||||
|
||||
如需单独检查“跨地域同步骨架是否已接上”,建议再补两条:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/sync-summary
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/sync-records?limit=10
|
||||
```
|
||||
|
||||
如需快速拿到“当前这套多机部署是否已进入可联调 / 待处理 / 阻断”结论,当前也已经固定了:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/readiness
|
||||
```
|
||||
|
||||
该接口会直接给出:
|
||||
|
||||
- `status`
|
||||
- `ready`
|
||||
- `attention`
|
||||
- `blocking`
|
||||
- `summary`
|
||||
- `blocking_issues`
|
||||
- `warnings`
|
||||
- `info`
|
||||
|
||||
如果这两条接口已经能看到:
|
||||
|
||||
- `source_region / target_region`
|
||||
- `records_total > 0`
|
||||
- 最近记录里出现 `runtime_projection`
|
||||
|
||||
则说明当前测试服已经具备:
|
||||
|
||||
- 同步配置观测入口
|
||||
- 同步记录落库入口
|
||||
- 后续接入正式 `sync-service` 的最小运行骨架
|
||||
|
||||
如果要在大陆 controller 节点本机确认“这台机器本身是否配成了 controller,而不是普通 Worker”,当前也已经固定了一条本机检查命令:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/check_mainland_controller.sh
|
||||
```
|
||||
|
||||
这条命令会直接校验:
|
||||
|
||||
- `/etc/default/domaincheck-worker`
|
||||
- `NODE_ROLE=control`
|
||||
- `SYNC_PUSH_ENABLED=true`
|
||||
- `SYNC_TARGET_API_BASE_URL` 是否已填写
|
||||
- `domaincheck-worker`
|
||||
- `domaincheck-sync-agent`
|
||||
是否已经启动
|
||||
|
||||
如果当前客观条件下还不能把代码真正部署到大陆机器,当前也支持先在国外测试机上做“模拟多节点联调”:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/simulate_multi_region.sh http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
这条命令会临时模拟:
|
||||
|
||||
- 一个大陆 `controller`
|
||||
- 一个大陆 `worker`
|
||||
|
||||
它的目的不是替代真实部署,而是先把下面这些提前跑通:
|
||||
|
||||
- `runtime/readiness`
|
||||
- `runtime/cluster`
|
||||
- 运行中心的多机就绪度提示
|
||||
- 文档、脚本、状态面板三者是否一致
|
||||
|
||||
如果测试服之前已经跑过旧节点、旧 worker,当前还残留陈旧心跳记录,也可以先清一次 `detect_worker_nodes` 里的历史残影,再观察 readiness:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/prune_cluster_nodes.sh --minutes 30 --dry-run
|
||||
bash deploy/multi-region/prune_cluster_nodes.sh --minutes 30
|
||||
```
|
||||
|
||||
它的作用是:
|
||||
|
||||
- 清掉很久没心跳的旧节点记录
|
||||
- 避免运行中心长期被历史离线节点污染成 `attention`
|
||||
- 让单机模拟多节点联调时,看到更接近真实接入后的状态
|
||||
|
||||
## 三点五、当前实测结论
|
||||
|
||||
截至 `2026-04-16 18:56`,测试服已经验证通过:
|
||||
|
||||
- `domaincheck-api` 与 `domaincheck-worker` 可在 `systemd` 下稳定重启
|
||||
- `worker_mode=linux-systemd`
|
||||
- `runtime/cluster` 可同时看到:
|
||||
- `overseas-control-01`
|
||||
- `mainland-worker-01`
|
||||
- 大陆 Worker 节点元数据已显示:
|
||||
- `phase`
|
||||
- `detail`
|
||||
- `job_id`
|
||||
- `job_code`
|
||||
- `cycle_token`
|
||||
- `detect/job/active` 的 `current_cycle_events` 已只回看当前这一轮检测事件,不再混入旧轮次历史
|
||||
|
||||
当前测试服最新一轮实测 `cycle_token` 示例:
|
||||
|
||||
- `aec105737f`
|
||||
|
||||
该轮已确认能看到:
|
||||
|
||||
- `job_dispatch_requested`
|
||||
- `job_dispatch_sent`
|
||||
- `domain_started`
|
||||
- `domain_completed`
|
||||
|
||||
这说明“控制面发起一次检测”到“执行面逐域名回写事件”的会话闭环已经打通。
|
||||
也说明当前后台已经不再只会显示“有告警”,而是能明确说明任务到底是在正常代理、降级直连,还是被代理卡住。
|
||||
|
||||
## 四、推荐架构
|
||||
|
||||
### 1. 国外控制面
|
||||
|
||||
国外机器负责:
|
||||
|
||||
- `domain-web`
|
||||
- `domain-api`
|
||||
- 国外主 PostgreSQL
|
||||
- 配置中心
|
||||
- 导出、审核、运营后台
|
||||
- 最终结果归档
|
||||
- 国外备份与日志归档
|
||||
|
||||
国外控制面的职责:
|
||||
|
||||
- 对外提供访问入口
|
||||
- 保存最终业务结果
|
||||
- 保存系统配置和审计记录
|
||||
- 接收大陆执行面的结果同步
|
||||
- 为后续灾备提供稳定的权威数据源
|
||||
|
||||
### 2. 大陆执行面
|
||||
|
||||
大陆机器负责:
|
||||
|
||||
- `detect-worker`
|
||||
- 大陆 Redis
|
||||
- 大陆运行库 PostgreSQL
|
||||
- 代理池配置与网络环境
|
||||
- 本地运行日志
|
||||
- 调度和任务租约
|
||||
|
||||
大陆执行面的职责:
|
||||
|
||||
- 抢任务
|
||||
- 续租
|
||||
- 运行检测链路
|
||||
- 写入本地运行态
|
||||
- 汇总并同步结果到国外
|
||||
|
||||
### 3. 初期物理部署
|
||||
|
||||
当前最优起步方案:
|
||||
|
||||
- 国外 `1` 台:
|
||||
- `domain-web`
|
||||
- `domain-api`
|
||||
- `postgresql_main`
|
||||
- 大陆 `1` 台:
|
||||
- `redis`
|
||||
- `postgresql_runtime`
|
||||
- `scheduler`
|
||||
- `detect-worker`
|
||||
|
||||
说明:
|
||||
|
||||
- 这个起步方案的优先目标是先把跨地域职责边界定清楚
|
||||
- 大陆机器当前可以先把 Redis、运行库、调度和 Worker 放在同一台
|
||||
- 但逻辑上必须按不同角色设计,避免后续扩容时重新返工
|
||||
- 各节点身份建议统一通过 `/etc/default/domaincheck-api` 与 `/etc/default/domaincheck-worker` 管理,不直接修改 service 文件正文
|
||||
|
||||
### 4. 后续扩容
|
||||
|
||||
当大陆执行压力不够时,扩容顺序建议为:
|
||||
|
||||
1. 新增大陆 Worker 机器
|
||||
2. 如果 Redis 压力增大,再拆 Redis
|
||||
3. 如果运行库写入压力增大,再拆运行库
|
||||
4. 国外主库继续作为最终结果主库,不参与高频任务调度
|
||||
|
||||
后续结构示意:
|
||||
|
||||
```text
|
||||
国外
|
||||
├── web + api + postgresql_main
|
||||
└── backup / archive
|
||||
|
||||
大陆
|
||||
├── redis + postgresql_runtime + scheduler
|
||||
├── worker-01
|
||||
├── worker-02
|
||||
├── worker-03
|
||||
└── worker-N
|
||||
```
|
||||
|
||||
## 五、数据分层
|
||||
|
||||
### 1. 结果态数据
|
||||
|
||||
这类数据保存在国外主库:
|
||||
|
||||
- 域名主数据
|
||||
- 检测最终结果
|
||||
- 黑名单结论
|
||||
- 导出记录
|
||||
- 审核记录
|
||||
- 系统配置
|
||||
- 操作审计
|
||||
|
||||
特点:
|
||||
|
||||
- 最终一致
|
||||
- 生命周期长
|
||||
- 提供给后台页面和运营使用
|
||||
|
||||
### 2. 运行态数据
|
||||
|
||||
这类数据优先保存在大陆执行面:
|
||||
|
||||
- 任务领取状态
|
||||
- 任务租约
|
||||
- 节点心跳
|
||||
- 当前阶段
|
||||
- 实时日志事件
|
||||
- 重试信息
|
||||
- 本地暂存结果
|
||||
|
||||
特点:
|
||||
|
||||
- 高频读写
|
||||
- 延迟敏感
|
||||
- 主要服务于 Worker 协作和调度
|
||||
|
||||
## 六、任务模型
|
||||
|
||||
当前项目还偏向单机 Worker 直接扫描 `domains` 表的模式。正式多机化后,建议改为显式任务模型。
|
||||
|
||||
### 1. 核心表建议
|
||||
|
||||
建议新增:
|
||||
|
||||
- `detect_jobs`
|
||||
- `detect_job_items`
|
||||
- `detect_worker_nodes`
|
||||
- `detect_run_events`
|
||||
- `detect_sync_records`
|
||||
|
||||
### 2. detect_jobs
|
||||
|
||||
表示一轮检测任务。
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `job_code`
|
||||
- `source`
|
||||
- `plan_hash`
|
||||
- `status`
|
||||
- `created_at`
|
||||
- `started_at`
|
||||
- `finished_at`
|
||||
- `created_by`
|
||||
- `remark`
|
||||
|
||||
说明:
|
||||
|
||||
- `plan_hash` 用于标识本轮检测所使用的规则版本和参数快照
|
||||
- 一轮任务可以对应大量域名任务项
|
||||
|
||||
### 3. detect_job_items
|
||||
|
||||
表示单个域名的具体任务项。
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `job_id`
|
||||
- `domain_id`
|
||||
- `status`
|
||||
- `claimed_by`
|
||||
- `claim_token`
|
||||
- `lease_expires_at`
|
||||
- `attempt_count`
|
||||
- `last_error`
|
||||
- `started_at`
|
||||
- `finished_at`
|
||||
- `result_version`
|
||||
- `updated_at`
|
||||
|
||||
建议唯一约束:
|
||||
|
||||
- `unique(job_id, domain_id)`
|
||||
|
||||
说明:
|
||||
|
||||
- 多台 Worker 只抢 `status=pending` 且未被占用或租约已过期的任务
|
||||
- `claim_token` 用于避免状态回写串单
|
||||
- `lease_expires_at` 用于机器故障后的任务回收
|
||||
|
||||
### 4. detect_worker_nodes
|
||||
|
||||
表示 Worker 节点。
|
||||
|
||||
建议字段:
|
||||
|
||||
- `node_code`
|
||||
- `region`
|
||||
- `role`
|
||||
- `hostname`
|
||||
- `ip`
|
||||
- `status`
|
||||
- `worker_version`
|
||||
- `last_heartbeat_at`
|
||||
- `current_load`
|
||||
- `remark`
|
||||
|
||||
说明:
|
||||
|
||||
- 后台后续可以直接展示“哪个节点在线、哪个节点在跑、当前负载多少”
|
||||
|
||||
### 5. detect_run_events
|
||||
|
||||
表示高价值阶段日志。
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `job_id`
|
||||
- `job_item_id`
|
||||
- `node_code`
|
||||
- `event_type`
|
||||
- `level`
|
||||
- `message`
|
||||
- `payload_json`
|
||||
- `created_at`
|
||||
|
||||
说明:
|
||||
|
||||
- 页面展示优先依赖事件流,不直接硬依赖某一台机器本地日志文件
|
||||
- 原始大日志仍保留在大陆 Worker 本地
|
||||
|
||||
## 七、多机抢任务与去重
|
||||
|
||||
### 1. 抢任务方式
|
||||
|
||||
推荐使用数据库租约模型:
|
||||
|
||||
- Worker 从 `detect_job_items` 中领取一批待处理任务
|
||||
- 使用 `FOR UPDATE SKIP LOCKED` 或原子更新方式抢占
|
||||
- 领取后写入:
|
||||
- `claimed_by`
|
||||
- `claim_token`
|
||||
- `lease_expires_at`
|
||||
|
||||
### 2. 去重原则
|
||||
|
||||
多机环境下,去重不能依赖“约定不重复”,必须依赖数据库约束和租约。
|
||||
|
||||
至少保证:
|
||||
|
||||
- 同一轮 `job_id` 下,同一域名只出现一条任务项
|
||||
- 同一任务项同一时刻只允许被一个 `claim_token` 持有
|
||||
- 回写结果时校验 `claim_token`
|
||||
|
||||
### 3. 续租机制
|
||||
|
||||
Worker 执行过程中应定期续租:
|
||||
|
||||
- 每 `30-60` 秒续租一次
|
||||
- 续租时更新 `lease_expires_at`
|
||||
- 如果节点挂掉,租约到期后其他 Worker 可重新领取
|
||||
|
||||
当前代码已实现的原则是:
|
||||
|
||||
- 任务被领取后进入 `claimed / running`
|
||||
- 检测步骤执行过程中会持续续租
|
||||
- 若任务长期未续租且租约过期,会自动回收到 `pending`
|
||||
|
||||
这样可以避免:
|
||||
|
||||
- 长任务跑到一半租约失效
|
||||
- Worker 异常退出后任务永远卡死
|
||||
- 后续多机扩容时出现大量“假占用”
|
||||
|
||||
### 4. 失败重试
|
||||
|
||||
建议对失败进行分类:
|
||||
|
||||
- 网络失败
|
||||
- 代理失败
|
||||
- 第三方目标站异常
|
||||
- 程序逻辑失败
|
||||
|
||||
可按类型控制重试次数,不要无限重试。
|
||||
|
||||
### 5. 当前代码与目标模型的关系
|
||||
|
||||
当前代码里,运行态表和节点心跳已经具备,但主检测流程仍以现有 `domains` / `detect_status` 链路为主。
|
||||
|
||||
这意味着:
|
||||
|
||||
- 现在已经可以先把“多机可见性”和“节点骨架”跑起来
|
||||
- 下一步要把“检测入口”从直接扫 `domains`,逐步切到 `detect_jobs + detect_job_items`
|
||||
- 切换时必须保留旧链路回退能力,避免一次性重写导致现网不稳
|
||||
|
||||
## 八、同步策略
|
||||
|
||||
### 1. 国外到大陆
|
||||
|
||||
同步内容:
|
||||
|
||||
- 系统配置
|
||||
- 检测规则
|
||||
- 敏感词版本
|
||||
- 任务创建命令
|
||||
|
||||
特点:
|
||||
|
||||
- 低频
|
||||
- 要求可靠
|
||||
- 可版本化
|
||||
|
||||
### 2. 大陆到国外
|
||||
|
||||
同步内容:
|
||||
|
||||
- 任务进度摘要
|
||||
- 关键阶段事件
|
||||
- 最终检测结果
|
||||
- 黑名单结论
|
||||
- 归档日志包索引
|
||||
|
||||
特点:
|
||||
|
||||
- 高频部分只传摘要和关键事件
|
||||
- 最终结果必须幂等
|
||||
|
||||
### 3. 幂等要求
|
||||
|
||||
结果同步到国外时,必须支持幂等:
|
||||
|
||||
- 同一 `job_item_id` 重复上报不应产生重复结果
|
||||
- 同一域名同一轮任务只保留最终有效状态
|
||||
|
||||
### 4. 推荐同步落地方式
|
||||
|
||||
第一阶段不建议直接做数据库双向复制,更推荐独立同步服务:
|
||||
|
||||
- 大陆执行面负责写本地运行态
|
||||
- `sync-service` 负责批量汇总结果与事件
|
||||
- 国外控制面负责接收、落库、归档
|
||||
|
||||
推荐第一阶段同步内容:
|
||||
|
||||
- 最终检测结果
|
||||
- 关键阶段事件
|
||||
- 失败摘要
|
||||
- 节点健康摘要
|
||||
- 配置快照版本
|
||||
|
||||
不建议第一阶段同步:
|
||||
|
||||
- 全量原始日志
|
||||
- 高频心跳明细
|
||||
- 临时抓取中间产物
|
||||
|
||||
原因:
|
||||
|
||||
- 成本高
|
||||
- 跨地域网络抖动会放大耦合
|
||||
- 对运营后台价值不成比例
|
||||
|
||||
## 九、部署建议
|
||||
|
||||
### 1. 国外机器
|
||||
|
||||
目录建议:
|
||||
|
||||
```text
|
||||
/opt/domaincheck
|
||||
├── domain-api
|
||||
├── domain-web
|
||||
└── shared
|
||||
```
|
||||
|
||||
部署角色:
|
||||
|
||||
- `web`
|
||||
- `api`
|
||||
- `postgresql_main`
|
||||
|
||||
### 2. 大陆调度中心
|
||||
|
||||
目录建议:
|
||||
|
||||
```text
|
||||
/opt/domaincheck
|
||||
├── domainCheck
|
||||
├── runtime-db
|
||||
├── redis
|
||||
└── shared
|
||||
```
|
||||
|
||||
部署角色:
|
||||
|
||||
- `scheduler`
|
||||
- `redis`
|
||||
- `postgresql_runtime`
|
||||
- `worker`
|
||||
|
||||
### 3. 大陆纯 Worker 节点
|
||||
|
||||
目录建议:
|
||||
|
||||
```text
|
||||
/opt/domaincheck
|
||||
├── domainCheck
|
||||
└── shared
|
||||
```
|
||||
|
||||
部署角色:
|
||||
|
||||
- `worker`
|
||||
|
||||
### 4. 一键化原则
|
||||
|
||||
部署脚本必须满足:
|
||||
|
||||
- 新机器只需要少量环境变量
|
||||
- 不要求现场手工改很多路径
|
||||
- 国外机和大陆机各自有独立入口脚本
|
||||
- 后续新增大陆 Worker 节点继续复用同一脚本
|
||||
|
||||
### 5. 当前建议的最小部署
|
||||
|
||||
当前最适合正式起步的形态:
|
||||
|
||||
- 国外 `1` 台:
|
||||
- `domain-web`
|
||||
- `domain-api`
|
||||
- 国外主 PostgreSQL
|
||||
- 大陆 `1` 台:
|
||||
- `redis`
|
||||
- 大陆运行库 PostgreSQL
|
||||
- `detect-worker`
|
||||
- 后续可补 `sync-service`
|
||||
|
||||
扩容时优先:
|
||||
|
||||
1. 新增大陆 Worker
|
||||
2. 再视压力拆分大陆运行库与 Redis
|
||||
3. 国外控制面保持稳定,不跟着高频扩缩
|
||||
|
||||
## 十、阶段性落地建议
|
||||
|
||||
### 第一阶段
|
||||
|
||||
先完成:
|
||||
|
||||
- 国外控制面部署
|
||||
- 大陆单机执行面部署
|
||||
- 节点注册与心跳
|
||||
- 当前后台继续可用
|
||||
|
||||
### 第二阶段
|
||||
|
||||
再完成:
|
||||
|
||||
- 任务项模型
|
||||
- 多 Worker 抢任务
|
||||
- 事件日志流
|
||||
- 结果异步同步回国外
|
||||
|
||||
### 第三阶段
|
||||
|
||||
最后完成:
|
||||
|
||||
- 大陆多 Worker 横向扩容
|
||||
- 运行库与调度中心独立拆分
|
||||
- 国外归档和监控补齐
|
||||
|
||||
## 十一、运行与观测建议
|
||||
|
||||
多机之后,不能再只靠“登录某台机器 tail 日志”来判断系统状态。
|
||||
|
||||
建议分层:
|
||||
|
||||
- 大陆 Worker 本地保留完整原始日志
|
||||
- `detect_run_events` 保存关键阶段事件
|
||||
- 国外后台优先展示事件流、节点负载和同步状态
|
||||
- 真排障时再下钻到具体节点原始日志
|
||||
|
||||
后台建议优先展示:
|
||||
|
||||
- 当前在线节点数
|
||||
- 每节点最近心跳
|
||||
- 每节点当前负载
|
||||
- 当前活跃任务数
|
||||
- 队列积压与最老待领年龄
|
||||
- 租约是否过期、是否即将到期
|
||||
- 近 15 分钟每节点吞吐
|
||||
- 最近失败摘要
|
||||
- 最近同步结果
|
||||
- 最近结果摘要投影
|
||||
|
||||
## 十二、下一阶段开发清单
|
||||
|
||||
接下来建议按下面顺序继续落地:
|
||||
|
||||
1. 后台创建 `detect_jobs / detect_job_items`
|
||||
2. Worker 实现批量 claim / renew / finish / fail
|
||||
3. 增加租约超时回收
|
||||
4. 将检测阶段事件写入 `detect_run_events`
|
||||
5. 增加 `sync-service`
|
||||
6. 完成第二台大陆 Worker 接入演练
|
||||
|
||||
## 十三、最终建议
|
||||
|
||||
对当前项目来说,最优解不是“全部放国外”,也不是“全部放大陆”,而是:
|
||||
|
||||
- 国外做控制面和主结果库
|
||||
- 大陆做执行面和运行态调度
|
||||
- 先从 `国外 1 台 + 大陆 1 台` 起步
|
||||
- 后续优先横向增加大陆 Worker
|
||||
|
||||
一句话总结:
|
||||
|
||||
> 先把职责边界设计对,再让部署简单;后续扩容时只加 Worker,不再重构核心架构。
|
||||
734
docs/17_domainCheck_全流程部署实操手册.md
Normal file
734
docs/17_domainCheck_全流程部署实操手册.md
Normal file
@@ -0,0 +1,734 @@
|
||||
# 17 domainCheck 手工部署实操手册
|
||||
|
||||
## 一、文档目标
|
||||
|
||||
这份文档只讲一件事:
|
||||
|
||||
> 不依赖一键脚本,完全手工完成部署、更新、排障和扩容。
|
||||
|
||||
它不是设计说明,也不是零散检查单,而是给实际部署时直接照着做的“手工操作手册”。
|
||||
|
||||
文档边界:
|
||||
|
||||
- 这里只讲手工部署
|
||||
- 不使用 `install_overseas_quick.sh`
|
||||
- 不使用 `install_mainland_controller_quick.sh`
|
||||
- 不使用 `install_mainland_worker_quick.sh`
|
||||
- 如果你想走傻瓜式复制部署,请改看:
|
||||
- [18_domainCheck_CentOS9一键复制部署与更新文档.md](/www/wwwroot/getDomain/docs/18_domainCheck_CentOS9一键复制部署与更新文档.md:1)
|
||||
|
||||
适用场景:
|
||||
|
||||
- 先在国外机器完成单机部署与联调
|
||||
- 后续再扩到“国外控制面 + 大陆执行面”
|
||||
- 当前暂时无法把代码真正部署到大陆机器时,先在国外机器模拟多节点联调
|
||||
- 最后再把同样的部署方式复制到其他机器
|
||||
|
||||
一句话理解:
|
||||
|
||||
> 先把国外主控机部署好,再按同样套路扩第二台、第三台,不靠临场猜。
|
||||
|
||||
并发配置补充:
|
||||
|
||||
- 系统支持 `默认线程数 + 节点单独覆盖`
|
||||
- 节点单独覆盖按机器自己的 `NODE_CODE` 命中
|
||||
- 某台机器没配置覆盖值时,自动回退到默认线程数
|
||||
|
||||
## 二、推荐部署形态
|
||||
|
||||
### 1. 当前最推荐起步形态
|
||||
|
||||
- 国外机器 `1` 台:
|
||||
- `domain-web`
|
||||
- `domain-api`
|
||||
- PostgreSQL
|
||||
- Redis
|
||||
- `domaincheck-worker`
|
||||
- 后续扩容时:
|
||||
- 新增大陆 `controller`
|
||||
- 新增大陆 `worker`
|
||||
|
||||
说明:
|
||||
|
||||
- 因为你当前还不能直接把代码稳定部署到大陆机器,所以第一阶段先把国外机器单机跑稳
|
||||
- 这台国外机器同时承担:
|
||||
- 后台
|
||||
- API
|
||||
- 数据库
|
||||
- Redis
|
||||
- Worker
|
||||
- 等这套稳定后,再把多机脚本复制到其他机器
|
||||
|
||||
### 2. 最终推荐形态
|
||||
|
||||
- 国外 `control`:
|
||||
- `domain-web`
|
||||
- `domain-api`
|
||||
- 主 PostgreSQL
|
||||
- 结果归档
|
||||
- 大陆 `controller`:
|
||||
- Redis
|
||||
- 运行态 PostgreSQL
|
||||
- `domaincheck-worker`
|
||||
- `domaincheck-sync-agent`
|
||||
- 大陆 `worker`:
|
||||
- `domaincheck-worker`
|
||||
|
||||
## 三、服务器准备
|
||||
|
||||
### 1. 系统要求
|
||||
|
||||
- CentOS Stream 9
|
||||
- Python `3.11`
|
||||
- PostgreSQL `14+`
|
||||
- Redis `6+`
|
||||
- Nginx
|
||||
|
||||
关键说明:
|
||||
|
||||
- 这里的 Python 不是“系统自带什么就用什么”
|
||||
- 必须明确安装 `python3.11`
|
||||
- 不能只装系统默认 `python3`
|
||||
- 因为后续部署命令直接使用的是 `python3.11 -m venv .venv`
|
||||
|
||||
推荐先执行:
|
||||
|
||||
```bash
|
||||
dnf install -y python3.11 python3.11-devel
|
||||
python3.11 --version
|
||||
```
|
||||
|
||||
期望输出类似:
|
||||
|
||||
```text
|
||||
Python 3.11.x
|
||||
```
|
||||
|
||||
### 2. 目录约定
|
||||
|
||||
统一使用:
|
||||
|
||||
```text
|
||||
/opt/domaincheck
|
||||
├── domain-api
|
||||
├── domain-web
|
||||
└── domainCheck
|
||||
```
|
||||
|
||||
### 3. 当前仓库与运行态关系
|
||||
|
||||
如果你像当前测试机一样,用仓库目录做源码源头,也可以用软链接:
|
||||
|
||||
```bash
|
||||
ln -s /www/wwwroot/getDomain/domain-api /opt/domaincheck/domain-api
|
||||
ln -s /www/wwwroot/getDomain/domain-web /opt/domaincheck/domain-web
|
||||
ln -s /www/wwwroot/getDomain/domainCheck /opt/domaincheck/domainCheck
|
||||
```
|
||||
|
||||
如果你是完整复制代码到目标机,也可以直接把目录上传到 `/opt/domaincheck/`。
|
||||
|
||||
## 四、第一阶段:国外单机部署
|
||||
|
||||
这一阶段的目标是:
|
||||
|
||||
- 后台可访问
|
||||
- API 正常
|
||||
- 数据库已初始化
|
||||
- Worker 可跑
|
||||
- 运行中心正常
|
||||
- smoke test 通过
|
||||
|
||||
### 1. 拉取代码
|
||||
|
||||
当前建议统一走 `git` 管理和更新,不再手工散传目录。
|
||||
|
||||
执行口径:
|
||||
|
||||
- 这里建议直接使用 `root`
|
||||
- 不建议使用 `www` 用户执行整套部署命令
|
||||
- 因为后面还会接着写 `systemd`、`/etc/default/`、`/opt/domaincheck/` 和服务启停
|
||||
|
||||
第一次部署建议:
|
||||
|
||||
```bash
|
||||
mkdir -p /www/wwwroot
|
||||
cd /www/wwwroot
|
||||
git clone 你的仓库地址 getDomain
|
||||
cd getDomain
|
||||
git checkout main
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
然后建立运行目录软链接:
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/domaincheck
|
||||
ln -s /www/wwwroot/getDomain/domain-api /opt/domaincheck/domain-api
|
||||
ln -s /www/wwwroot/getDomain/domain-web /opt/domaincheck/domain-web
|
||||
ln -s /www/wwwroot/getDomain/domainCheck /opt/domaincheck/domainCheck
|
||||
```
|
||||
|
||||
后续更新统一使用:
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/getDomain
|
||||
git fetch --all
|
||||
git checkout main
|
||||
git pull --ff-only origin main
|
||||
```
|
||||
|
||||
### 1.1 先确认 Python 3.11 已安装
|
||||
|
||||
如果当前机器还没有 `python3.11`,先执行:
|
||||
|
||||
```bash
|
||||
dnf install -y python3.11 python3.11-devel
|
||||
python3.11 --version
|
||||
```
|
||||
|
||||
只有确认 `python3.11` 命令存在后,再继续下面的虚拟环境步骤。
|
||||
|
||||
### 2. 创建 Python 虚拟环境
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domainCheck
|
||||
python3.11 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install --upgrade pip
|
||||
python3.11 - <<'PY'
|
||||
from pathlib import Path
|
||||
|
||||
source = Path("requirements.txt")
|
||||
target = Path("requirements.linux.txt")
|
||||
raw = source.read_bytes()
|
||||
for encoding in ("utf-8", "utf-16", "utf-16-le", "utf-16-be", "gbk"):
|
||||
try:
|
||||
text = raw.decode(encoding)
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
else:
|
||||
raise SystemExit("无法解析 requirements.txt 编码")
|
||||
|
||||
skip_prefixes = (
|
||||
"pywin32==",
|
||||
"pywin32-ctypes==",
|
||||
"twisted-iocpsupport==",
|
||||
"win32-setctime==",
|
||||
)
|
||||
lines = []
|
||||
for line in text.splitlines():
|
||||
normalized = line.strip().lstrip("\ufeff")
|
||||
if normalized.lower().startswith(skip_prefixes):
|
||||
continue
|
||||
lines.append(normalized)
|
||||
|
||||
target.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
||||
PY
|
||||
pip install -r requirements.linux.txt
|
||||
```
|
||||
|
||||
然后补 API 依赖:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
/opt/domaincheck/domainCheck/.venv/bin/pip install fastapi uvicorn pydantic-settings psycopg2-binary redis openpyxl python-multipart
|
||||
```
|
||||
|
||||
补充说明:
|
||||
|
||||
- 这里不能直接在 Linux 上裸跑 `pip install -r requirements.txt`
|
||||
- 因为桌面版历史依赖里包含 `pywin32` 等 Windows-only 包
|
||||
- 手工部署时也必须先生成 `requirements.linux.txt` 再安装
|
||||
|
||||
### 3. 配置数据库和 Redis
|
||||
|
||||
确保 PostgreSQL 和 Redis 可用。
|
||||
|
||||
建议先确认:
|
||||
|
||||
```bash
|
||||
psql -h 127.0.0.1 -U postgres -d domain -c "select 1;"
|
||||
redis-cli ping
|
||||
```
|
||||
|
||||
### 4. 配置 `domainCheck/.env`
|
||||
|
||||
至少确认这些项:
|
||||
|
||||
```env
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=5432
|
||||
DB_DATABASE=domain
|
||||
DB_USER=postgres
|
||||
DB_PASSWORD=你的密码
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=
|
||||
REDIS_DB=0
|
||||
```
|
||||
|
||||
### 5. 初始化数据库
|
||||
|
||||
这是最重要的一步,新库必须先做:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domainCheck
|
||||
python3 init_database.py
|
||||
```
|
||||
|
||||
如果不先执行,至少这些接口会直接 `500`:
|
||||
|
||||
- `/api/v1/dashboard/overview`
|
||||
- `/api/v1/detect/status`
|
||||
- `/api/v1/imports/summary`
|
||||
|
||||
### 6. 构建前端
|
||||
|
||||
进入 `domain-web`,配置生产环境 API 地址:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-web
|
||||
cp .env.production.example .env.production
|
||||
```
|
||||
|
||||
把 `VITE_API_BASE_URL` 改成目标 API,例如:
|
||||
|
||||
```env
|
||||
VITE_API_BASE_URL=https://api.domain.com/api/v1
|
||||
```
|
||||
|
||||
然后构建:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 7. 配置 Nginx
|
||||
|
||||
参考:
|
||||
|
||||
- `domain-web/deploy/nginx/domain-web.conf`
|
||||
|
||||
把静态目录指到:
|
||||
|
||||
```text
|
||||
/opt/domaincheck/domain-web/dist
|
||||
```
|
||||
|
||||
常见做法:
|
||||
|
||||
- `admin.domain` 对外提供后台页面
|
||||
- `api.domain.com` 对外提供 API
|
||||
|
||||
### 8. 安装 systemd 服务
|
||||
|
||||
复制模板:
|
||||
|
||||
```bash
|
||||
cp /opt/domaincheck/domain-api/deploy/systemd/domain-api.service /etc/systemd/system/domaincheck-api.service
|
||||
cp /opt/domaincheck/domain-api/deploy/systemd/domain-worker.service /etc/systemd/system/domaincheck-worker.service
|
||||
```
|
||||
|
||||
### 9. 配置 API 环境变量
|
||||
|
||||
建议使用:
|
||||
|
||||
```bash
|
||||
cp /opt/domaincheck/domain-api/deploy/multi-region/templates/domaincheck-api.env.example /etc/default/domaincheck-api
|
||||
```
|
||||
|
||||
至少改这些:
|
||||
|
||||
```env
|
||||
WORKER_MODE=linux-systemd
|
||||
API_HOST=0.0.0.0
|
||||
API_PORT=8100
|
||||
DOMAIN_ROOT=/opt/domaincheck/domainCheck
|
||||
NODE_CODE=overseas-control-01
|
||||
NODE_REGION=overseas
|
||||
NODE_ROLE=control
|
||||
CORS_ORIGINS='["http://127.0.0.1:3201","http://localhost:3201","http://你的服务器IP:3201"]'
|
||||
SYNC_PUSH_ENABLED=false
|
||||
```
|
||||
|
||||
如果你已经固定域名,建议直接改成:
|
||||
|
||||
```env
|
||||
CORS_ORIGINS='["https://admin.domain","http://127.0.0.1:3201","http://localhost:3201"]'
|
||||
```
|
||||
|
||||
### 10. 修正权限
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/domaincheck/domain-api/runtime
|
||||
touch /opt/domaincheck/domainCheck/detect_worker.log
|
||||
chown -R www:www /opt/domaincheck/domain-api/runtime
|
||||
chown www:www /opt/domaincheck/domainCheck/detect_worker.log
|
||||
chmod 664 /opt/domaincheck/domainCheck/detect_worker.log
|
||||
```
|
||||
|
||||
### 11. 启动服务
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable domaincheck-api
|
||||
systemctl enable domaincheck-worker
|
||||
systemctl restart domaincheck-api
|
||||
systemctl restart domaincheck-worker
|
||||
```
|
||||
|
||||
### 12. 检查服务状态
|
||||
|
||||
```bash
|
||||
systemctl status domaincheck-api --no-pager -l
|
||||
systemctl status domaincheck-worker --no-pager -l
|
||||
```
|
||||
|
||||
## 五、第一阶段验收
|
||||
|
||||
### 1. 接口检查
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8100/health
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/preflight
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/status
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/readiness
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- `/health.status=ok`
|
||||
- `/health.worker_mode=linux-systemd`
|
||||
- `/runtime/preflight.ok=true`
|
||||
- `/runtime/status.worker.running=true`
|
||||
- `/runtime/readiness.status` 至少不是 `blocking`
|
||||
|
||||
### 2. smoke test
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api/deploy/linux
|
||||
python3 smoke_test.py --base-url http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
如果要连 Web 一起检查:
|
||||
|
||||
```bash
|
||||
python3 smoke_test.py --base-url http://127.0.0.1:8100 --web-url http://127.0.0.1:3201
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- `ok=true`
|
||||
|
||||
### 3. 后台页面检查
|
||||
|
||||
浏览器打开:
|
||||
|
||||
```text
|
||||
https://admin.domain
|
||||
```
|
||||
|
||||
至少检查:
|
||||
|
||||
- 登录
|
||||
- 运行中心
|
||||
- 系统设置
|
||||
- 域名筛选
|
||||
- 导入
|
||||
- 导出
|
||||
|
||||
## 六、第二阶段:国外机器模拟多机联调
|
||||
|
||||
如果你暂时还不能把代码部署到大陆机器,就先在国外机器做这一步。
|
||||
|
||||
### 1. 一键多机演练
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/rehearse_multi_region.sh http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
它会自动模拟:
|
||||
|
||||
- 一个大陆 controller
|
||||
- 两个大陆 worker
|
||||
|
||||
并自动检查:
|
||||
|
||||
- `runtime/readiness`
|
||||
- `runtime/cluster`
|
||||
- online control / online worker 数量
|
||||
- 节点状态是否符合预期
|
||||
|
||||
### 2. 通过标准
|
||||
|
||||
如果输出里出现:
|
||||
|
||||
```text
|
||||
rehearsal passed
|
||||
```
|
||||
|
||||
说明当前这台国外机器上的多机模拟联调已通过,可以继续部署到其他机器。
|
||||
|
||||
### 3. 如果想手工模拟
|
||||
|
||||
也可以单独跑:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/simulate_multi_region.sh http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
停止时按:
|
||||
|
||||
```text
|
||||
Ctrl+C
|
||||
```
|
||||
|
||||
### 4. 清理旧节点残影
|
||||
|
||||
如果之前测试过多轮,集群里可能残留老节点:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/prune_cluster_nodes.sh --minutes 30 --dry-run
|
||||
bash deploy/multi-region/prune_cluster_nodes.sh --minutes 30
|
||||
```
|
||||
|
||||
如果只删某个旧节点:
|
||||
|
||||
```bash
|
||||
bash deploy/multi-region/prune_cluster_nodes.sh --node-code mainland-worker-01
|
||||
```
|
||||
|
||||
## 七、第三阶段:部署到其他机器
|
||||
|
||||
等国外单机和模拟多机都通过后,就可以把同样的代码与脚本部署到其他机器。
|
||||
|
||||
### A. 新海外控制机
|
||||
|
||||
在目标机执行:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/bootstrap_overseas.sh /opt/domaincheck
|
||||
```
|
||||
|
||||
然后完善:
|
||||
|
||||
- `/etc/default/domaincheck-api`
|
||||
- Nginx
|
||||
- PostgreSQL
|
||||
- Redis
|
||||
|
||||
最后检查:
|
||||
|
||||
```bash
|
||||
bash deploy/multi-region/check_cluster.sh http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
### B. 大陆 controller
|
||||
|
||||
在目标机执行:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/bootstrap_mainland.sh /opt/domaincheck controller
|
||||
```
|
||||
|
||||
然后检查:
|
||||
|
||||
```bash
|
||||
bash deploy/multi-region/check_mainland_controller.sh
|
||||
```
|
||||
|
||||
关键配置是:
|
||||
|
||||
```env
|
||||
NODE_CODE=mainland-controller-01
|
||||
NODE_REGION=mainland
|
||||
NODE_ROLE=control
|
||||
SYNC_PUSH_ENABLED=true
|
||||
SYNC_SOURCE_REGION=mainland
|
||||
SYNC_TARGET_REGION=overseas
|
||||
SYNC_TARGET_API_BASE_URL=http://海外控制面IP:8100/api/v1
|
||||
SYNC_SHARED_TOKEN=你自己的共享令牌
|
||||
```
|
||||
|
||||
### C. 大陆 worker
|
||||
|
||||
在目标机执行:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/bootstrap_mainland.sh /opt/domaincheck worker
|
||||
```
|
||||
|
||||
关键配置是:
|
||||
|
||||
```env
|
||||
NODE_CODE=mainland-worker-01
|
||||
NODE_REGION=mainland
|
||||
NODE_ROLE=worker
|
||||
SYNC_PUSH_ENABLED=true
|
||||
SYNC_SOURCE_REGION=mainland
|
||||
SYNC_TARGET_REGION=overseas
|
||||
SYNC_TARGET_API_BASE_URL=http://海外控制面IP:8100/api/v1
|
||||
```
|
||||
|
||||
## 八、部署到其他机器后的联调顺序
|
||||
|
||||
建议按这个顺序,不容易乱:
|
||||
|
||||
1. 先让海外控制机稳定
|
||||
2. 再接大陆 controller
|
||||
3. 再接第一台大陆 worker
|
||||
4. 再接第二台、第三台 worker
|
||||
|
||||
每接一台都执行:
|
||||
|
||||
```bash
|
||||
curl http://海外控制机:8100/api/v1/runtime/readiness
|
||||
curl http://海外控制机:8100/api/v1/runtime/cluster
|
||||
curl http://海外控制机:8100/api/v1/runtime/sync-summary
|
||||
```
|
||||
|
||||
如果海外 API 已经挂到正式域名,建议直接写成:
|
||||
|
||||
```bash
|
||||
curl https://api.domain.com/api/v1/runtime/readiness
|
||||
curl https://api.domain.com/api/v1/runtime/cluster
|
||||
curl https://api.domain.com/api/v1/runtime/sync-summary
|
||||
```
|
||||
|
||||
### 联调通过标准
|
||||
|
||||
- `runtime/cluster` 能看到新节点
|
||||
- `last_heartbeat_at` 持续刷新
|
||||
- 大陆 controller 为 `role=control`
|
||||
- 大陆 worker 为 `role=worker`
|
||||
- 执行任务时 worker 状态能变成 `busy`
|
||||
- `runtime/readiness` 至少不是 `blocking`
|
||||
- `runtime/sync-summary` 能看到 `detect_result_batches`
|
||||
|
||||
## 九、上线前最后检查
|
||||
|
||||
按这份文档部署完成后,再回看:
|
||||
|
||||
- [14_domainCheck_正式上线前最终检查单.md](/www/wwwroot/getDomain/docs/14_domainCheck_正式上线前最终检查单.md:1)
|
||||
|
||||
重点保留:
|
||||
|
||||
- `systemctl status`
|
||||
- `journalctl`
|
||||
- `/health`
|
||||
- `/runtime/preflight`
|
||||
- `/runtime/readiness`
|
||||
- `/runtime/sync-summary`
|
||||
- `smoke test`
|
||||
- 诊断包
|
||||
|
||||
## 十、常见问题
|
||||
|
||||
### 1. API 启动了,但接口 500
|
||||
|
||||
优先检查有没有先执行:
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domainCheck
|
||||
python3 init_database.py
|
||||
```
|
||||
|
||||
### 2. Worker 一直重启
|
||||
|
||||
优先检查:
|
||||
|
||||
- `/opt/domaincheck/domainCheck/detect_worker.log` 权限
|
||||
- `/opt/domaincheck/domain-api/runtime/` 权限
|
||||
- `domainCheck/.env` 数据库和 Redis 配置
|
||||
|
||||
### 3. readiness 一直是 `attention`
|
||||
|
||||
优先检查:
|
||||
|
||||
- 集群里是否残留旧离线节点
|
||||
- 是否还没接入大陆 controller
|
||||
- 是否还没有在线 worker
|
||||
|
||||
必要时先清理旧节点:
|
||||
|
||||
```bash
|
||||
bash deploy/multi-region/prune_cluster_nodes.sh --minutes 30
|
||||
```
|
||||
|
||||
### 4. 模拟多机通过了,真实机器还没接上
|
||||
|
||||
这是正常的。
|
||||
|
||||
模拟多机的意义是:
|
||||
|
||||
- 验证代码、脚本、页面、状态口径一致
|
||||
- 不代表真实大陆网络、代理、同步链路已经完成
|
||||
|
||||
真实机器接入时,重点要再看:
|
||||
|
||||
- 节点心跳
|
||||
- 同步目标地址
|
||||
- 共享 token
|
||||
- 真实 Redis / PostgreSQL 连接
|
||||
|
||||
## 十一、最短执行版本
|
||||
|
||||
如果你只想看最短版,可以照这个跑:
|
||||
|
||||
### 国外单机先跑通
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domainCheck
|
||||
python3.11 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
python3 init_database.py
|
||||
|
||||
cd /opt/domaincheck/domain-api
|
||||
/opt/domaincheck/domainCheck/.venv/bin/pip install fastapi uvicorn pydantic-settings psycopg2-binary redis openpyxl python-multipart
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable domaincheck-api domaincheck-worker
|
||||
systemctl restart domaincheck-api domaincheck-worker
|
||||
|
||||
curl http://127.0.0.1:8100/health
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/preflight
|
||||
curl http://127.0.0.1:8100/api/v1/runtime/readiness
|
||||
```
|
||||
|
||||
### 再跑多机模拟验收
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash deploy/multi-region/rehearse_multi_region.sh http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
### 通过后再上其他机器
|
||||
|
||||
```bash
|
||||
bash deploy/multi-region/bootstrap_overseas.sh /opt/domaincheck
|
||||
bash deploy/multi-region/bootstrap_mainland.sh /opt/domaincheck controller
|
||||
bash deploy/multi-region/bootstrap_mainland.sh /opt/domaincheck worker
|
||||
```
|
||||
|
||||
## 十二、最终结论
|
||||
|
||||
当前最稳的推进方式是:
|
||||
|
||||
1. 先在国外机器完成单机部署
|
||||
2. 再在国外机器完成多机模拟演练
|
||||
3. 演练通过后,再复制到其他机器
|
||||
4. 最后再做真实跨地域联调
|
||||
|
||||
一句话总结:
|
||||
|
||||
> 先把单机跑稳,再把多机脚本跑通,最后再扩机器;每一步都有现成脚本,不靠现场猜。
|
||||
1196
docs/18_domainCheck_CentOS9一键复制部署与更新文档.md
Normal file
1196
docs/18_domainCheck_CentOS9一键复制部署与更新文档.md
Normal file
File diff suppressed because it is too large
Load Diff
404
docs/19_domainCheck_国内外联调交接说明.md
Normal file
404
docs/19_domainCheck_国内外联调交接说明.md
Normal file
@@ -0,0 +1,404 @@
|
||||
# domainCheck 国内外联调交接说明
|
||||
|
||||
## 1. 当前目标
|
||||
|
||||
本次联调的目标是把现有架构整理成下面这条可运行链路:
|
||||
|
||||
- 海外机保留主数据与后台展示
|
||||
- 海外机把待检测任务批次下发到国内 controller
|
||||
- 国内 controller 落本地任务与本地 `domains`
|
||||
- 国内 worker 执行检测
|
||||
- 国内运行时状态、检测结果再同步回海外
|
||||
- 海外后台统一查看总体进度与结果
|
||||
|
||||
当前主链路已经基本跑通,剩下的是:
|
||||
|
||||
- 海外 cluster/readiness 视图的最后收尾
|
||||
- 文档固化
|
||||
- 最好增加“国内日志回调到海外”的调试手段,减少人工复制日志
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前已确认跑通的链路
|
||||
|
||||
### 2.1 海外 API 正常
|
||||
|
||||
海外 API 已经具备:
|
||||
|
||||
- `/health`
|
||||
- `/api/v1/runtime/cluster`
|
||||
- `/api/v1/runtime/readiness`
|
||||
- `/api/v1/runtime/preflight`
|
||||
- `/api/v1/runtime/sync-summary`
|
||||
|
||||
并且 nginx 对 `/api/v1/runtime/*` 的转发已经修好。
|
||||
|
||||
### 2.2 国内 controller 正常
|
||||
|
||||
国内 controller 这边已经确认:
|
||||
|
||||
- `domaincheck-api` 正常运行
|
||||
- `domaincheck-sync-agent` 正常运行
|
||||
- 本地 PostgreSQL 可用
|
||||
- 本地 Redis 可用
|
||||
- `detect/start` 不再受 `sudo: a password is required` 影响
|
||||
|
||||
### 2.3 国内 worker 正常
|
||||
|
||||
国内 worker 这边已经确认:
|
||||
|
||||
- `domaincheck-worker` 正常运行
|
||||
- 可以连接国内 controller 的 PostgreSQL
|
||||
- 可以连接国内 controller 的 Redis
|
||||
- Redis 密码配置后,Worker 控制指令已能正确消费
|
||||
|
||||
### 2.4 海外任务下发到国内已跑通
|
||||
|
||||
已实现并验证:
|
||||
|
||||
- 海外导出待检测任务批次
|
||||
- 国内 controller 主动拉取任务批次
|
||||
- 国内本地写入 `domains`
|
||||
- 国内本地生成 `detect_jobs` / `detect_job_items`
|
||||
- 国内 worker 已开始执行实际检测任务
|
||||
|
||||
实际验证过的现象:
|
||||
|
||||
- 国内 `domains` 从 `0` 变成 `200`
|
||||
- `detect/start` 能创建任务
|
||||
- `job_id=1` 已进入 `running`
|
||||
- `items_completed`、`items_running`、`items_claimed` 已持续变化
|
||||
|
||||
### 2.5 结果与运行时同步部分已跑通
|
||||
|
||||
已确认:
|
||||
|
||||
- 国内 `runtime_projection` 已成功推送到海外
|
||||
- 国内 `detect_result_projection` 已开始生成
|
||||
- 海外已能看到新的大陆 controller 节点在线
|
||||
|
||||
---
|
||||
|
||||
## 3. 本次实际修改过的核心代码
|
||||
|
||||
以下文件已经被修改,是后续接手时最需要优先查看的:
|
||||
|
||||
### 3.1 任务下发/同步相关
|
||||
|
||||
- [domain-api/app/services/sync_push_service.py](/www/wwwroot/getDomain/domain-api/app/services/sync_push_service.py:1)
|
||||
- [domain-api/app/services/sync_record_service.py](/www/wwwroot/getDomain/domain-api/app/services/sync_record_service.py:1)
|
||||
- [domain-api/app/api/routes/runtime.py](/www/wwwroot/getDomain/domain-api/app/api/routes/runtime.py:1)
|
||||
- [domain-api/app/sync_agent.py](/www/wwwroot/getDomain/domain-api/app/sync_agent.py:1)
|
||||
|
||||
新增/补充的能力包括:
|
||||
|
||||
- `runtime_projection` 推送与接收
|
||||
- `detect_result_projection` 推送与接收
|
||||
- `detect_task_projection` 任务批次导出
|
||||
- 国内 `pull_detect_task_batch_now()`
|
||||
- 海外 `task-export`
|
||||
- 海外 `task-ack`
|
||||
- 国内任务批次入库逻辑
|
||||
|
||||
### 3.2 任务创建与控制
|
||||
|
||||
- [domain-api/app/services/detect_job_service.py](/www/wwwroot/getDomain/domain-api/app/services/detect_job_service.py:1)
|
||||
- [domain-api/app/services/worker_control_service.py](/www/wwwroot/getDomain/domain-api/app/services/worker_control_service.py:1)
|
||||
- [domain-api/app/services/runtime_control_service.py](/www/wwwroot/getDomain/domain-api/app/services/runtime_control_service.py:1)
|
||||
- [domain-api/app/api/routes/detect.py](/www/wwwroot/getDomain/domain-api/app/api/routes/detect.py:1)
|
||||
|
||||
关键变化:
|
||||
|
||||
- 本地没有任务时,`create_detect_job_if_needed()` 会先尝试从海外拉一批任务
|
||||
- Linux `systemd` 模式下不再强依赖 `sudo -n`
|
||||
- 增加了 `pull_tasks` 运行时动作
|
||||
|
||||
### 3.3 运行时节点与 cluster 视图
|
||||
|
||||
- [domain-api/app/services/cluster_runtime_service.py](/www/wwwroot/getDomain/domain-api/app/services/cluster_runtime_service.py:1)
|
||||
|
||||
关键变化:
|
||||
|
||||
- 支持导入远端 runtime 节点
|
||||
- 支持清理历史 `*-imported` 脏节点
|
||||
- 正在补齐“海外显示大陆 worker 节点”的投影逻辑
|
||||
|
||||
### 3.4 前面已经做过的部署类改动
|
||||
|
||||
这些文件之前也已经做过较多修复,交接时可一起复核:
|
||||
|
||||
- `domain-api/deploy/multi-region/install_overseas_quick.sh`
|
||||
- `domain-api/deploy/multi-region/install_mainland_controller_quick.sh`
|
||||
- `domain-api/deploy/multi-region/install_mainland_worker_quick.sh`
|
||||
- `docs/17_domainCheck_全流程部署实操手册.md`
|
||||
- `docs/18_domainCheck_CentOS9一键复制部署与更新文档.md`
|
||||
|
||||
---
|
||||
|
||||
## 4. 当前仍未完全收尾的问题
|
||||
|
||||
### 4.1 海外 cluster 里大陆 worker 显示不完整
|
||||
|
||||
当前已经能在海外看到:
|
||||
|
||||
- `mainland-controller-01`
|
||||
|
||||
但一度没有稳定看到:
|
||||
|
||||
- `mainland-worker-01`
|
||||
|
||||
原因:
|
||||
|
||||
- 海外主要是根据大陆 controller 回传的 `runtime_projection` 做远端节点物化
|
||||
- 之前 projection 里缺少 `active_job.node_stats`
|
||||
- 后续已补代码,让海外可根据 `node_stats` 额外注册 worker 节点
|
||||
|
||||
接手人需要重点验证:
|
||||
|
||||
- 海外 `/api/v1/runtime/cluster` 中是否出现 `mainland-worker-01`
|
||||
- `online_worker_nodes` 是否从 `0` 变为 `1`
|
||||
|
||||
### 4.2 历史脏节点 `mainland-control-imported`
|
||||
|
||||
这是早期调试阶段遗留的 imported 节点。
|
||||
|
||||
现象:
|
||||
|
||||
- 海外 `readiness` / `cluster` 曾显示:
|
||||
- `mainland-control-imported`
|
||||
- `status: offline`
|
||||
|
||||
影响:
|
||||
|
||||
- 不影响主流程执行
|
||||
- 但会污染 readiness / cluster 展示
|
||||
|
||||
已经补了清理逻辑,但需要继续验证是否彻底清干净。
|
||||
|
||||
### 4.3 结果回传展示还需要继续观察
|
||||
|
||||
当前已经看到:
|
||||
|
||||
- `detect_result_projection` 在国内生成
|
||||
- 海外 `sync-summary` 中出现结果相关记录
|
||||
|
||||
还需要继续确认:
|
||||
|
||||
- 海外是否稳定生成 `detect_result_ingest`
|
||||
- 海外业务展示页/结果页是否正确反映国内执行结果
|
||||
- 海外主库中的业务表是否已被正确更新
|
||||
|
||||
---
|
||||
|
||||
## 5. 两边部署时容易踩的坑
|
||||
|
||||
### 5.1 root 和 www 的职责不要混
|
||||
|
||||
建议约定:
|
||||
|
||||
- `git pull` / 仓库代码操作:用 `www`
|
||||
- `systemctl restart ...`:用 `root`
|
||||
|
||||
原因:
|
||||
|
||||
- `root` 在当前环境下经常遇到 git safe.directory / ssh / dubious ownership 问题
|
||||
- `www` 是仓库实际维护用户
|
||||
|
||||
### 5.2 国内 controller 与 worker 的 Redis 密码必须一致
|
||||
|
||||
至少这些位置要确认:
|
||||
|
||||
- `/etc/default/domaincheck-api`
|
||||
- `/etc/default/domaincheck-worker`
|
||||
- `/www/wwwroot/getDomain/domainCheck/.env`
|
||||
|
||||
如果 Redis 开了密码,但上述文件里 `REDIS_PASSWORD=` 为空,会出现:
|
||||
|
||||
- `Authentication required.`
|
||||
- API 无法发 Worker 控制指令
|
||||
- Worker 无法订阅控制消息
|
||||
|
||||
### 5.3 国内 controller 本地数据库并不是海外主数据
|
||||
|
||||
之前最大的误区就是:
|
||||
|
||||
- 海外有 `16w` 数据
|
||||
- 但国内本地 `domains` 一开始是 `0`
|
||||
|
||||
当前设计已经调整为:
|
||||
|
||||
- 海外通过 `task-export` 导出待检测批次
|
||||
- 国内主动拉批次,落本地最小 `domains`
|
||||
- 国内 worker 只跑本地任务
|
||||
|
||||
不要再假设“国内本地库天然就有海外那 16w 主数据”。
|
||||
|
||||
### 5.4 代码更新要确认文件内容,不要只看 restart
|
||||
|
||||
如果 `systemctl restart domaincheck-api` 之后行为没变,不要只怀疑服务。
|
||||
|
||||
先直接检查源码关键片段是否真的更新到位。
|
||||
|
||||
例如本次调试里最典型的就是:
|
||||
|
||||
- `domain-api/app/services/sync_push_service.py`
|
||||
|
||||
通过 `grep` 关键代码判断是否已是新版,比只看服务状态更可靠。
|
||||
|
||||
---
|
||||
|
||||
## 6. 建议给海外 Codex 的接手任务
|
||||
|
||||
建议在海外机新开 Codex 后,直接按下面顺序接手:
|
||||
|
||||
### 6.1 第一优先级
|
||||
|
||||
- 确认海外 cluster 能稳定显示:
|
||||
- `overseas-control-01`
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
|
||||
- 确认海外 `readiness` 中:
|
||||
- `online_worker_nodes >= 1`
|
||||
- 不再被 `mainland-control-imported` 影响
|
||||
|
||||
### 6.2 第二优先级
|
||||
|
||||
- 确认 `detect_result_projection -> detect_result_ingest` 的闭环
|
||||
- 确认海外业务查询接口/后台页面能看到国内执行回流结果
|
||||
|
||||
### 6.3 第三优先级
|
||||
|
||||
- 整理 `docs/18_domainCheck_CentOS9一键复制部署与更新文档.md`
|
||||
- 把国内 controller / worker 的最终正确部署流程写成“复制即可执行”的版本
|
||||
|
||||
---
|
||||
|
||||
## 7. 建议的优秀调试方式:国内日志主动回调到海外
|
||||
|
||||
当前最大问题不是代码本身,而是:
|
||||
|
||||
- 每次都要在国内机执行命令
|
||||
- 再手工复制长日志给海外
|
||||
- 调试效率太低
|
||||
|
||||
最推荐的改法不是继续人工贴日志,而是做“日志回调到海外调试面板”。
|
||||
|
||||
### 7.1 推荐目标
|
||||
|
||||
增加一个轻量调试链路:
|
||||
|
||||
- 国内 controller
|
||||
- 国内 worker
|
||||
- 国内 sync-agent
|
||||
|
||||
把最近 N 条关键日志、关键事件、关键指标,主动推送到海外一个调试接口,或写入海外一张调试表。
|
||||
|
||||
### 7.2 最小可行方案
|
||||
|
||||
推荐只同步“结构化调试事件”,不要直接全量推原始日志文件。
|
||||
|
||||
建议结构:
|
||||
|
||||
- `source_region`
|
||||
- `node_code`
|
||||
- `service`
|
||||
- `event_type`
|
||||
- `level`
|
||||
- `message`
|
||||
- `payload_json`
|
||||
- `created_at`
|
||||
|
||||
来源可以先选这三类:
|
||||
|
||||
- `domaincheck-api`
|
||||
- `domaincheck-worker`
|
||||
- `domaincheck-sync-agent`
|
||||
|
||||
### 7.3 最值得先回调的事件
|
||||
|
||||
不是所有日志都要回传,优先回传高价值事件:
|
||||
|
||||
- Worker 控制指令成功/失败
|
||||
- 任务批次拉取成功/失败
|
||||
- 任务创建成功/失败
|
||||
- 结果投影生成成功/失败
|
||||
- 结果同步推送成功/失败
|
||||
- Redis/PostgreSQL 连接失败
|
||||
- 代理池刷新结果摘要
|
||||
- `domain_started` / `domain_completed` / `domain_failed`
|
||||
|
||||
### 7.4 为什么推荐结构化事件而不是原始日志
|
||||
|
||||
因为结构化事件更适合:
|
||||
|
||||
- 海外 Codex 直接查询分析
|
||||
- 后台页面直接展示
|
||||
- 做筛选、聚合、时间线回放
|
||||
- 后续做自动告警
|
||||
|
||||
### 7.5 建议实现方式
|
||||
|
||||
建议海外增加一个轻量接口,例如:
|
||||
|
||||
- `POST /api/v1/runtime/debug-ingest`
|
||||
|
||||
国内三类服务把关键事件 POST 到海外。
|
||||
|
||||
海外落库到新表,例如:
|
||||
|
||||
- `detect_debug_events`
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `source_region`
|
||||
- `node_code`
|
||||
- `service`
|
||||
- `event_type`
|
||||
- `level`
|
||||
- `message`
|
||||
- `payload_json`
|
||||
- `created_at`
|
||||
|
||||
这样后面海外 Codex 只要直接查海外库,就能复原国内问题,不需要再人工复制日志。
|
||||
|
||||
---
|
||||
|
||||
## 8. 建议下一步实施顺序
|
||||
|
||||
### 方案 A:先收尾展示,再补日志回调
|
||||
|
||||
1. 修海外 cluster/readiness 的 worker 显示
|
||||
2. 清理 `mainland-control-imported`
|
||||
3. 确认结果回流展示
|
||||
4. 再做日志回调
|
||||
|
||||
### 方案 B:先补日志回调,再继续深度调试
|
||||
|
||||
1. 海外新增 `debug-ingest`
|
||||
2. 国内 controller / worker / sync-agent 回调关键事件
|
||||
3. 海外 Codex 直接观察结构化事件
|
||||
4. 再做 cluster/readiness 视图收尾
|
||||
|
||||
如果后续还要继续高频调试,我更推荐 **方案 B**。
|
||||
|
||||
---
|
||||
|
||||
## 9. 当前阶段结论
|
||||
|
||||
截至本交接文档生成时,可以确认:
|
||||
|
||||
- 国内外任务下发链路已打通
|
||||
- 国内本地任务落库已打通
|
||||
- 国内 worker 已实际执行检测
|
||||
- 国内运行时已回传海外
|
||||
- 海外已能看到新的大陆 controller 节点
|
||||
|
||||
当前剩余问题已经从“主流程不通”降级为:
|
||||
|
||||
- 海外 cluster/readiness 视图收尾
|
||||
- 结果回流展示补强
|
||||
- 调试手段升级为结构化日志回调
|
||||
|
||||
主流程已经不再是 blocker。
|
||||
262
docs/20_domainCheck_临时海外控制面联调清单.md
Normal file
262
docs/20_domainCheck_临时海外控制面联调清单.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# domainCheck 临时海外控制面联调清单
|
||||
|
||||
适用场景:
|
||||
|
||||
- 暂时不使用正式海外机器
|
||||
- 先把大陆 `controller + worker` 对接到当前测试海外机
|
||||
- 先跑通“控制面 + 同步 + 观测”全链路,再切回正式海外环境
|
||||
|
||||
当前临时海外控制面:
|
||||
|
||||
- 节点编码:`overseas-control-01`
|
||||
- 节点角色:`overseas / control`
|
||||
- 机器 IP:`152.53.37.118`
|
||||
- 后台地址:`http://152.53.37.118/`
|
||||
- API 基址:`http://152.53.37.118:8100`
|
||||
|
||||
## 1. 当前目标拓扑
|
||||
|
||||
本次联调按下面的角色分工:
|
||||
|
||||
- 大陆 controller
|
||||
- 承担 API 控制面
|
||||
- 承担 Sync Agent
|
||||
- 可以兼跑本机 Worker
|
||||
- 大陆 worker
|
||||
- 只承担检测执行
|
||||
- 临时海外控制面
|
||||
- 只承担 API 控制与同步接收
|
||||
- 不承载本机 Worker
|
||||
- 不承载 Sync Agent
|
||||
|
||||
## 2. 临时海外控制面应有状态
|
||||
|
||||
在临时海外控制面机器上执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/check_temp_overseas_control.sh
|
||||
```
|
||||
|
||||
预期:
|
||||
|
||||
- `domaincheck-api` 为 `active (running)`
|
||||
- `domaincheck-worker` 为 `inactive (dead)` 或禁用
|
||||
- `runtime.status.data.node`
|
||||
- `code=overseas-control-01`
|
||||
- `region=overseas`
|
||||
- `role=control`
|
||||
- `runtime.status.data.worker.expected_on_this_node=false`
|
||||
- `runtime.status.data.sync_agent.expected_on_this_node=false`
|
||||
- `runtime.status.data.detect.phase_label=当前节点不承载`
|
||||
|
||||
## 3. 大陆 controller 切到临时海外控制面
|
||||
|
||||
在大陆 controller 上执行:
|
||||
|
||||
```bash
|
||||
sed -i 's#^SYNC_TARGET_API_BASE_URL=.*#SYNC_TARGET_API_BASE_URL=http://152.53.37.118:8100#' /etc/default/domaincheck-api
|
||||
sed -i 's/^SYNC_PUSH_ENABLED=.*/SYNC_PUSH_ENABLED=true/' /etc/default/domaincheck-api
|
||||
|
||||
systemctl restart domaincheck-api
|
||||
systemctl restart domaincheck-sync-agent
|
||||
systemctl restart domaincheck-worker
|
||||
sleep 3
|
||||
```
|
||||
|
||||
然后检查:
|
||||
|
||||
```bash
|
||||
curl -s http://127.0.0.1:8100/api/v1/runtime/readiness
|
||||
echo
|
||||
curl -s http://127.0.0.1:8100/api/v1/runtime/sync-summary
|
||||
```
|
||||
|
||||
预期:
|
||||
|
||||
- `runtime/readiness` 至少不是大陆本机配置错误导致的 `blocking`
|
||||
- `runtime/sync-summary.data.enabled=true`
|
||||
- `runtime/sync-summary.data.target_api_base_url=http://152.53.37.118:8100`
|
||||
|
||||
## 4. 大陆 worker 检查项
|
||||
|
||||
在大陆 worker 上执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/check_mainland_worker.sh
|
||||
```
|
||||
|
||||
预期:
|
||||
|
||||
- `NODE_CODE=mainland-worker-01`
|
||||
- `NODE_REGION=mainland`
|
||||
- `NODE_ROLE=worker`
|
||||
- `domaincheck-worker` 为 `active (running)`
|
||||
|
||||
如果大陆 controller 也兼跑检测,再执行:
|
||||
|
||||
```bash
|
||||
systemctl status domaincheck-worker --no-pager -l
|
||||
echo
|
||||
curl -s http://127.0.0.1:8100/api/v1/runtime/status
|
||||
```
|
||||
|
||||
预期:
|
||||
|
||||
- `worker.running=true`
|
||||
- `worker.expected_on_this_node=true`
|
||||
|
||||
## 5. 最短联调命令
|
||||
|
||||
### 5.1 在大陆 controller 上
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/check_temp_link.sh http://127.0.0.1:8100 http://152.53.37.118:8100
|
||||
```
|
||||
|
||||
关注点:
|
||||
|
||||
- `push_sync` 返回 `code=0` 或幂等成功
|
||||
- 不再出现目标地址为空
|
||||
- 不再出现 `SYNC_PUSH_ENABLED=false`
|
||||
|
||||
关注点:
|
||||
|
||||
- `cluster` 中至少能看到:
|
||||
- `overseas-control-01`
|
||||
- 大陆 `mainland-controller-01`
|
||||
- 大陆 `mainland-worker-01`
|
||||
- `sync-summary` 中能看到来自大陆的接收记录
|
||||
- `readiness` 不再是“完全单节点海外态”
|
||||
|
||||
## 6. 后台页面应如何理解
|
||||
|
||||
打开:
|
||||
|
||||
- `http://152.53.37.118/`
|
||||
|
||||
在运行中心里看到下面这些内容时,属于正常:
|
||||
|
||||
- `本机 Worker:当前节点不承载`
|
||||
- `Sync Agent:当前节点不承载`
|
||||
- `当前检测阶段:当前节点不承载`
|
||||
- `代理运行态:不适用`
|
||||
|
||||
这不是故障,而是因为当前节点就是临时海外控制面。
|
||||
|
||||
真正应该关注的是:
|
||||
|
||||
- `集群节点`
|
||||
- `有效执行节点`
|
||||
- `同步状态`
|
||||
- `多机就绪度`
|
||||
|
||||
## 7. 判断“到底有几台 Worker 在工作”
|
||||
|
||||
如果页面上“在线 Worker 数”和“实际正在跑检测的节点数”看起来不一致,以数据库为准。
|
||||
|
||||
在大陆 controller 上执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/check_worker_participation.sh
|
||||
```
|
||||
|
||||
判断规则:
|
||||
|
||||
- `detect_worker_nodes`
|
||||
- 看谁在线
|
||||
- 看谁是 `worker_online=true`
|
||||
- `detect_participating=true` 只能说明它曾被判断为“正在参与”
|
||||
- `detect_job_items`
|
||||
- 看任务到底被哪台节点 `claimed_by`
|
||||
- 这才是“当前真正干活的节点”
|
||||
- `runtime/status`
|
||||
- 看 `participation_summary.dispatch_active_nodes`
|
||||
- 这是“当前真正执行/领任务的节点”
|
||||
- 看 `participation_summary.non_participating_nodes`
|
||||
- 这是“在线但未参与的节点”
|
||||
- 看 `non_participating_nodes[].participation_state`
|
||||
- `standby` 表示在线待命
|
||||
- `load_syncing` 表示负载待确认,不要直接算成“正在干活”
|
||||
- 看 `log_sync`
|
||||
- 能直接确认远端日志回传是否开启、是关键还是全量、样本来自哪些节点
|
||||
|
||||
## 8. 常见误判
|
||||
|
||||
### 8.1 海外控制面显示“本机 Worker 不承载”
|
||||
|
||||
这是正常,不是故障。
|
||||
|
||||
### 8.2 页面显示“在线 Worker 1”,但你部署了 2 台大陆机器
|
||||
|
||||
先区分:
|
||||
|
||||
- “有效执行节点”是可承担任务的在线节点数
|
||||
- “当前参与检测节点”是当前真的在领任务、跑任务的节点
|
||||
- “在线但未参与节点”是已经在线、可承接任务,但当前这轮还没分到任务的节点
|
||||
|
||||
如果 controller 没兼跑检测,通常只会看到独立 worker 在真正执行。
|
||||
|
||||
### 8.3 controller 机器也开了 worker 服务,但没有领任务
|
||||
|
||||
这不一定是 bug,可能只是当前调度没有分到它。应以 `detect_job_items.claimed_by` 为准,不要只看服务在线。
|
||||
|
||||
### 8.4 页面显示“负载待确认”
|
||||
|
||||
这不是新的故障状态,而是为了避免误判:
|
||||
|
||||
- 节点已经上报 `busy` 或有 `current_load`
|
||||
- 但当前还没看到明确的 `items_claimed / items_running / processed_recent`
|
||||
|
||||
通常是心跳和任务快照还没完全对齐。先等下一轮刷新,再结合 `claimed_by` 和 `participation_summary` 判断,不要立刻当作“这台机器已经在跑检测”。
|
||||
|
||||
### 8.5 日志控制台看不到大陆节点过程
|
||||
|
||||
先看 `runtime/status` 或页面里的“远端日志回传”:
|
||||
|
||||
- 若 `enabled=false`
|
||||
- 说明本来就没开回传
|
||||
- 若 `enabled=true` 但 `line_count=0`
|
||||
- 说明开关已开,但当前还没有远端样本
|
||||
- 若 `source_nodes` 里没有目标大陆节点
|
||||
- 说明该节点这轮还没回传日志,先看它是否真的在参与检测
|
||||
|
||||
## 9. 联调完成后的回滚
|
||||
|
||||
如果你后续要切回正式海外机器,在大陆 controller 上把目标地址改回正式值即可:
|
||||
|
||||
```bash
|
||||
sed -i 's#^SYNC_TARGET_API_BASE_URL=.*#SYNC_TARGET_API_BASE_URL=http://正式海外控制面IP:8100#' /etc/default/domaincheck-api
|
||||
systemctl restart domaincheck-api
|
||||
systemctl restart domaincheck-sync-agent
|
||||
sleep 3
|
||||
```
|
||||
|
||||
如果临时海外控制面不再使用,可在该机器上保留 `domaincheck-api` 供后续调试,也可以停掉:
|
||||
|
||||
```bash
|
||||
systemctl stop domaincheck-api
|
||||
```
|
||||
|
||||
## 10. 本次临时海外控制面结论
|
||||
|
||||
当前这台测试海外机已经整理为:
|
||||
|
||||
- 纯 `overseas-control`
|
||||
- API 正常
|
||||
- Worker 不承载
|
||||
- Sync Agent 不承载
|
||||
- 数据已清空并按首装态初始化
|
||||
- 可直接作为大陆 controller 的临时同步接收端
|
||||
|
||||
## 11. 配套脚本
|
||||
|
||||
- 临时海外控制面自检:
|
||||
- `domain-api/deploy/multi-region/check_temp_overseas_control.sh`
|
||||
- 大陆 controller -> 临时海外控制面联调检查:
|
||||
- `domain-api/deploy/multi-region/check_temp_link.sh`
|
||||
- 三机拓扑总览检查:
|
||||
- `domain-api/deploy/multi-region/check_temp_topology.sh`
|
||||
- 当前活跃任务由谁真正执行:
|
||||
- `domain-api/deploy/multi-region/check_worker_participation.sh`
|
||||
- 大陆 worker 本机自检:
|
||||
- `domain-api/deploy/multi-region/check_mainland_worker.sh`
|
||||
708
docs/21_domainCheck_海外主机集中运维与自动化方案.md
Normal file
708
docs/21_domainCheck_海外主机集中运维与自动化方案.md
Normal file
@@ -0,0 +1,708 @@
|
||||
# 21 domainCheck 海外主机集中运维与自动化方案
|
||||
|
||||
如果当前你不是在做“为什么要这么设计”的方案评审,而是已经进入真实收口、准备上线阶段,建议先跳转:
|
||||
|
||||
- `docs/25_domainCheck_海外单脑控制面上线收口总表.md`
|
||||
- `docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md`
|
||||
- `docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md`
|
||||
|
||||
## 一、为什么要升级成“集中运维”
|
||||
|
||||
这段时间的多机联调已经证明一个事实:
|
||||
|
||||
- 现在这套“人在海外主机上看后台,再去大陆机器上手工跑命令、复制日志、判断状态”的方式,能联调,但效率很低
|
||||
- 一旦节点数从 `2` 台增加到 `3` 台、`5` 台、`10` 台,复杂度会快速失控
|
||||
- 国内机器上又不能稳定部署 Codex,因此不能指望每台机器都具备“本机智能调试能力”
|
||||
- 检测日志很大,靠人工复制日志片段,不适合做持续诊断
|
||||
|
||||
所以后续不应该继续堆更多“检查脚本”,而应该把整个体系升级成:
|
||||
|
||||
> 海外主机作为唯一运维控制面,统一接管大陆机器的安装、更新、重启、巡检、日志回流和故障诊断。
|
||||
|
||||
一句话目标:
|
||||
|
||||
> 只在海外主机操作,大陆机器尽量不需要人工登录。
|
||||
|
||||
---
|
||||
|
||||
## 二、最终目标形态
|
||||
|
||||
### 1. 海外主机承担什么
|
||||
|
||||
海外主机作为唯一控制面,承担:
|
||||
|
||||
- Web 后台
|
||||
- API 控制面
|
||||
- 运维任务中心
|
||||
- 发布包仓库
|
||||
- 节点注册与权限中心
|
||||
- 日志汇聚与诊断入口
|
||||
- 远程命令编排
|
||||
- 巡检结果展示
|
||||
|
||||
也就是说,后续所有动作都从海外主机发起:
|
||||
|
||||
- 新机器纳管
|
||||
- 初始化安装
|
||||
- 发布更新
|
||||
- 配置下发
|
||||
- 服务重启
|
||||
- 健康检查
|
||||
- 采集诊断包
|
||||
- 远端日志查看
|
||||
- 故障一键排查
|
||||
|
||||
### 2. 大陆机器承担什么
|
||||
|
||||
大陆机器不再承担复杂控制逻辑,只承担:
|
||||
|
||||
- `domaincheck worker/controller` 本体服务
|
||||
- 一个轻量 Node Agent
|
||||
- 本机 systemd / 日志 / 版本 / 健康信息暴露
|
||||
- 接收控制面任务并执行
|
||||
- 将执行结果、日志、诊断包回传到海外主机
|
||||
|
||||
这意味着大陆机器以后是“被管理对象”,而不是“人工登录操作对象”。
|
||||
|
||||
---
|
||||
|
||||
## 三、推荐方案
|
||||
|
||||
## 方案 A:海外控制面 + 大陆 Node Agent
|
||||
|
||||
这是我建议的主方案,也是长期最优方案。
|
||||
|
||||
### 核心思想
|
||||
|
||||
不要把“SSH 到每台机器执行命令”作为主链路,而是让每台大陆机器常驻一个 Agent:
|
||||
|
||||
- Agent 主动连海外控制面
|
||||
- Agent 拉取待执行任务
|
||||
- 本地执行 systemd / shell / 发布 / 巡检
|
||||
- Agent 把 stdout / stderr / 状态 / 日志游标回传
|
||||
|
||||
这样做的好处是:
|
||||
|
||||
- 不要求海外机能直接入站打通到大陆机
|
||||
- 不要求每次人工 SSH
|
||||
- 不怕 SSH 权限、跳板机、端口变化导致整套流程断掉
|
||||
- 天然适合 NAT、弱网络、多机扩容
|
||||
|
||||
### 交互方式
|
||||
|
||||
建议 Agent 使用下面其中一种方式主动连海外控制面:
|
||||
|
||||
#### 首选:HTTPS 长轮询
|
||||
|
||||
- `agent -> overseas-api`
|
||||
- 周期拉取任务
|
||||
- 周期上报心跳、版本、服务状态、日志摘要
|
||||
|
||||
优点:
|
||||
|
||||
- 实现最简单
|
||||
- 最容易兼容现有 Python / FastAPI 架构
|
||||
- 容易先落 MVP
|
||||
|
||||
#### 可升级:WebSocket 常连
|
||||
|
||||
- 建立长连接
|
||||
- 海外控制面可实时下发任务
|
||||
- Agent 实时回传执行日志
|
||||
|
||||
优点:
|
||||
|
||||
- 更实时
|
||||
- 日志流式体验更好
|
||||
|
||||
缺点:
|
||||
|
||||
- 第一版复杂度更高
|
||||
|
||||
### 为什么 Agent 比 SSH 更优
|
||||
|
||||
SSH 适合作为:
|
||||
|
||||
- 首次 bootstrap
|
||||
- 临时人工兜底
|
||||
- 非常规应急
|
||||
|
||||
但不适合作为日常主运维链路,因为:
|
||||
|
||||
- 节点一多,权限和连通性管理会变得脆弱
|
||||
- 脚本回显、超时、日志采集很难标准化
|
||||
- 人工 SSH 本质上还是“远程手工运维”
|
||||
|
||||
所以最佳做法是:
|
||||
|
||||
- SSH 只用于首次纳管
|
||||
- 日常统一走 Agent
|
||||
|
||||
## 三点五、当前已经落地的第一版操作闭环
|
||||
|
||||
这套方案现在已经不只是设计稿,仓库里已经有一批可以直接使用的统一入口:
|
||||
|
||||
- `domain-api/deploy/multi-region/init_ops_center_config.sh`
|
||||
- `domain-api/deploy/multi-region/drive_ops_center.sh`
|
||||
- `domain-api/deploy/multi-region/drive_release_hub.sh`
|
||||
- `domain-api/deploy/multi-region/drive_ops_action.sh`
|
||||
- `domain-api/deploy/multi-region/build_node_agent_bootstrap_plan.sh`
|
||||
|
||||
推荐从海外控制面按这个顺序使用:
|
||||
|
||||
### 1. 初始化控制面配置
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-api
|
||||
bash domain-api/deploy/multi-region/init_ops_center_config.sh \
|
||||
/etc/default/domaincheck-ops-center \
|
||||
http://121.204.244.188:8100 \
|
||||
http://152.53.37.118:8100 \
|
||||
https://api.example.com
|
||||
```
|
||||
|
||||
### 2. 查看当前统一配置
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh config
|
||||
```
|
||||
|
||||
### 3. 在控制面本机生成发布包
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh release-package
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh release-launchpad
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh release-preview
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh release-preview-smart worker
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh release-show
|
||||
```
|
||||
|
||||
### 4. 导出一份联调/交接报告
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-export
|
||||
```
|
||||
|
||||
### 5. 为新节点导出接管计划
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh agent-plan-export \
|
||||
/opt/domaincheck/domain-api/runtime/ops-center-reports/agent-plans \
|
||||
http://127.0.0.1:8100 \
|
||||
mainland-worker-02 \
|
||||
mainland \
|
||||
worker \
|
||||
https://api.example.com \
|
||||
/opt/domaincheck
|
||||
```
|
||||
|
||||
这五步对应的意义分别是:
|
||||
|
||||
- 先统一控制面默认地址和身份
|
||||
- 再确认驾驶舱当前在看哪个环境
|
||||
- 再把发布物、发布前预检和发版驾驶舱都收回统一入口,不再额外记根目录脚本
|
||||
- 再把现场收敛成可以回看、可以交接的报告
|
||||
- 最后为新增节点生成标准接管方案
|
||||
|
||||
这样后面无论是海外 Codex 自动驾驶、后台按钮,还是人工运维,都不再需要先去大陆机器手工拼命令。
|
||||
|
||||
## 三点六、现在发布驾驶舱已经进入统一数据口径
|
||||
|
||||
目前发布侧也已经不是零散接口拼出来的状态,而是收敛成了一套统一判断:
|
||||
|
||||
- `GET /api/v1/ops/releases/launchpad`
|
||||
- `ops overview -> release_hub.launchpad`
|
||||
- `check_release_hub.sh`
|
||||
- `drive_release_hub.sh launchpad`
|
||||
- 运维中枢页面里的“发布驾驶舱”
|
||||
|
||||
这几处现在复用的是同一套结论,都会统一告诉你:
|
||||
|
||||
- 当前是 `ready / attention / blocked`
|
||||
- 最新发布包是否可用
|
||||
- 最新 Release 是否已经建立
|
||||
- Worker 智能灰度是否可发
|
||||
- Control 发布是否可发
|
||||
- 下一步推荐动作是什么
|
||||
|
||||
同时,`GET /api/v1/ops/runbook` 里的标准作业路径 `release_progression` 也已经切到同一套发布驾驶舱判断。
|
||||
也就是说,海外控制面看到的“标准作业路径”和“发布驾驶舱”不会再出现一套说能发、一套说先补接管的分裂口径。
|
||||
|
||||
现在又往前推进了一步:
|
||||
|
||||
- `POST /api/v1/ops/runbook/sequences/{sequence_key}/execute`
|
||||
|
||||
后台上的标准作业路径按钮,后续都应该优先走这个入口,再由后端统一分发到 driver action / playbook / rollout 预案,而不是前端自己维护动作分支。
|
||||
|
||||
这样后续海外 Codex、后台按钮和命令行脚本拿到的就不再是三套不同口径,而是同一套“发布驾驶判断”。
|
||||
|
||||
## 三点七、现在回执队列也已经进入统一治理入口
|
||||
|
||||
除了发布驾驶舱,Node Agent 回执队列这一层现在也已经不再是“只能看、不能管”的状态。
|
||||
|
||||
当前已经统一收口成三类入口:
|
||||
|
||||
- 页面:
|
||||
- OpsCenter 托管节点表可以直接打开“回执队列治理”抽屉
|
||||
- 驾驶建议:
|
||||
- `dead_letter / retrying` 会优先落到标准动作模板
|
||||
- 海外单入口 CLI:
|
||||
- `drive_ops_center.sh queue-status`
|
||||
- `drive_ops_center.sh queue-records`
|
||||
- `drive_ops_center.sh queue-flush`
|
||||
- `drive_ops_center.sh queue-replay`
|
||||
- `drive_ops_center.sh queue-replay-record`
|
||||
- `drive_ops_center.sh queue-discard-record`
|
||||
|
||||
这意味着海外主机已经可以统一处理:
|
||||
|
||||
- 哪台节点存在积压 / 死信
|
||||
- 头部记录是什么
|
||||
- 什么时候应该立即冲刷
|
||||
- 什么时候应该重放
|
||||
- 什么时候应该说明原因后丢弃
|
||||
|
||||
当前阶段仍然明确限制为:
|
||||
|
||||
- `record_visibility=head_only`
|
||||
- 所有治理动作都落成正式 `ops job`
|
||||
- 不直接 SSH 到节点改队列文件
|
||||
|
||||
这样以后即使把远端全量死信记录正式投影到控制面,也只是“扩可见范围”,而不是重新推翻当前模型。
|
||||
|
||||
---
|
||||
|
||||
## 四、这套方案要解决的具体问题
|
||||
|
||||
## 1. 安装部署自动化
|
||||
|
||||
目标:
|
||||
|
||||
- 海外控制面点一次“新增节点”
|
||||
- 填一个节点模板
|
||||
- 大陆机器自动初始化
|
||||
|
||||
建议流程:
|
||||
|
||||
1. 海外后台新增节点
|
||||
2. 生成 `bootstrap token`
|
||||
3. 大陆机器只执行一次极短安装命令
|
||||
4. Node Agent 注册到海外控制面
|
||||
5. 控制面向该节点下发:
|
||||
- 拉取发布包
|
||||
- 解压
|
||||
- 生成 `/etc/default/...`
|
||||
- 安装 systemd
|
||||
- 启动服务
|
||||
6. 回传安装结果
|
||||
|
||||
这样后续加机器时,不需要再重复人工对照文档逐条敲。
|
||||
|
||||
## 2. 更新发布自动化
|
||||
|
||||
目标:
|
||||
|
||||
- 海外主机统一推版本
|
||||
- 大陆节点自动拉包、灰度更新、失败回滚
|
||||
|
||||
这里强烈建议:
|
||||
|
||||
> 后续不要让大陆机器自己跑 git 作为正式更新链路。
|
||||
|
||||
而是改成:
|
||||
|
||||
- 海外控制面构建发布包
|
||||
- 版本号固定
|
||||
- Agent 下载指定 release 包
|
||||
- 校验 checksum
|
||||
- 切换当前版本软链
|
||||
- 重启服务
|
||||
- 回传成功/失败
|
||||
|
||||
这样比远程 `git pull` 更稳,因为:
|
||||
|
||||
- 不依赖每台机器 git 权限
|
||||
- 不怕工作区脏文件
|
||||
- 不怕 root/www 用户混用
|
||||
- 可回滚
|
||||
|
||||
推荐目录形态:
|
||||
|
||||
```text
|
||||
/opt/domaincheck/releases/<version>/
|
||||
/opt/domaincheck/current -> /opt/domaincheck/releases/<version>/
|
||||
```
|
||||
|
||||
更新时:
|
||||
|
||||
- 下载新版本到 `releases`
|
||||
- 校验
|
||||
- 切换 `current`
|
||||
- `systemctl restart ...`
|
||||
|
||||
失败就回滚软链。
|
||||
|
||||
## 3. 远程命令执行自动化
|
||||
|
||||
目标:
|
||||
|
||||
- 海外控制面能发“结构化任务”
|
||||
- 不再让人手工复制命令
|
||||
|
||||
建议任务类型:
|
||||
|
||||
- `service.start`
|
||||
- `service.stop`
|
||||
- `service.restart`
|
||||
- `service.status`
|
||||
- `deploy.release`
|
||||
- `config.render`
|
||||
- `diagnostics.collect`
|
||||
- `logs.tail`
|
||||
- `script.run`
|
||||
- `health.check`
|
||||
|
||||
每个任务统一回传:
|
||||
|
||||
- 任务 ID
|
||||
- 节点编码
|
||||
- 开始时间 / 结束时间
|
||||
- exit code
|
||||
- stdout
|
||||
- stderr
|
||||
- 结构化结果 JSON
|
||||
|
||||
这样后面后台才能真正做“操作中心”。
|
||||
|
||||
## 4. 日志集中回流
|
||||
|
||||
目标:
|
||||
|
||||
- 海外后台就能看到大陆机器日志
|
||||
- 不再人工抄 `journalctl`
|
||||
|
||||
### 日志回流建议分三层
|
||||
|
||||
#### A. 关键事件流
|
||||
|
||||
只回传关键事件:
|
||||
|
||||
- 服务启动
|
||||
- 服务重启
|
||||
- 任务开始
|
||||
- 任务完成
|
||||
- 代理刷新失败
|
||||
- Redis/DB 连接异常
|
||||
- 第三方站点异常
|
||||
|
||||
适合默认长期开启。
|
||||
|
||||
#### B. 诊断模式日志流
|
||||
|
||||
像你现在提的“关闭 / 关键 / 全量回传”一样:
|
||||
|
||||
- `off`
|
||||
- `key`
|
||||
- `full`
|
||||
|
||||
这是正确方向,应该继续保留。
|
||||
|
||||
#### C. 诊断包
|
||||
|
||||
当出现疑难问题时,一键打包:
|
||||
|
||||
- 最近 N 分钟 `journalctl`
|
||||
- `runtime/status`
|
||||
- `runtime/cluster`
|
||||
- `detect_worker.log tail`
|
||||
- `/etc/default/*`
|
||||
- 当前版本号
|
||||
- 本机健康检查输出
|
||||
|
||||
然后上传海外主机。
|
||||
|
||||
这比全量实时传所有日志更经济,也更适合定位问题。
|
||||
|
||||
## 5. 健康巡检自动化
|
||||
|
||||
目标:
|
||||
|
||||
- 每台大陆机自动自检
|
||||
- 海外后台只看结果
|
||||
|
||||
建议 Agent 每 30 秒到 60 秒上报:
|
||||
|
||||
- 节点在线状态
|
||||
- 当前版本
|
||||
- API / Worker / Sync Agent 运行态
|
||||
- Redis / PostgreSQL / 磁盘 / 内存 / CPU
|
||||
- 最近告警
|
||||
- 当前任务负载
|
||||
- 最近日志时间
|
||||
|
||||
并把现有脚本升级为 Agent 内部检查项:
|
||||
|
||||
- `check_mainland_controller.sh`
|
||||
- `check_mainland_worker.sh`
|
||||
- `check_temp_topology.sh`
|
||||
- `check_worker_participation.sh`
|
||||
|
||||
后续不是人工执行这些脚本,而是 Agent 周期性执行并结构化上传结果。
|
||||
|
||||
---
|
||||
|
||||
## 五、建议的系统分层
|
||||
|
||||
## 1. 海外控制面
|
||||
|
||||
建议新增一个“运维控制模块”,逻辑上可放进 `domain-api`,后续再拆独立服务也可以。
|
||||
|
||||
### 需要的核心对象
|
||||
|
||||
#### `managed_nodes`
|
||||
|
||||
记录纳管节点:
|
||||
|
||||
- `node_code`
|
||||
- `region`
|
||||
- `role`
|
||||
- `hostname`
|
||||
- `ip`
|
||||
- `agent_version`
|
||||
- `current_release`
|
||||
- `status`
|
||||
- `ssh_enabled`
|
||||
- `agent_last_seen_at`
|
||||
- `tags`
|
||||
|
||||
#### `ops_jobs`
|
||||
|
||||
记录运维任务:
|
||||
|
||||
建议以后直接以 [ops_job_contract.md](/www/wwwroot/getDomain/docs/schemas/ops_job_contract.md:1) 为正式母本。
|
||||
|
||||
- `job_id`
|
||||
- `job_type`
|
||||
- `target_nodes`
|
||||
- `payload`
|
||||
- `created_by`
|
||||
- `status`
|
||||
- `started_at`
|
||||
- `finished_at`
|
||||
|
||||
#### `ops_job_steps`
|
||||
|
||||
记录每个节点执行步骤:
|
||||
|
||||
- `node_code`
|
||||
- `step_name`
|
||||
- `status`
|
||||
- `stdout`
|
||||
- `stderr`
|
||||
- `result_json`
|
||||
|
||||
#### `node_log_streams`
|
||||
|
||||
记录日志游标和日志回流状态:
|
||||
|
||||
- `node_code`
|
||||
- `source`
|
||||
- `mode`
|
||||
- `cursor`
|
||||
- `last_received_at`
|
||||
|
||||
## 2. Node Agent
|
||||
|
||||
建议单独做一个轻量 Python 服务,比如:
|
||||
|
||||
```text
|
||||
domaincheck-node-agent
|
||||
```
|
||||
|
||||
职责:
|
||||
|
||||
- 周期心跳
|
||||
- 拉取任务
|
||||
- 本地执行
|
||||
- 采集日志
|
||||
- 上报结果
|
||||
- 生成诊断包
|
||||
|
||||
Agent 尽量独立于业务主程序,不要把它耦合进 `detect_worker.py`。
|
||||
|
||||
原因:
|
||||
|
||||
- 运维系统不能依赖业务进程是否正常
|
||||
- 即使 Worker 崩了,Agent 还应该活着,才能帮你排障
|
||||
|
||||
---
|
||||
|
||||
## 六、对你当前项目最合适的落地路线
|
||||
|
||||
## 第一阶段:先做“控制面集中化”
|
||||
|
||||
目标:
|
||||
|
||||
- 海外后台统一看到所有大陆机器
|
||||
- 一键拉诊断
|
||||
- 一键执行已有检查脚本
|
||||
- 一键切日志回传模式
|
||||
|
||||
这个阶段先不碰太多发布链路,优先把“看”和“查”统一。
|
||||
|
||||
### 交付物
|
||||
|
||||
- Node Agent MVP
|
||||
- 海外后台“节点管理”页
|
||||
- 海外后台“运维任务”页
|
||||
- 海外后台“远端日志”页
|
||||
- 海外后台“诊断包”页
|
||||
|
||||
## 第二阶段:再做“一键更新”
|
||||
|
||||
目标:
|
||||
|
||||
- 海外控制面选择版本
|
||||
- 指定节点灰度发布
|
||||
- 自动回滚
|
||||
|
||||
### 交付物
|
||||
|
||||
- 发布包生成器
|
||||
- `release manifest`
|
||||
- Agent 下载 / 校验 / 切换版本
|
||||
- 回滚机制
|
||||
|
||||
## 第三阶段:再做“一键安装新节点”
|
||||
|
||||
目标:
|
||||
|
||||
- 新机器只执行一次 bootstrap
|
||||
- 其余全部由海外控制面接管
|
||||
|
||||
### 交付物
|
||||
|
||||
- bootstrap token
|
||||
- 安装向导
|
||||
- 节点注册流程
|
||||
- 环境模板生成器
|
||||
|
||||
---
|
||||
|
||||
## 七、比“SSH 全接管”更优的地方
|
||||
|
||||
你提的方向是:
|
||||
|
||||
> 海外主机配置好 SSH,后续所有大陆机器都由代码内部接管
|
||||
|
||||
这个方向本身是对的,但如果只做“SSH 全接管”,还不够优秀。
|
||||
|
||||
更优解是:
|
||||
|
||||
> SSH 只作为纳管和兜底方式;日常统一走 Agent 主动连接。
|
||||
|
||||
这样好处是:
|
||||
|
||||
- 架构更稳
|
||||
- 不依赖每次远程入站打通
|
||||
- 不怕某些网络环境 SSH 不稳定
|
||||
- 更适合未来节点继续增加
|
||||
- 更容易做权限分级、审计、结果留痕
|
||||
|
||||
所以我建议最终定成:
|
||||
|
||||
### 运维主链路
|
||||
|
||||
- `海外控制面 -> Agent 任务编排 -> 大陆节点执行 -> 回传结果`
|
||||
|
||||
### 运维兜底链路
|
||||
|
||||
- `海外控制面 -> SSH -> 大陆节点`
|
||||
|
||||
---
|
||||
|
||||
## 八、和现有代码如何衔接
|
||||
|
||||
当前项目已经有一些很好的基础,不需要推翻:
|
||||
|
||||
- 多机节点模型
|
||||
- `runtime/status`
|
||||
- `runtime/cluster`
|
||||
- `sync-summary`
|
||||
- 一批巡检脚本
|
||||
- 日志回传开关雏形
|
||||
- 运行中心
|
||||
|
||||
这些都应该保留,并演进成:
|
||||
|
||||
### 当前脚本的未来定位
|
||||
|
||||
- `bootstrap_*.sh`
|
||||
- 保留为 bootstrap / 应急工具
|
||||
- `check_*.sh`
|
||||
- 演进成 Agent 内部的标准诊断动作
|
||||
- `runtime/status`
|
||||
- 继续作为统一运行态接口
|
||||
- `runtime/cluster`
|
||||
- 继续作为统一集群视图
|
||||
- `detect_result_projection / runtime_projection`
|
||||
- 继续作为跨地域观测基础
|
||||
|
||||
也就是说,现有代码不是废掉,而是从“人工脚本时代”升级成“控制面编排时代”。
|
||||
|
||||
---
|
||||
|
||||
## 九、我建议的最优落地决策
|
||||
|
||||
如果只选一个方向,我建议直接定成:
|
||||
|
||||
### 最优方案
|
||||
|
||||
- 海外主机为唯一控制面
|
||||
- 大陆节点统一部署 `domaincheck-node-agent`
|
||||
- Agent 主动访问海外控制面
|
||||
- 日常安装、更新、巡检、日志回流全部走 Agent
|
||||
- SSH 仅保留为 bootstrap 和应急手段
|
||||
- 正式更新统一改为 release 包分发,不再把 `git pull` 作为正式更新链路
|
||||
|
||||
这是当前最值得投入的方向,因为它能同时解决:
|
||||
|
||||
- 调试效率低
|
||||
- 多机管理复杂
|
||||
- 权限混乱
|
||||
- 日志分散
|
||||
- 更新不稳定
|
||||
- 新增节点成本高
|
||||
|
||||
---
|
||||
|
||||
## 十、建议的下一步执行顺序
|
||||
|
||||
不要再继续先补散点 bug,而是先把运维骨架建起来。
|
||||
|
||||
建议顺序:
|
||||
|
||||
1. 固化这份方案
|
||||
2. 新建 `node-agent` 设计草案
|
||||
3. 先做 Agent MVP
|
||||
4. 先接入:
|
||||
- 心跳
|
||||
- 远程任务
|
||||
- 诊断包
|
||||
- 日志 tail
|
||||
5. 海外后台新增:
|
||||
- 节点管理页
|
||||
- 运维任务页
|
||||
- 远端日志页
|
||||
6. 再把现有检查脚本封成 Agent 动作
|
||||
7. 最后再做发布链路自动化
|
||||
|
||||
---
|
||||
|
||||
## 十一、结论
|
||||
|
||||
当前最优策略不是“继续加脚本”,而是:
|
||||
|
||||
> 把 domainCheck 从“多机联调项目”升级成“海外控制面统一接管大陆节点的自动化运维系统”。
|
||||
|
||||
从长期看,这会比继续靠人工 SSH、人工复制日志、人工比对状态高效很多,也更符合你后续继续扩机器的目标。
|
||||
1052
docs/22_domainCheck_海外Codex驾驶员与OpsCenter落地路线.md
Normal file
1052
docs/22_domainCheck_海外Codex驾驶员与OpsCenter落地路线.md
Normal file
File diff suppressed because it is too large
Load Diff
1163
docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md
Normal file
1163
docs/23_domainCheck_终局运维架构设计_海外单脑控制面.md
Normal file
File diff suppressed because it is too large
Load Diff
4421
docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md
Normal file
4421
docs/24_domainCheck_NodeAgent协议与ReleaseHub设计.md
Normal file
File diff suppressed because it is too large
Load Diff
430
docs/25_domainCheck_海外单脑控制面上线收口总表.md
Normal file
430
docs/25_domainCheck_海外单脑控制面上线收口总表.md
Normal file
@@ -0,0 +1,430 @@
|
||||
# 25 domainCheck 海外单脑控制面上线收口总表
|
||||
|
||||
## 一、这份文档解决什么问题
|
||||
|
||||
这份文档不是再讲设计,而是把当前项目进入正式上线前,真正需要收口的事项压成一张总表。
|
||||
|
||||
适用场景:
|
||||
|
||||
- 海外主机已经作为单脑控制面
|
||||
- 大陆节点已经开始纳管
|
||||
- Ops Center / Codex Driver / CLI 都已经接入同一套 `ops` contract
|
||||
- 目标从“能联调”切换到“能稳定上线、能持续运维”
|
||||
|
||||
这份文档优先回答 4 个问题:
|
||||
|
||||
1. 现在能不能继续收口
|
||||
2. 现在能不能正式发布
|
||||
3. 还有哪些阻断项没清
|
||||
4. 下一步到底先跑哪条命令
|
||||
|
||||
---
|
||||
|
||||
## 二、上线前统一原则
|
||||
|
||||
上线前必须统一成下面这条工作方式:
|
||||
|
||||
- 海外主机作为唯一主驾驶席
|
||||
- 页面、CLI、Codex 共用同一套后端判断
|
||||
- 默认先看 `go-live-summary`
|
||||
- 真要解释原因时再下钻 `stack-diagnosis`
|
||||
- 真要执行动作时走 `driver-resolve / execute-resolved`
|
||||
- 真要发布或放量时走 `Release Hub / rollout`
|
||||
|
||||
不再推荐:
|
||||
|
||||
- 人工分别登录多台大陆机器拼状态
|
||||
- 每次上线都从 `journalctl + systemctl + curl` 临时组合判断
|
||||
- 前端、CLI、Codex 各自维护不同的默认下一步
|
||||
|
||||
---
|
||||
|
||||
## 三、正式上线门禁
|
||||
|
||||
### 1. 收口门禁
|
||||
|
||||
至少同时满足:
|
||||
|
||||
- `go_live_summary.go_live_status != blocked`
|
||||
- `stack_diagnosis.diagnosis.stack_status != blocked`
|
||||
- `route_surface_complete=true`
|
||||
- `driver-feed.automation_coverage.launch_status != blocked`
|
||||
- 首屏默认下一步已经明确,不再是模糊人工判断
|
||||
|
||||
### 2. 发布门禁
|
||||
|
||||
至少同时满足:
|
||||
|
||||
- `publish_ready=true`
|
||||
- `launchpad_status != blocked`
|
||||
- 不存在未处理的关键 `blocking_reasons`
|
||||
- 当前发布主车道已经清晰落在:
|
||||
- `review_smart_rollout_preview`
|
||||
- `review_control_rollout`
|
||||
- `publish_latest_worker`
|
||||
- `create_release_rollout_*`
|
||||
|
||||
### 3. 运维门禁
|
||||
|
||||
至少同时满足:
|
||||
|
||||
- 海外控制面 API 稳定在线
|
||||
- 大陆 controller / worker 心跳稳定
|
||||
- 节点接管缺口已经收口,或至少首个缺口节点已有明确恢复动作
|
||||
- 远端日志回传可按需开启、复核、关闭
|
||||
- 运行中心首屏能直接区分:
|
||||
- 在线但未参与
|
||||
- 正在执行 / 正在领任务
|
||||
|
||||
---
|
||||
|
||||
## 四、真正的起手顺序
|
||||
|
||||
每次准备上线、复核、值班接手时,都按这个顺序来:
|
||||
|
||||
### 第 1 步:看上线收口摘要
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/getDomain
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-check http://127.0.0.1:8100 http://127.0.0.1:8100 summary
|
||||
```
|
||||
|
||||
如果当前是临时海外控制面联调,也可以把第二个地址替换成海外目标 API。
|
||||
|
||||
第一眼重点只看:
|
||||
|
||||
- `go_live_status`
|
||||
- `publish_status`
|
||||
- `blocking_reasons`
|
||||
- `warnings`
|
||||
- `next_step_action_code`
|
||||
- `operator_title`
|
||||
|
||||
如果你怀疑当前是环境本身有漂移,而不是业务链路没收口,先执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh env-audit
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh runtime-refresh-recover
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover
|
||||
```
|
||||
|
||||
重点只看:
|
||||
|
||||
- `status`
|
||||
- `headline`
|
||||
- `missing_items`
|
||||
- `tooling_items`
|
||||
- `runtime.preflight_ok`
|
||||
- `runtime.readiness_status`
|
||||
- `runtime.route_surface_complete`
|
||||
- `runtime.repo_capability_drift`
|
||||
- `runtime.runtime_may_need_restart`
|
||||
- `recommended_actions`
|
||||
|
||||
如果这里出现:
|
||||
|
||||
- `runtime.repo_capability_drift=true`
|
||||
- `runtime.runtime_may_need_restart=true`
|
||||
|
||||
则优先执行 `runtime-refresh-recover`,不要先把问题误判成“代码还没写完”。这通常表示:
|
||||
|
||||
- 仓库代码已经更新
|
||||
- 但运行中的 `domaincheck-api` 进程还没重启到这版代码
|
||||
|
||||
`runtime-refresh-recover` 会固定给出:
|
||||
|
||||
- 当前是否真的属于运行时版本漂移
|
||||
- 推荐先跑的 `runtime-refresh-recover` 统一恢复入口
|
||||
- 重启后应该按什么顺序继续:
|
||||
- `stack-diagnosis`
|
||||
- `node-bootstrap-plan`
|
||||
- `stack-next`
|
||||
- `doctor-decision`
|
||||
|
||||
如果你已经不想再手工一条条执行,而是想把“刷新运行时 + 再做总检复核”压成一次操作,直接执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover
|
||||
```
|
||||
|
||||
它会固定串起:
|
||||
|
||||
1. `runtime-refresh-recover`
|
||||
2. `stack-diagnosis summary`
|
||||
3. `stack-next`
|
||||
4. `go-live-check summary`
|
||||
5. `doctor-decision`
|
||||
|
||||
如果要把这次上线前检查直接导出成一整包证据,而不是手工复制多段终端输出,直接执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-export
|
||||
```
|
||||
|
||||
它会统一导出:
|
||||
|
||||
- `env-audit`
|
||||
- `go-live-check` 摘要
|
||||
- `go-live-summary`
|
||||
- `stack-diagnosis`
|
||||
- `driver-feed`
|
||||
- `codex-brief`
|
||||
- `release-launchpad`
|
||||
- `doctor-decision`
|
||||
- `doctor-export`
|
||||
- `manifest.json`
|
||||
|
||||
其中 `manifest.json` 会直接标记:
|
||||
|
||||
- 环境审计当前是 `ready / attention / blocked`
|
||||
- 哪些 artifact 成功
|
||||
- 哪些 artifact 超时
|
||||
- 哪些 endpoint 缺失或返回异常
|
||||
- 当前推荐的阅读顺序
|
||||
|
||||
现在 Ops Center 首屏也会同步读取最新 bundle / manifest:
|
||||
|
||||
- 顶部 `总检决策`
|
||||
- 详情区 `总检主决策详情`
|
||||
- API `GET /api/v1/ops/doctor-decision`
|
||||
- 顶部 `交付证据`
|
||||
- 详情区 `交付证据详情`
|
||||
- API `GET /api/v1/ops/go-live-bundle`
|
||||
- 顶部 `正式复核`
|
||||
- 详情区 `正式复核详情`
|
||||
- API `GET /api/v1/ops/go-live-review`
|
||||
|
||||
如果你想先拿到一句“bundle manifest 正式复核是否通过”的统一结论,而不是直接跳到最终签收,也可以先执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-review
|
||||
```
|
||||
|
||||
如果你想在 bundle 基础上直接得到一句“现在能不能签字上线”的统一结论,而不是人工再看多份 JSON,直接执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-signoff
|
||||
```
|
||||
|
||||
或基于已有 bundle:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-signoff /path/to/go-live-bundle
|
||||
```
|
||||
|
||||
这里的 `go-live-signoff` 已经不是另一套独立摘要,而是固定压缩:
|
||||
|
||||
- `go-live-review`
|
||||
- `doctor-decision`
|
||||
- `go-live-summary / 发布门禁 / launchpad 摘要`
|
||||
|
||||
所以页面首屏、CLI 与海外 Codex 看到的是同一份最终签字口径。
|
||||
|
||||
第一眼重点只看:
|
||||
|
||||
- `signoff_status`
|
||||
- `headline`
|
||||
- `release_gate`
|
||||
- `blocked_reasons`
|
||||
- `attention_reasons`
|
||||
- `decision`
|
||||
|
||||
### 第 2 步:看总检详情
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh stack-diagnosis
|
||||
```
|
||||
|
||||
重点只看:
|
||||
|
||||
- `stack_status`
|
||||
- `issues`
|
||||
- `next_step`
|
||||
- `quick_commands`
|
||||
|
||||
### 第 3 步:看驾驶主线
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh driver-feed
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh codex-brief
|
||||
```
|
||||
|
||||
重点只看:
|
||||
|
||||
- `top_recommendation`
|
||||
- `automation_coverage`
|
||||
- `recommended_behavior`
|
||||
- `focus`
|
||||
|
||||
### 第 4 步:确认默认下一步
|
||||
|
||||
如果只是预览:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh stack-next
|
||||
```
|
||||
|
||||
如果已经确认要执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh stack-next run confirm
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、当前项目的主处理车道
|
||||
|
||||
上线前遇到问题时,不要发散排查,先归到下面 5 条主车道:
|
||||
|
||||
### 1. 节点接管车道
|
||||
|
||||
典型信号:
|
||||
|
||||
- `remote_access_ready=0`
|
||||
- `bootstrap_run`
|
||||
- `run_acceptance`
|
||||
- `managed_nodes_agent_pending`
|
||||
|
||||
优先命令:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh agent-gap-check
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh agent-gap-recover
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-onboarding http://127.0.0.1:8100 mainland-worker-01
|
||||
```
|
||||
|
||||
### 2. 远端日志车道
|
||||
|
||||
典型信号:
|
||||
|
||||
- 首屏显示“现场日志覆盖不足”
|
||||
- `log_sync_enabled=false`
|
||||
- `line_count=0`
|
||||
- `source_nodes` 缺节点
|
||||
|
||||
优先命令:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh log-sync-check
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh log-sync-recover
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh scene-node-log http://127.0.0.1:8100 mainland-worker-01 120 key
|
||||
```
|
||||
|
||||
### 3. 总检修复车道
|
||||
|
||||
典型信号:
|
||||
|
||||
- `stack_status=blocked`
|
||||
- `surface_status=broken`
|
||||
- `contracts` / `launchpad` / `activity-stream` 缺口
|
||||
|
||||
优先命令:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/check_ops_center_stack.sh http://127.0.0.1:8100
|
||||
bash domain-api/deploy/multi-region/check_ops_contracts.sh http://127.0.0.1:8100
|
||||
bash domain-api/deploy/multi-region/check_release_hub.sh http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
### 4. 检测参与车道
|
||||
|
||||
典型信号:
|
||||
|
||||
- 页面显示在线节点多,但真正跑检测的少
|
||||
- `claimed_by` 分布异常
|
||||
- 在线但未参与节点过多
|
||||
|
||||
优先命令:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/check_worker_participation.sh
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh activity-stream
|
||||
```
|
||||
|
||||
### 5. 发布 / 放量车道
|
||||
|
||||
典型信号:
|
||||
|
||||
- `publish_ready=true`
|
||||
- `launchpad_status` 已可进入 Worker / Control rollout
|
||||
- 默认下一步已落在 Release Hub
|
||||
|
||||
优先命令:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh release-launchpad
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh codex-focus-preview
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、首屏通过标准
|
||||
|
||||
Ops Center 首屏如果要算“可上线收工”,至少应满足:
|
||||
|
||||
- 首屏能同时显示:
|
||||
- 上线收口状态
|
||||
- 发布闸门状态
|
||||
- 自动化收口状态
|
||||
- 主处理车道
|
||||
- 默认下一步
|
||||
- 后端接管覆盖
|
||||
- 观察层完整度
|
||||
- 现场日志覆盖度
|
||||
- 首屏动作条可直接完成:
|
||||
- 默认下一步
|
||||
- 定位下一步
|
||||
- 看契约
|
||||
- 复制命令
|
||||
- 进入主处理面板
|
||||
- 首屏回执条能统一反馈:
|
||||
- 打开契约成功
|
||||
- 定位成功
|
||||
- 复制成功
|
||||
- 后端动作执行成功 / 警告 / 失败
|
||||
|
||||
如果这些已经稳定,就说明值班同事和海外 Codex 已经在同一个驾驶台上工作,而不是各自再拼逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 七、通过标准后的最小上线动作
|
||||
|
||||
当上面门禁都通过后,建议最小上线动作顺序为:
|
||||
|
||||
1. 跑 `go-live-check`
|
||||
2. 看 `stack-diagnosis`
|
||||
3. 复核 `driver-feed.automation_coverage`
|
||||
4. 复核 `codex-brief.recommended_behavior`
|
||||
5. 若进入发布车道,先看 `release-launchpad`
|
||||
6. 对 `guarded_auto` 动作显式确认后再执行
|
||||
|
||||
上线前最后一轮建议保留证据:
|
||||
|
||||
- `go-live-summary` 输出
|
||||
- `stack-diagnosis` 输出
|
||||
- `driver-feed` 输出
|
||||
- `codex-brief` 输出
|
||||
- `release-launchpad` 输出
|
||||
- 前端构建成功记录
|
||||
|
||||
---
|
||||
|
||||
## 八、现在这套体系是否已经进入可上线状态
|
||||
|
||||
按当前仓库现状,可以认为已经具备:
|
||||
|
||||
- 单脑控制面的协议骨架
|
||||
- 首屏驾驶舱骨架
|
||||
- 总检与驾驶 contract
|
||||
- Release Hub / Driver / Node Agent 的联动骨架
|
||||
- 海外 CLI 单入口
|
||||
|
||||
但正式宣称“可以上线”,仍建议每次以这份总表复核,而不是只凭某一个页面截图或某一次联调成功就直接跳过。
|
||||
|
||||
这份文档的定位就是:
|
||||
|
||||
> 后续每次上线、值班接手、发布前复核,都先回到这里。
|
||||
|
||||
如果你已经准备进入“这次要不要真的发”的最终执行阶段,下一份应直接看:
|
||||
|
||||
- `docs/26_domainCheck_发布前运行验证与交付模板.md`
|
||||
635
docs/26_domainCheck_发布前运行验证与交付模板.md
Normal file
635
docs/26_domainCheck_发布前运行验证与交付模板.md
Normal file
@@ -0,0 +1,635 @@
|
||||
# 26 domainCheck 发布前运行验证与交付模板
|
||||
|
||||
## 一、这份模板怎么用
|
||||
|
||||
这份文档不是设计说明,而是正式发布前最后一轮执行模板。
|
||||
|
||||
适用场景:
|
||||
|
||||
- 海外单脑控制面已经搭好
|
||||
- 大陆节点已经接入或正在收口
|
||||
- 代码已经更新到待发布版本
|
||||
- 现在要做最后一轮运行验证、证据留存、交付确认
|
||||
|
||||
这份模板分成 3 段:
|
||||
|
||||
1. 发布前运行验证
|
||||
2. 上线证据导出
|
||||
3. 最终交付结论模板
|
||||
|
||||
---
|
||||
|
||||
## 二、发布前运行验证
|
||||
|
||||
### 1. 先跑统一收口摘要
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/getDomain
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-check http://127.0.0.1:8100 http://127.0.0.1:8100 summary
|
||||
```
|
||||
|
||||
记录结果:
|
||||
|
||||
- `go_live_status`
|
||||
- `publish_status`
|
||||
- `blocking_reasons`
|
||||
- `warnings`
|
||||
- `next_step_action_code`
|
||||
- `operator_title`
|
||||
- `launchpad_recommended_target_node_code`
|
||||
- `launchpad_recommended_recovery_label`
|
||||
- `launchpad_recommended_recovery_summary`
|
||||
- `launchpad_onboarding_bootstrap_pending_nodes`
|
||||
- `launchpad_onboarding_acceptance_ready_nodes`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `go_live_status != blocked`
|
||||
- `publish_status != blocked`
|
||||
|
||||
### 1.5 先看环境差异是否已收口
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh env-audit
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh runtime-refresh-recover
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover
|
||||
```
|
||||
|
||||
重点只看:
|
||||
|
||||
- `status`
|
||||
- `headline`
|
||||
- `python.pytest_installed / fastapi_installed / uvicorn_installed`
|
||||
- `python.runtimes`
|
||||
- `services`
|
||||
- `runtime.preflight_ok`
|
||||
- `runtime.readiness_status`
|
||||
- `runtime.route_surface_complete`
|
||||
- `missing_items`
|
||||
- `tooling_items`
|
||||
|
||||
通过标准建议:
|
||||
|
||||
- `status != blocked`
|
||||
- `runtime.preflight_ok=true`
|
||||
- `route_surface_complete=true`
|
||||
- 如果 `missing_items` 里仍有关键基础项,先补环境,再继续业务复核
|
||||
- 如果只有 `tooling_items`,可以继续上线复核,但建议后补本机工具链
|
||||
- 如果 `runtime.runtime_may_need_restart=true`
|
||||
- 不要直接继续接管或发布链
|
||||
- 先按 `runtime-refresh-recover` 给出的固定顺序完成 API 重启与复检
|
||||
- 如果你希望把这一轮“重启 + 总检 + 默认下一步 + 上线摘要”压成一次复核
|
||||
- 直接执行 `go-live-recover`
|
||||
|
||||
### 1.6 先看托管节点接入面是否清楚
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh nodes http://127.0.0.1:8100
|
||||
```
|
||||
|
||||
重点只看:
|
||||
|
||||
- `summary.agent_ready`
|
||||
- `summary.ssh_ready`
|
||||
- `summary.remote_access_ready`
|
||||
- `summary.remote_access_state_counts`
|
||||
- 每台节点的 `agent_state`
|
||||
- 每台节点的 `remote_access_state`
|
||||
- 每台节点的 `ssh_access_label`
|
||||
- 每台节点的 `ssh_entry`
|
||||
|
||||
通过标准建议:
|
||||
|
||||
- 如果某台节点还是 `agent_pending`
|
||||
- 先确认是否已经保存 SSH 入口
|
||||
- 如果节点尚未保存 SSH 入口,但你已经决定由海外控制面统一接管
|
||||
- 先补录:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-bind-ssh http://127.0.0.1:8100 mainland-worker-01 121.204.244.248 root 22
|
||||
```
|
||||
|
||||
- 补录后立即复查:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh nodes http://127.0.0.1:8100
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-handover http://127.0.0.1:8100 mainland-worker-01
|
||||
```
|
||||
|
||||
- 如果已经 `agent_ready`
|
||||
- 说明该节点已进入标准远端执行器接管面
|
||||
- 如果还不是 `agent_ready`,但 `ssh_ready` 已经成立
|
||||
- 说明至少已经具备海外主控经 SSH 进入节点完成 bootstrap / 验收的前置条件
|
||||
|
||||
### 2. 再看总检详情
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh stack-diagnosis
|
||||
```
|
||||
|
||||
记录结果:
|
||||
|
||||
- `stack_status`
|
||||
- `issues`
|
||||
- `next_step`
|
||||
- `quick_commands`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `stack_status != blocked`
|
||||
- `issues` 里没有未处理的关键阻断项
|
||||
|
||||
### 3. 再看驾驶主线
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh driver-feed
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh codex-brief
|
||||
```
|
||||
|
||||
记录结果:
|
||||
|
||||
- `top_recommendation`
|
||||
- `automation_coverage`
|
||||
- `recommended_behavior`
|
||||
- `focus`
|
||||
- `summary.launchpad_recommended_target_node_code`
|
||||
- `summary.launchpad_recommended_recovery_label`
|
||||
- `summary.launchpad_onboarding_bootstrap_pending_nodes`
|
||||
- `summary.launchpad_onboarding_acceptance_ready_nodes`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `automation_coverage.launch_status != blocked`
|
||||
- 默认下一步已经明确
|
||||
- 如果 `summary.launchpad_recommended_target_node_code` 非空
|
||||
- 值班同事应能直接知道当前卡在哪台节点
|
||||
- 不需要再回 launchpad 明细手工翻 gap rows
|
||||
|
||||
### 4. 若涉及发布,再看 Release Hub
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh release-launchpad
|
||||
```
|
||||
|
||||
记录结果:
|
||||
|
||||
- `launchpad_status`
|
||||
- `recommended_action_code`
|
||||
- `default_rollout_gate_status`
|
||||
- `recommended_target_node_code`
|
||||
- `recommended_recovery_label`
|
||||
- `recommended_recovery_summary`
|
||||
- `onboarding_bootstrap_pending_nodes`
|
||||
- `onboarding_acceptance_ready_nodes`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `launchpad_status != blocked`
|
||||
- `default_rollout_gate_status != blocked`
|
||||
|
||||
特殊判读:
|
||||
|
||||
- 如果 `recommended_action_code=api-restart`
|
||||
- 不要误判成“节点没接好”
|
||||
- 这更像是运行中的控制面 API 还没刷新到当前仓库的最新运维能力
|
||||
- 应先执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh runtime-refresh-recover
|
||||
```
|
||||
|
||||
- 然后重新跑:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh stack-diagnosis
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh release-launchpad
|
||||
```
|
||||
|
||||
补充说明:
|
||||
|
||||
- 从 `latest_release.json` 直接创建 Release,或执行“基于最新包的一键智能 Rollout”之前
|
||||
- 现在不仅要求 `smoke_test_ok=true`
|
||||
- 还要求当前 `final_release_report.json` 与最新包完全匹配,且 `final_release_ok=true`
|
||||
- 如果页面按钮被禁用,或 API 返回“最新发布包尚未完成最终签收”
|
||||
- 优先检查 `final_release_report_stale_reason`
|
||||
- 再检查 `final_release_gate_decision / final_release_gate_blocked_reasons`
|
||||
|
||||
### 5. 若涉及节点接管,补跑节点验收
|
||||
|
||||
如果这次发布包含:
|
||||
|
||||
- 新增大陆节点
|
||||
- 重新接管旧节点
|
||||
- 切换到 Node Agent 主接管模式
|
||||
|
||||
则不能只看总检摘要,还要对目标节点逐台完成验收。
|
||||
|
||||
先看验收计划:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-acceptance-plan http://127.0.0.1:8100 mainland-worker-01
|
||||
```
|
||||
|
||||
确认无误后执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-acceptance-run http://127.0.0.1:8100 mainland-worker-01 cli/acceptance
|
||||
```
|
||||
|
||||
记录结果:
|
||||
|
||||
- `node_code`
|
||||
- `status`
|
||||
- `checks`
|
||||
- `blocking_issues`
|
||||
- `warnings`
|
||||
- `recommended_next_step`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `status != blocked`
|
||||
- 没有未处理的 `blocking_issues`
|
||||
- 目标节点已经不再停留在“bootstrap pending / acceptance pending”
|
||||
|
||||
### 6. 若涉及远端执行,补跑日志回传验证
|
||||
|
||||
如果当前版本准备进入:
|
||||
|
||||
- 多机值班
|
||||
- 海外单脑统一接管
|
||||
- 远端动作回执与现场日志复核
|
||||
|
||||
则需要确认日志回传链已经可用,而不是只看节点在线。
|
||||
|
||||
先检查:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh log-sync-check
|
||||
```
|
||||
|
||||
如果存在缺口,再执行恢复:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh log-sync-recover http://127.0.0.1:8100 key confirm cli/log-sync
|
||||
```
|
||||
|
||||
必要时抓一份节点现场日志:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh scene-node-log http://127.0.0.1:8100 mainland-worker-01 120 full
|
||||
```
|
||||
|
||||
记录结果:
|
||||
|
||||
- `log_sync_enabled`
|
||||
- `line_count`
|
||||
- `source_nodes`
|
||||
- `missing_nodes`
|
||||
- `scene_log.status`
|
||||
|
||||
通过标准:
|
||||
|
||||
- 关键节点已出现在 `source_nodes`
|
||||
- `missing_nodes` 不包含当前发布主车道节点
|
||||
- 如需人工复核现场,`scene-node-log` 能取到有效日志
|
||||
|
||||
### 7. 若涉及 Node Agent 交付,补看队列健康
|
||||
|
||||
如果这轮发布已经进入“控制面发动作、节点拉任务、节点回执结果”的模式,就必须确认 delivery queue 没有假健康。
|
||||
|
||||
先看队列摘要:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-status http://127.0.0.1:8100 mainland-worker-01
|
||||
```
|
||||
|
||||
如果怀疑有堆积或死信,再看明细:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-records http://127.0.0.1:8100 mainland-worker-01 dead_letter
|
||||
```
|
||||
|
||||
如需重放:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-replay http://127.0.0.1:8100 mainland-worker-01 20 cli/queue-replay
|
||||
```
|
||||
|
||||
记录结果:
|
||||
|
||||
- `delivery_queue.summary`
|
||||
- `dead_letter`
|
||||
- `retrying`
|
||||
- `pending`
|
||||
- `replayed_count`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `dead_letter=0`
|
||||
- 没有持续增长的 `retrying`
|
||||
- 队列不处于异常堆积状态
|
||||
|
||||
注意:
|
||||
|
||||
- `dead_letter > 0` 时,不应宣称“可正式发布”
|
||||
- 这种情况至少按 `publish_status = blocked` 处理
|
||||
|
||||
### 8. 最后跑一次 doctor 结论
|
||||
|
||||
前面的检查是分面复核,最后还要再收成一句话,让交班、值班、Codex 驾驶员看到同一结论。
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-decision
|
||||
```
|
||||
|
||||
记录结果:
|
||||
|
||||
- `status`
|
||||
- `decision`
|
||||
- `recommended_commands`
|
||||
- `recommended_reading_order`
|
||||
- `launchpad_alignment`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `status != blocked`
|
||||
- `decision` 与前面的 `go-live-check / stack-diagnosis / release-launchpad` 不冲突
|
||||
- `recommended_commands` 已经指向明确的下一跳,而不是泛化排查
|
||||
|
||||
### 9. 若希望直接生成“可否签字上线”的最终摘要
|
||||
|
||||
如果你不想手工再拼:
|
||||
|
||||
- bundle review
|
||||
- doctor 结论
|
||||
- 发布门禁
|
||||
|
||||
可以直接执行:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-signoff
|
||||
```
|
||||
|
||||
如果已经有现成证据包,也可以直接基于 manifest 输出:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-signoff /path/to/go-live-bundle
|
||||
```
|
||||
|
||||
这一步现在不是“另一套单独判断”,而是固定复用:
|
||||
|
||||
- `go-live-review`
|
||||
- `doctor-decision`
|
||||
- `go-live-summary / 发布门禁 / launchpad 摘要`
|
||||
|
||||
也就是说,页面首屏、CLI 和海外 Codex 看到的最终签收结论,已经开始共享同一份签字口径。
|
||||
|
||||
重点只看:
|
||||
|
||||
- `signoff_status`
|
||||
- `headline`
|
||||
- `release_gate`
|
||||
- `blocked_reasons`
|
||||
- `attention_reasons`
|
||||
- `decision`
|
||||
- `recommended_commands`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `signoff_status=ready`
|
||||
- 可进入最终人工签字或正式发布
|
||||
- `signoff_status=attention`
|
||||
- 说明现场已经接近完成,但仍应先清 attention 项
|
||||
- `signoff_status=blocked`
|
||||
- 本轮不应宣称收口完成
|
||||
|
||||
---
|
||||
|
||||
## 三、上线证据导出
|
||||
|
||||
### 1. 导出 bundle
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-export
|
||||
```
|
||||
|
||||
这会生成一整包上线前证据。
|
||||
|
||||
建议至少保留:
|
||||
|
||||
- `00_env_audit.txt`
|
||||
- `01_go_live_check_summary.txt`
|
||||
- `02_go_live_summary.json`
|
||||
- `03_stack_diagnosis.json`
|
||||
- `04_driver_feed.json`
|
||||
- `05_codex_brief.json`
|
||||
- `06_release_launchpad.json`
|
||||
- `manifest.json`
|
||||
|
||||
如果当前轮次涉及节点接管,建议额外保留:
|
||||
|
||||
- `agent_gap_export.json`
|
||||
- `node_bootstrap_plan.txt`
|
||||
- `node_acceptance_plan.json`
|
||||
|
||||
如果当前轮次涉及远端执行与日志回传,建议额外保留:
|
||||
|
||||
- `scene_log_*.txt`
|
||||
- `doctor_decision.json`
|
||||
|
||||
### 2. 直接复核 bundle
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-review
|
||||
```
|
||||
|
||||
如果你已经切到 Ops Center 页面,也可以直接看:
|
||||
|
||||
- 首屏 `总检决策`
|
||||
- `总检主决策详情`
|
||||
- API `GET /api/v1/ops/doctor-decision`
|
||||
- 首屏 `交付证据`
|
||||
- `交付证据详情`
|
||||
- API `GET /api/v1/ops/go-live-bundle`
|
||||
- 首屏 `正式复核`
|
||||
- `正式复核详情`
|
||||
- API `GET /api/v1/ops/go-live-review`
|
||||
|
||||
记录结果:
|
||||
|
||||
- `status`
|
||||
- `headline`
|
||||
- `critical_failures`
|
||||
- `noncritical_failures`
|
||||
- `launchpad_alignment.consistent`
|
||||
- `env_audit.status`
|
||||
- `env_audit.missing_items`
|
||||
- `recommended_next_steps`
|
||||
|
||||
通过标准建议:
|
||||
|
||||
- `status=ready`
|
||||
- 可进入最终人工确认或正式发布
|
||||
- `status=attention`
|
||||
- 核心报告已齐,但仍需复核补充失败项或环境缺口
|
||||
- 也包括 `go_live_summary / stack_diagnosis / driver_feed / codex_brief` 的 launchpad 摘要出现不一致
|
||||
- `status=blocked`
|
||||
- 关键报告缺失,或环境审计已经判定阻断,不应直接宣称收口完成
|
||||
|
||||
如果 `env_audit.missing_items` 里出现:
|
||||
|
||||
- `missing_env:/etc/default/domaincheck-node-agent`
|
||||
|
||||
则这次 bundle review 已经不是泛泛地提示“环境缺口”,而是明确指向 Node Agent 接管还未收口。此时按下面顺序推进:
|
||||
|
||||
1. `agent-gap-export`
|
||||
2. `node-bootstrap-plan`
|
||||
3. 如果 summary 已提示 `runtime_may_need_restart=true`
|
||||
4. 完成恢复后重新导出 bundle,再做一次 `go-live-review`
|
||||
|
||||
### 3. 生成最终交付包
|
||||
|
||||
运行验证、bundle 复核都通过后,再生成最终交付包。
|
||||
|
||||
如果当前机器已经具备 smoke 运行条件,直接执行:
|
||||
|
||||
```bash
|
||||
bash ./prepare_final_release.sh
|
||||
```
|
||||
|
||||
如果当前机器只适合先做离线打包,可先跳过 smoke:
|
||||
|
||||
```bash
|
||||
DOMAINCHECK_SKIP_SMOKE_TEST=1 bash ./package_domain_release.sh
|
||||
bash ./verify_domain_release.sh
|
||||
```
|
||||
|
||||
后续再回到具备运行条件的机器上执行:
|
||||
|
||||
```bash
|
||||
bash ./prepare_final_release.sh
|
||||
```
|
||||
|
||||
最后统一查看最新交付结果:
|
||||
|
||||
```bash
|
||||
bash ./show_latest_release.sh
|
||||
```
|
||||
|
||||
重点只看:
|
||||
|
||||
- `latest_release.package_name`
|
||||
- `latest_release.archive_path`
|
||||
- `latest_release.sha256`
|
||||
- `latest_release.smoke_test_ok`
|
||||
- `final_release_ok`
|
||||
- `final_release_report`
|
||||
- `final_release_report_ok`
|
||||
- `final_release_report_matches_latest`
|
||||
- `final_release_report_stale_reason`
|
||||
- `final_release_gate_decision`
|
||||
- `final_release_gate_blocked_reasons`
|
||||
- `final_release_gate_verify_ok`
|
||||
- `final_release_gate_smoke_test_ok`
|
||||
|
||||
通过标准:
|
||||
|
||||
- `verify_domain_release.sh` 返回 `ok=true`
|
||||
- `latest_release.smoke_test_ok=true`
|
||||
- `final_release_ok=true`
|
||||
- `final_release_report_matches_latest=true`
|
||||
- `final_release_gate_decision=ready`
|
||||
- `final_release_gate_verify_ok=true`
|
||||
- `final_release_gate_smoke_test_ok=true`
|
||||
- `final_release_report` 已指向最新一轮生成的正式报告
|
||||
4. 先执行 `runtime-refresh-recover`
|
||||
5. 再重新导出 bootstrap plan
|
||||
|
||||
---
|
||||
|
||||
## 四、最终交付结论模板
|
||||
|
||||
下面这段可以直接作为正式发布前的交付结论模板使用。
|
||||
|
||||
### 模板正文
|
||||
|
||||
```text
|
||||
本轮发布前运行验证已完成。
|
||||
|
||||
一、统一收口结论
|
||||
- go_live_status: <填写>
|
||||
- publish_status: <填写>
|
||||
- stack_status: <填写>
|
||||
- automation_coverage.launch_status: <填写>
|
||||
- launchpad_status: <填写>
|
||||
|
||||
二、默认下一步
|
||||
- next_step_action_code: <填写>
|
||||
- operator_title: <填写>
|
||||
- launchpad_recommended_target_node_code: <填写>
|
||||
- launchpad_recommended_recovery_label: <填写>
|
||||
|
||||
三、上线证据包
|
||||
- bundle 路径: <填写>
|
||||
- manifest 复核状态: <填写 ready/attention/blocked>
|
||||
- go-live-review.headline: <填写>
|
||||
- manifest.review_status_hint: <填写>
|
||||
- critical_failures: <填写>
|
||||
- noncritical_failures: <填写>
|
||||
- manifest.launchpad_recommended_target_node_code: <填写>
|
||||
- manifest.launchpad_recommended_recovery_label: <填写>
|
||||
- manifest.launchpad_onboarding_bootstrap_pending_nodes: <填写>
|
||||
- manifest.launchpad_onboarding_acceptance_ready_nodes: <填写>
|
||||
- manifest.launchpad_alignment.consistent: <填写 true/false>
|
||||
|
||||
四、结论
|
||||
- <填写:可进入正式发布 / 仍需继续收口 / 暂不可发布>
|
||||
```
|
||||
|
||||
### 模板补充说明
|
||||
|
||||
填写“可进入正式发布”前,建议再做一次人工交叉确认:
|
||||
|
||||
- 发布门禁是否为 `ready` 或至少非 `blocked`
|
||||
- 当前主车道是否已经明确
|
||||
- 是否还存在 `dead_letter`
|
||||
- 是否还有节点停留在 `bootstrap pending / acceptance pending`
|
||||
- 是否已经保留可复盘的证据包与 manifest
|
||||
|
||||
---
|
||||
|
||||
## 五、交付给值班同事时最少要带什么
|
||||
|
||||
最少带下面 4 样:
|
||||
|
||||
1. `go-live-check` 摘要
|
||||
2. `stack-diagnosis` 结果
|
||||
3. `driver-feed / codex-brief` 结果
|
||||
4. `go-live-export` 生成的 `manifest.json`
|
||||
|
||||
如果值班同事需要直接接手节点问题,再多带 3 样:
|
||||
|
||||
1. `node-acceptance-run` 最近结果
|
||||
2. `log-sync-check` 最近结果
|
||||
3. `queue-status` 或 `queue-records dead_letter` 最近结果
|
||||
|
||||
这样交班的人不需要重新从零拼现场。
|
||||
|
||||
---
|
||||
|
||||
## 六、真正的收工标准
|
||||
|
||||
如果要算“这次版本已经可以收工”,建议至少同时满足:
|
||||
|
||||
- 前端构建成功
|
||||
- 海外单脑驾驶舱首屏状态正常
|
||||
- `go-live-review.status != blocked`
|
||||
- 发布门禁不为 `blocked`
|
||||
- Node Agent 目标节点已完成接管验收
|
||||
- 远端日志回传链可用或已确认本轮不依赖
|
||||
- delivery queue 不存在未处理 `dead_letter`
|
||||
- 当前默认下一步已经不是“继续补基础设施”,而是进入正式发布 / 观察 / 验收车道
|
||||
|
||||
到这一步,才适合说:
|
||||
|
||||
> 当前项目已经进入可上线、可交付、可持续运维状态。
|
||||
287
docs/base.md
Normal file
287
docs/base.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# 主线任务验收总表
|
||||
|
||||
更新时间:2026-04-21
|
||||
|
||||
## 当前执行原则
|
||||
|
||||
当前先只做一件事:
|
||||
|
||||
- 跑通主任务流程
|
||||
- 把 7 个大任务按“可测试、可验收”的标准推进
|
||||
- 并发、代理、展示层、CPU 打满这类细节优化先封存,不再抢主线
|
||||
|
||||
当前不再把“性能抠点”当主目标。
|
||||
后续额度恢复后,再继续做细节优化专项。
|
||||
|
||||
## 当前主线优先级
|
||||
|
||||
按下面顺序推进,不跳步:
|
||||
|
||||
1. 大任务 1 真实验收闭环
|
||||
2. 大任务 2 controller 编排闭环
|
||||
3. 大任务 3 统一结果状态机闭环
|
||||
4. 大任务 4 本地控制状态 + syncer/finalizer 闭环
|
||||
5. 大任务 5 固定 worker pool + 持续补位替换旧模型
|
||||
6. 大任务 6 时光机一期接入标准步骤
|
||||
7. 大任务 7 运营视角指标面板落地
|
||||
|
||||
## 7 个大任务当前状态
|
||||
|
||||
### 大任务 1
|
||||
单步骤任务底座落地
|
||||
|
||||
目标:
|
||||
先打通 `controller -> queue -> claim -> worker -> result -> controller` 的完整闭环。
|
||||
|
||||
当前状态:
|
||||
- 已有较完整代码底座
|
||||
- `single_step` / `step_code` 模型已基本成形
|
||||
- 现在缺的是“真实运行验收”而不是继续堆骨架
|
||||
|
||||
本任务验收只认下面 5 件事:
|
||||
|
||||
1. controller 能生成 `baidu_check` 任务
|
||||
2. worker 能拉到 `baidu_check` 任务并执行
|
||||
3. worker 能回传标准化结果
|
||||
4. controller 能更新本地步骤状态
|
||||
5. worker 超时未回传时,任务会回收重投
|
||||
|
||||
当前结论:
|
||||
- 代码方向已基本对齐
|
||||
- 2026-04-20 已完成一轮 live 验收打钩:
|
||||
- `controller` 已生成 `single_step / detect_baidu_site` 任务(例:`job_id=6`, `job_code=step-20260420153527-9fc7b5`)
|
||||
- `worker` 已精准领取当前 `job_id` 并执行,不再被旧 `pipeline / sync / legacy fallback` 污染
|
||||
- `worker` 已回传标准化结果到 `detect_job_items.result_payload_json`
|
||||
- `controller` 已可按 `job_id` 定向执行 `process_pipeline`,并把结果落到本地 `domain_detections.baidu_site`
|
||||
- “超时/遗留未回传”链路已验证会被节点启动释放并重新领取执行(`job_id=5` 在遗留 `running` 后被重新释放、重新领取并完成)
|
||||
- 当前主线结论:大任务 1 已达到“可验收通过”状态,可以继续把主精力切到大任务 2 / 3
|
||||
|
||||
### 大任务 2
|
||||
pipeline 编排器落地
|
||||
|
||||
目标:
|
||||
把“下一步跑什么”彻底收回 controller。
|
||||
|
||||
当前状态:
|
||||
- 基础方向已落到 controller 驱动
|
||||
- 还需要继续做“按后台勾选顺序推进 / 按域名属性跳过”的真实验收
|
||||
|
||||
本任务必须确认:
|
||||
- 同一个域名不会在 worker 里串完整条链
|
||||
- controller 是唯一推进者
|
||||
- 勾选顺序变化能影响下一步投递
|
||||
- 跳过规则生效
|
||||
|
||||
当前结论:
|
||||
- 已进入可验收阶段
|
||||
- 2026-04-20 已补上关键收口:
|
||||
- `single_step` 会话下,worker 只按当前 `job_id` 领取任务
|
||||
- `single_step` 会话下,旧的 `pipeline 推进 / sync pull / legacy fallback` 已被显式跳过
|
||||
- `process_pipeline` 已支持按 `job_id` 定向处理,方便 controller 精准推进当前步骤
|
||||
- 2026-04-20 又补完一轮 live 验收:
|
||||
- `pass`:`detect_baidu_site` 完成后,controller 已为同一 `job` 创建下一步 `detect_360_site`
|
||||
- `skip`:一口价域名在 `detect_register + detect_baidu_site` 配置下,会直接解析到 `detect_baidu_site`
|
||||
- 同时修掉了一个真实阻塞点:`process_pipeline()` 事务内再开第二连接写 `detect_run_events` 会把 controller 自己锁住;现已改成同事务同 cursor 写事件
|
||||
- 当前主线结论:大任务 2 的 controller 编排主干已可验收,剩下更多是扩步骤和补更细跳过规则
|
||||
|
||||
### 大任务 3
|
||||
步骤结果判定与重试策略落地
|
||||
|
||||
目标:
|
||||
统一 `pass / retry / black_hit / reject`。
|
||||
|
||||
当前状态:
|
||||
- 结果结构、重试入口、黑名单终止方向已基本进入主链
|
||||
- 还需要补 live 验收,重点是 TTL 回收、重投、终止规则
|
||||
|
||||
本任务必须确认:
|
||||
- 外部失败会重投当前步骤
|
||||
- 黑名单命中会终止后续步骤
|
||||
- 非黑名单业务不通过按规则终止
|
||||
- 不会出现同一步无限重试
|
||||
|
||||
当前结论:
|
||||
- 代码已明显推进
|
||||
- 2026-04-20 已完成 controller 侧 live 验收:
|
||||
- `retry`:`state=degraded` 会重投当前步骤,不推进下一步
|
||||
- `black_hit`:`state=blacklisted` 会终止后续步骤并结束当前 job
|
||||
- `reject`:`state=rejected` 会终止当前流程,不再重试
|
||||
- worker 侧也已补上业务失败 -> `rejected` 的结果态,不再把业务不通过和技术失败都混成 `failed`
|
||||
- 当前主线结论:大任务 3 的统一结果状态机已基本闭环,可继续往大任务 4 / 5 推进
|
||||
|
||||
### 大任务 4
|
||||
本地控制状态与海外主库同步落地
|
||||
|
||||
目标:
|
||||
controller 本地维护高频状态,syncer 批量同步海外主库,finalizer 标记流程完成。
|
||||
|
||||
当前状态:
|
||||
- 本地状态和部分同步链路已经在跑
|
||||
- 已补上“最近完成任务快照也继续产出结果投影”
|
||||
- 已补上结果导入后按 job_code 优先定位本地 job,并刷新本地 job 收尾状态
|
||||
- syncer/finalizer 还缺少一轮 live 闭环验收
|
||||
|
||||
本任务必须确认:
|
||||
- 高频链路不依赖 worker 频繁直写海外主库
|
||||
- controller 本地状态完整
|
||||
- 批量同步成功
|
||||
- 流程完成状态准确
|
||||
|
||||
当前结论:
|
||||
- 代码主链已进一步收口
|
||||
- 2026-04-21 已确认 `detect_result_projection / runtime_projection` 在 `detect_sync_records` 中持续产出且状态为 `projected`
|
||||
- 当前说明 syncer 主链已恢复,但“本地 job 收尾状态 + 主库最终账本完全一致”的终验还需要继续盯现场
|
||||
|
||||
### 大任务 5
|
||||
worker 池化与持续补位调度落地
|
||||
|
||||
目标:
|
||||
真正替掉“批量认领 + 批量等待”的旧模型。
|
||||
|
||||
当前状态:
|
||||
- 已经做了多轮并发热路径优化
|
||||
- 已进一步压缩 executor 内部 backlog,补位更接近固定槽位模型
|
||||
- 但还需要一轮 live 运行观察 claimed/running 曲线,确认旧的批量认领惯性已被压住
|
||||
|
||||
本任务必须确认:
|
||||
- 活跃槽位稳定贴近配置上限
|
||||
- 并发不再大起大落
|
||||
- 吞吐明显提升
|
||||
- 调度器自耗下降
|
||||
|
||||
当前结论:
|
||||
- 这是主线里仍然偏重的未完项
|
||||
- 2026-04-21 已继续做现场修正:
|
||||
- `claim_detect_job_items()` 已显式排除空 `step_code` 的 legacy 项,避免 worker 从标准队列入口继续误吞旧 whole-domain 项
|
||||
- `mainland-controller-01 / 121.204.244.188` 与 `mainland-worker-01 / 121.204.244.248` 均已确认在真大陆节点参与执行
|
||||
- 海外控制面 `queue_health / dashboard` 已补上“读取大陆 runtime/debug 近窗执行流”的兜底口径
|
||||
- 当前首页已能看到真实近窗吞吐,例如 `10-15 项/分钟` 量级、并能拆到 controller/worker 两个节点
|
||||
- 当前主线判断:
|
||||
- “高 claimed 假活跃”问题已继续缓解
|
||||
- “活吞吐不可见”问题已明显改善
|
||||
- 但“总 completed 账本持续增长”和“running 贴近线程上限”仍未彻底验收,所以大任务 5 仍未签字通过
|
||||
|
||||
### 大任务 6
|
||||
时光机一期流程落地
|
||||
|
||||
目标:
|
||||
时光机按“最近 5 年”方案接成标准步骤任务。
|
||||
|
||||
当前状态:
|
||||
- 现有项目里已有时光机相关检测逻辑
|
||||
- 但还没有完全按标准步骤任务方式接进新 pipeline 验收
|
||||
|
||||
本任务必须确认:
|
||||
- wayback 作为标准步骤任务接入
|
||||
- 最近 5 年快照策略稳定
|
||||
- 返回标准化结果
|
||||
- controller 能把它当普通步骤推进/终止
|
||||
|
||||
当前结论:
|
||||
- 2026-04-21 已落代码并通过测试:
|
||||
- `detect_wayback` 已作为标准 `single_step` 步骤接入 controller / worker 主链
|
||||
- 时光机一期已按“最近 5 年 + 命中即停”策略落地到 payload 和 detector
|
||||
- 焦点测试已通过
|
||||
- 但还缺 live 现场验收:
|
||||
- 真实任务投递
|
||||
- worker 执行
|
||||
- 标准化结果回传
|
||||
- controller 按普通步骤推进/终止
|
||||
- 当前主线结论:大任务 6 已进入“代码落地完成、待现场验收”状态
|
||||
|
||||
### 大任务 7
|
||||
运营视角指标与验收面板落地
|
||||
|
||||
目标:
|
||||
让后台能判断“有没有跑起来、卡在哪一步、多久跑完”。
|
||||
|
||||
当前状态:
|
||||
- 后端已有部分 runtime / detect status / debug event 统计基础
|
||||
- 但完整的运营视角指标面板还没有完全落地验收
|
||||
|
||||
本任务必须确认:
|
||||
- 每步骤队列数
|
||||
- 每步骤吞吐
|
||||
- 每分钟完成量
|
||||
- 当前 pipeline 分布
|
||||
- 重试数 / 黑名单数 / 失败数
|
||||
- 预估剩余时间
|
||||
|
||||
当前结论:
|
||||
- 2026-04-21 已落地首页最小运营面板,并补了第二层口径修正:
|
||||
- `completed / pending / running` 已切到“全活跃任务累计口径”
|
||||
- `步骤队列 / 节点吞吐 / 重试压力 / 有效执行节点` 已可直接展示
|
||||
- `ETA` 在无真实近窗完成量时会显示“待计算”,避免误报 0 小时
|
||||
- 2026-04-21 又补上“大陆 runtime/debug 近窗执行流”兜底:
|
||||
- `active_job` 已可显示 `runtime_job_code`
|
||||
- `processed_per_minute / completed_recent / node_throughput / step_queue` 已能贴近大陆真实执行
|
||||
- 首页已能直接区分 `db_job_code` 与 `runtime_job_code`
|
||||
- 当前结论:大任务 7 已进入“可运营分析并能指导现场排障”阶段,但仍需继续把“总 completed 账本”和“最终验收面板”完全统一
|
||||
|
||||
## 现在只做什么
|
||||
|
||||
当前只盯主线,不跑偏:
|
||||
|
||||
1. 把大任务 1 做成可真实验收
|
||||
2. 验收过后立刻推进大任务 2
|
||||
3. 再按顺序推进 3、4、5、6、7
|
||||
|
||||
如果某个问题只是:
|
||||
|
||||
- CPU 没吃满
|
||||
- 某个 timeout 还能再抠
|
||||
- 代理池还能更激进
|
||||
- 页面还能再改得更好看
|
||||
|
||||
都先不打断主线。
|
||||
|
||||
## 已封存的细节优化 backlog
|
||||
|
||||
下面这些不是不做,而是先封存:
|
||||
|
||||
### A. 并发/调度优化
|
||||
|
||||
- 固定 worker pool 彻底替换旧批量认领模型
|
||||
- claimed 回弹继续压缩
|
||||
- executor 内部排队继续收紧
|
||||
- 活跃 running 继续往上抬
|
||||
- controller / worker 双节点吞吐平衡
|
||||
|
||||
### B. DB 往返优化
|
||||
|
||||
- 继续合并 `domains` 表高频更新
|
||||
- 继续减少 `mark_running / finalize` 这类必要写库点开销
|
||||
- 能走 Redis 或本地状态的尽量不走高频 DB
|
||||
|
||||
### C. 外部请求链路优化
|
||||
|
||||
- 代理失败后的重试链继续压缩
|
||||
- 直连失败后回代理的等待窗口再收紧
|
||||
- 无代理窗口等待策略再优化
|
||||
- 外部请求 timeout 再按真实成功率调优
|
||||
|
||||
### D. 代理池策略优化
|
||||
|
||||
- 代理池刷新频率与补位策略继续增强
|
||||
- 失败代理淘汰与新代理拉取节奏继续优化
|
||||
- 控制“不过度预验证”和“不过度浪费线程”之间的平衡
|
||||
|
||||
### E. 运营展示层优化
|
||||
|
||||
- 更细的 runtime 面板
|
||||
- ETA / 每分钟吞吐更精细展示
|
||||
- 日志窗口布局继续优化
|
||||
- 非主线的页面交互增强
|
||||
|
||||
## 接下来执行口径
|
||||
|
||||
接下来统一按这个口径推进:
|
||||
|
||||
- 先验收主流程
|
||||
- 再补主流程缺口
|
||||
- 性能细节先记账,不抢主线
|
||||
- 每做完一个大任务,就给出“是否验收通过”的明确结论
|
||||
|
||||
一句话定调:
|
||||
|
||||
当前阶段不是“继续无限抠并发”,而是“先把 7 个大任务按主线流程逐个打通并验收”。
|
||||
49
docs/codex接手.md
Normal file
49
docs/codex接手.md
Normal file
@@ -0,0 +1,49 @@
|
||||
把下面这段直接发给新的 Codex 就行:
|
||||
|
||||
```text
|
||||
接手这个项目,请先不要发散,也不要先动展示层。你先完整阅读并基于现状继续推进主线。
|
||||
|
||||
项目路径:
|
||||
`/www/wwwroot/getDomain`
|
||||
|
||||
必须先看这几份文档:
|
||||
1. `docs/ops_center_runtime/HANDOFF_20260420_1920.md`
|
||||
2. `docs/base.md`
|
||||
3. `docs/test.md`
|
||||
|
||||
这次接手的硬性要求:
|
||||
1. 先以 `docs/ops_center_runtime/HANDOFF_20260420_1920.md` 为准建立上下文。
|
||||
2. 不要把当前这台机器当成真正的 mainland controller。
|
||||
3. 当前工作机是海外 12 核测试控制面,真正的 `mainland-controller-01` 是 `121.204.244.188`。
|
||||
4. 不要再优先动页面、展示层、面板文案。
|
||||
5. 不要用破坏性 git 命令,不要回滚现有脏工作区改动。
|
||||
6. 新增或修改代码前,先确认你改的是主线瓶颈,而不是辅助功能。
|
||||
|
||||
当前已经确认的事实:
|
||||
1. 真正的 `mainland-controller-01` 已重新对正。
|
||||
2. controller 的 node-agent 身份上报已经修好,现在控制面里应显示:
|
||||
- `agent_hostname = mainland-controller-01`
|
||||
- `agent_ip = 121.204.244.188`
|
||||
3. controller 远端发布链已经成功跑通过一次。
|
||||
4. 当前真正吃任务的是 `mainland-controller-01`。
|
||||
5. `mainland-worker-01` 目前是 agent 在线,但检测没有真正参与,现象是本地检测态里出现 `127.0.0.1:5432 connection refused`。
|
||||
6. 当前主线已经不是“节点身份问题”,而是“真 controller 吞吐”和“worker 恢复”。
|
||||
|
||||
你接手后只做两条主线:
|
||||
1. 恢复 `mainland-worker-01`,让它重新进入可参与检测状态。
|
||||
2. 继续压 `mainland-controller-01` 的真实吞吐,只盯 `claimed -> running -> completed` 的推进,不回展示层。
|
||||
|
||||
你要避免的坑:
|
||||
1. 不要再把本机当成 `mainland-controller-01`。
|
||||
2. 不要优先用本机 Python service 入口直接造 deploy job,优先通过运行中的 API HTTP 接口。
|
||||
3. 不要把 `job 332` 这种“node-agent 重启自己导致状态未优雅回写”的现象直接误判为真正失败。
|
||||
4. 不要跑偏到 UI、导出、日志窗口样式这些支线。
|
||||
|
||||
你开始后先做这三件事,再继续动手:
|
||||
1. 复述你理解的当前真实环境拓扑。
|
||||
2. 复述当前两条唯一主线任务。
|
||||
3. 给出你准备先验证的 3 个现场指标,再开始执行。
|
||||
|
||||
目标只有一个:
|
||||
先把主流程和真实并发跑起来,让 controller 真机和 worker 真正参与检测,再谈细节优化。
|
||||
```
|
||||
98
docs/ops_center_runtime/HANDOFF_20260418_2321.md
Normal file
98
docs/ops_center_runtime/HANDOFF_20260418_2321.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# HANDOFF 2026-04-18 23:21
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
大陆节点接管闭环最小路径
|
||||
|
||||
原因:
|
||||
|
||||
- 当前控制面能力已基本足够
|
||||
- 当前最大阻塞不是新功能,而是大陆两台还停在:
|
||||
- `pending_bootstrap`
|
||||
- `agent_pending`
|
||||
- `SSH 未配置`
|
||||
- 只要这条链路不闭合,项目就仍然停留在“主控骨架可用,但统一接管未落地”的状态
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 当前阶段重心是优先级判断、闭环收口、执行顺序压缩
|
||||
- 需要稳定判断力,不适合降到偏快但更容易发散的配置
|
||||
- 当前阶段也暂时不需要切到 `xhigh`
|
||||
|
||||
## 下一轮如果继续,第一步先做什么
|
||||
|
||||
下一轮必须先做:
|
||||
|
||||
1. 录入大陆两台节点的 SSH 信息
|
||||
2. 复查 `nodes`
|
||||
3. 逐台跑 `node-handover`
|
||||
4. 逐台跑 `node-bootstrap-plan`
|
||||
|
||||
建议顺序:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
|
||||
推荐第一组动作:
|
||||
|
||||
```bash
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-bind-ssh http://127.0.0.1:8100 mainland-controller-01 <ssh_host> <ssh_user> 22
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-bind-ssh http://127.0.0.1:8100 mainland-worker-01 <ssh_host> <ssh_user> 22
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh nodes http://127.0.0.1:8100
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-handover http://127.0.0.1:8100 mainland-controller-01
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-bootstrap-plan http://127.0.0.1:8100 mainland-controller-01
|
||||
```
|
||||
|
||||
## 当前不要做的事情
|
||||
|
||||
现在不要做:
|
||||
|
||||
- 扩写新的架构设计文档
|
||||
- 新增页面
|
||||
- 新增模块
|
||||
- 继续增强控制面专题能力
|
||||
- 扩大 Release Hub 范围
|
||||
- 扩大 runbook / playbook 范围
|
||||
- 做与大陆节点接管闭环无直接关系的功能开发
|
||||
|
||||
## 当前阶段边界
|
||||
|
||||
本次已完成:
|
||||
|
||||
- 阶段校准
|
||||
- 闭环优先级重排
|
||||
- 任务板初始化
|
||||
- 状态板初始化
|
||||
- handoff 生成
|
||||
|
||||
本次未进入:
|
||||
|
||||
- 任何新实现
|
||||
- 任何新页面或新模块
|
||||
- 任何新的控制面增强项
|
||||
|
||||
## 下一轮完成主批次后的预期
|
||||
|
||||
如果大陆两台顺利完成:
|
||||
|
||||
- SSH 纳管
|
||||
- bootstrap
|
||||
- acceptance
|
||||
- `remote_access_ready=3/3`
|
||||
|
||||
则项目总体进度预计进入:
|
||||
|
||||
- `60%~65%` 的稳定上线准备区间
|
||||
|
||||
那时下一阶段才应该切到:
|
||||
|
||||
- 发布前总检
|
||||
- 正式收口
|
||||
- 上线证据导出
|
||||
155
docs/ops_center_runtime/HANDOFF_20260418_2344.md
Normal file
155
docs/ops_center_runtime/HANDOFF_20260418_2344.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# HANDOFF 2026-04-18 23:44
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
仍然是:大陆节点接管闭环最小路径
|
||||
|
||||
但当前阶段已经从“补 SSH 入口”切到:
|
||||
|
||||
- 修正大陆节点环境内容
|
||||
- 让 bootstrap 真正可以落地执行
|
||||
|
||||
## 今晚已完成的步骤
|
||||
|
||||
已完成:
|
||||
|
||||
1. 录入 `mainland-controller-01` SSH 信息
|
||||
2. 录入 `mainland-worker-01` SSH 信息
|
||||
3. 复查 `ops/nodes`
|
||||
4. 逐台执行 `node-handover`
|
||||
5. 逐台生成并复核 `node-bootstrap-plan`
|
||||
6. 复核:
|
||||
- `go-live-summary`
|
||||
- `ops/nodes`
|
||||
- `release-launchpad`
|
||||
7. 手工验证 controller SSH 登录可达
|
||||
|
||||
## 当前结果
|
||||
|
||||
当前指标:
|
||||
|
||||
- `ssh_ready = 2`
|
||||
- `remote_access_ready = 3`
|
||||
- 是否达到 `remote_access_ready = 3/3`:是
|
||||
|
||||
但 A1 仍未闭环,因为:
|
||||
|
||||
- `mainland-controller-01` 仍是 `pending_bootstrap`
|
||||
- `mainland-worker-01` 仍是 `pending_bootstrap`
|
||||
- 两台都还没有完成:
|
||||
- `bootstrap`
|
||||
- `register / heartbeat`
|
||||
- `acceptance`
|
||||
|
||||
## 两台节点推进到哪一步
|
||||
|
||||
### mainland-controller-01
|
||||
|
||||
已推进到:
|
||||
|
||||
- SSH 已录入
|
||||
- `node-handover` 已完成
|
||||
- `node-bootstrap-plan` 已生成
|
||||
- 手工 SSH 登录成功
|
||||
- 尝试执行 bootstrap 片段
|
||||
|
||||
准确卡点:
|
||||
|
||||
- 远端缺少 node-agent 所需文件
|
||||
- bootstrap 执行时报错:
|
||||
- `bootstrap_node_agent.sh not found under known layouts`
|
||||
- `Unit domaincheck-node-agent.service could not be found`
|
||||
|
||||
阻塞分类:
|
||||
|
||||
- 主阻塞:环境问题
|
||||
- 次阻塞:权限 / 外部条件问题
|
||||
- 当前控制面自动 SSH 执行器默认走密钥模式
|
||||
- 今晚验证可用的是密码 SSH
|
||||
|
||||
### mainland-worker-01
|
||||
|
||||
已推进到:
|
||||
|
||||
- SSH 已录入
|
||||
- `node-handover` 已完成
|
||||
- `node-bootstrap-plan` 已生成
|
||||
|
||||
准确卡点:
|
||||
|
||||
- 与 controller 同类
|
||||
- 远端缺少:
|
||||
- `domain-api/app/node_agent.py`
|
||||
- `domain-api/app/api/routes/ops_agent.py`
|
||||
- `domain-api/app/services/ops_agent_service.py`
|
||||
- `domain-api/deploy/systemd/domain-node-agent.service`
|
||||
- `domain-api/deploy/multi-region/templates/domaincheck-node-agent.env.example`
|
||||
|
||||
阻塞分类:
|
||||
|
||||
- 主阻塞:环境问题
|
||||
|
||||
## 收口结论
|
||||
|
||||
今晚属于“有明显进展,但 A1 未闭环”的收口结果。
|
||||
|
||||
明确进展:
|
||||
|
||||
- 从 `remote_access_ready = 1/3` 推进到了 `3/3`
|
||||
- 两台大陆节点都已进入 `ssh_ready`
|
||||
- handover 与 bootstrap plan 链路都已打通
|
||||
|
||||
明确未完成:
|
||||
|
||||
- 两台大陆节点仍未完成 bootstrap
|
||||
- 因此还没有 register / heartbeat
|
||||
- 也没有进入 acceptance
|
||||
|
||||
## 下一轮如果继续,第一步先做什么
|
||||
|
||||
下一轮先做的不是新功能,而是修正大陆节点环境。
|
||||
|
||||
最小动作:
|
||||
|
||||
1. 确认大陆两台代码目录由 `www` 用户更新到包含 node-agent 文件的最新版本
|
||||
2. 确认以下文件在两台大陆节点都存在:
|
||||
- `domain-api/app/node_agent.py`
|
||||
- `domain-api/app/api/routes/ops_agent.py`
|
||||
- `domain-api/app/services/ops_agent_service.py`
|
||||
- `domain-api/deploy/systemd/domain-node-agent.service`
|
||||
- `domain-api/deploy/multi-region/templates/domaincheck-node-agent.env.example`
|
||||
3. 然后重新执行:
|
||||
- `node-bootstrap-plan`
|
||||
- `bootstrap`
|
||||
- `acceptance`
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强项
|
||||
- 新架构文档扩写
|
||||
- Candidate B2
|
||||
- 为了解决今晚问题而扩展新的运维功能
|
||||
|
||||
## 明天需要你补充或操作的内容
|
||||
|
||||
你明天需要安排的最小动作是:
|
||||
|
||||
- 让大陆两台节点的仓库内容更新到当前控制面所需版本
|
||||
- 并且注意:
|
||||
- git / 代码更新应继续使用 `www`
|
||||
- 不要用 `root` 跑 git
|
||||
|
||||
## 当前一句话状态
|
||||
|
||||
今晚已经把大陆两台从“未纳管 SSH”推进到“SSH 可执行、bootstrap plan 可生成”,但两台都卡在相同的环境缺口上:远端仓库缺 node-agent 运行文件,因此 A1 还差最后的 bootstrap / register / acceptance 收口。
|
||||
138
docs/ops_center_runtime/HANDOFF_20260419_0007.md
Normal file
138
docs/ops_center_runtime/HANDOFF_20260419_0007.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# HANDOFF 2026-04-19 00:07
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 完成 `mainland-controller-01` 的公网控制面重接入
|
||||
|
||||
原因:
|
||||
|
||||
- `mainland-worker-01` 已经接管成功
|
||||
- `remote_access_ready = 3/3` 已达成
|
||||
- 当前只剩 controller 一台仍处于 `pending_bootstrap`
|
||||
|
||||
## 本轮已完成的步骤
|
||||
|
||||
已完成:
|
||||
|
||||
1. 复核当前 `nodes / go-live-summary / release-launchpad`
|
||||
2. 确认两台大陆节点都已拉到最新代码
|
||||
3. 重新生成 controller / worker 的 bootstrap plan
|
||||
4. 在 `mainland-controller-01` 成功执行一次 bootstrap 落地
|
||||
5. 在 `mainland-worker-01` 使用公网控制面地址完成:
|
||||
- bootstrap
|
||||
- register
|
||||
- heartbeat
|
||||
6. 确认 `mainland-worker-01` 已变为:
|
||||
- `agent_state = online_busy`
|
||||
- `remote_access_state = hybrid_ready`
|
||||
7. 为 `mainland-worker-01` 发起接管后验收:
|
||||
- `playbook_run_code = pbr-137e8b258b`
|
||||
|
||||
## 当前结果
|
||||
|
||||
当前摘要:
|
||||
|
||||
- `ssh_ready = 2`
|
||||
- `agent_ready = 2`
|
||||
- `remote_access_ready = 3/3`
|
||||
- `pending_bootstrap = 1`
|
||||
|
||||
节点结果:
|
||||
|
||||
- `mainland-worker-01`
|
||||
- 已接管成功
|
||||
- 已开始 acceptance
|
||||
- `mainland-controller-01`
|
||||
- 仍未完成接管
|
||||
- 当前是唯一剩余阻塞点
|
||||
|
||||
## 两台节点推进到哪一步
|
||||
|
||||
### mainland-worker-01
|
||||
|
||||
已推进到:
|
||||
|
||||
- SSH 已录入
|
||||
- `node-handover` 已完成
|
||||
- `node-bootstrap-plan` 已生成
|
||||
- 使用公网控制面地址完成 bootstrap
|
||||
- register / heartbeat 已建立
|
||||
- 节点已进入:
|
||||
- `online_busy`
|
||||
- `hybrid_ready`
|
||||
- acceptance 已发起
|
||||
|
||||
当前状态判断:
|
||||
|
||||
- 该节点已经不再属于接管主阻塞
|
||||
|
||||
### mainland-controller-01
|
||||
|
||||
已推进到:
|
||||
|
||||
- SSH 已录入
|
||||
- `node-handover` 已完成
|
||||
- `node-bootstrap-plan` 已生成
|
||||
- 首次 bootstrap 已真正落地安装并启动 node-agent
|
||||
|
||||
准确卡点:
|
||||
|
||||
- 第一次写入的 `OPS_CONTROL_PLANE_BASE_URL` 是:
|
||||
- `http://127.0.0.1:8100`
|
||||
- 对远端大陆节点来说,这会指向它自己,而不是海外控制面
|
||||
- 随后尝试把它改为公网控制面地址时,SSH 握手被远端重置
|
||||
|
||||
阻塞分类:
|
||||
|
||||
- 主阻塞:外部条件 / 网络或权限问题
|
||||
- 不是:
|
||||
- 新功能缺失
|
||||
- 代码目录缺文件
|
||||
- Node Agent 主链路不可用
|
||||
|
||||
## 下一轮若继续,第一步先做什么
|
||||
|
||||
下一轮第一步只做这一件事:
|
||||
|
||||
- 让 `mainland-controller-01` 成功执行“公网控制面地址版本”的 bootstrap 命令块
|
||||
|
||||
最小动作顺序:
|
||||
|
||||
1. 恢复 controller SSH 可执行窗口
|
||||
2. 重新写入:
|
||||
- `/etc/default/domaincheck-node-agent`
|
||||
3. 确认其中:
|
||||
- `OPS_CONTROL_PLANE_BASE_URL=http://152.53.37.118:8100`
|
||||
4. 重启:
|
||||
- `domaincheck-node-agent`
|
||||
5. 回控制面确认 controller 建立 register / heartbeat
|
||||
6. 对 controller 执行 acceptance
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
当前不建议切低模型的原因:
|
||||
|
||||
- 剩下的是收口型、多条件联动的现场问题
|
||||
- 需要稳定地分辨代码、执行参数、SSH 状态和节点真实状态
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强项
|
||||
- 新架构文档扩写
|
||||
- Candidate B2
|
||||
- 任何与 controller 收口无直接关系的工作
|
||||
|
||||
## 一句话结论
|
||||
|
||||
今晚不是“要不要重装系统”的阶段,而是已经把大陆接管闭环收束到只剩一台 controller:`worker-01` 已接管成功,`controller-01` 只差把 node-agent 正确指向海外公网控制面并完成一次成功回连。
|
||||
151
docs/ops_center_runtime/HANDOFF_20260419_0030.md
Normal file
151
docs/ops_center_runtime/HANDOFF_20260419_0030.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# HANDOFF 2026-04-19 00:30
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 完成 acceptance 与发布前证据收口
|
||||
|
||||
原因:
|
||||
|
||||
- A1 大陆节点接管闭环已经完成
|
||||
- 当前 3 台节点都已在线
|
||||
- 当前真正剩余的不是接管问题,而是:
|
||||
- acceptance 还没全部收口
|
||||
- playbook run 仍有排队 / attention
|
||||
- log sync 仍是 partial
|
||||
|
||||
## 本轮已完成的步骤
|
||||
|
||||
已完成:
|
||||
|
||||
1. 复跑 `go-live-check`
|
||||
2. 复跑 `stack-diagnosis`
|
||||
3. 复跑 `release-launchpad`
|
||||
4. 复核 `mainland-worker-01` acceptance run:
|
||||
- `pbr-137e8b258b`
|
||||
5. 确认 `mainland-controller-01` 已成功进入:
|
||||
- `online_busy`
|
||||
- `hybrid_ready`
|
||||
6. 确认全局摘要:
|
||||
- `pending_bootstrap = 0`
|
||||
- `agent_ready = 3`
|
||||
- `remote_access_ready = 3`
|
||||
|
||||
## 当前结果
|
||||
|
||||
当前已经成立的事实:
|
||||
|
||||
- 大陆节点接管闭环已完成
|
||||
- controller / worker 都已接管成功
|
||||
- delivery queue 当前 3/3 健康
|
||||
- 发布包与 release gate 已就绪
|
||||
|
||||
当前仍未收口的事实:
|
||||
|
||||
- `mainland-worker-01` acceptance run `pbr-137e8b258b`
|
||||
- 仍是 `queued / running`
|
||||
- `release-launchpad` 当前推荐动作:
|
||||
- `run_acceptance`
|
||||
- 推荐目标:
|
||||
- `mainland-controller-01`
|
||||
- `log_sync_state = partial_coverage`
|
||||
- 未覆盖节点:
|
||||
- `mainland-worker-01`
|
||||
- `mainland-controller-01`
|
||||
|
||||
## 最新总检摘要
|
||||
|
||||
### go-live-summary
|
||||
|
||||
- `go_live_status = attention`
|
||||
- `publish_status = attention`
|
||||
- `publish_blocking_reasons = []`
|
||||
- `next_step_action_code = focus_playbook_run`
|
||||
|
||||
说明:
|
||||
|
||||
- 当前不是硬阻断
|
||||
- 但仍建议先把 playbook / acceptance 收口完再正式发版
|
||||
|
||||
### stack-diagnosis
|
||||
|
||||
- `surface_status = healthy`
|
||||
- `automation_status = attention`
|
||||
- `stack_status = attention`
|
||||
- 当前主推荐动作:
|
||||
- `focus_playbook_run`
|
||||
|
||||
说明:
|
||||
|
||||
- 接口面与 contract 面没有缺口
|
||||
- 当前问题集中在运行编排层
|
||||
|
||||
### release-launchpad
|
||||
|
||||
- latest package 可用
|
||||
- latest release `ready`
|
||||
- default rollout gate `ready`
|
||||
- 当前 launchpad 仍显示阻断,原因不是 bootstrap,而是:
|
||||
- `Node Agent 已在线,可以直接跑 onboarding.acceptance 做标准接管验收。`
|
||||
- 推荐命令:
|
||||
- `bash domain-api/deploy/multi-region/drive_ops_center.sh node-acceptance-run http://127.0.0.1:8100 mainland-controller-01 cli`
|
||||
|
||||
## 下一轮若继续,第一步先做什么
|
||||
|
||||
下一轮第一步只做这一件事:
|
||||
|
||||
- 对 `mainland-controller-01` 发起 acceptance
|
||||
|
||||
然后依次做:
|
||||
|
||||
1. 观察 `mainland-controller-01` acceptance run
|
||||
2. 跟完 `mainland-worker-01` acceptance run `pbr-137e8b258b`
|
||||
3. 复查 playbook runs 是否仍有 `focus_playbook_run`
|
||||
4. 再复查 `go-live-summary / stack-diagnosis / release-launchpad`
|
||||
5. 输出上线签收证据摘要
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 当前阶段是高耦合收口,不适合切低模型
|
||||
- 需要稳定判断 acceptance、playbook、launchpad 和 go-live 之间的关联关系
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强项
|
||||
- 新架构文档扩写
|
||||
- 接管之外的自动化扩展
|
||||
- 在 acceptance 未收口前提前进入正式 Rollout
|
||||
|
||||
## 上线前证据摘要
|
||||
|
||||
已经具备的证据:
|
||||
|
||||
- 大陆节点接管完成
|
||||
- 3 台节点均在线
|
||||
- 发布包可用
|
||||
- smoke test 通过
|
||||
- final release gate 为 `ready`
|
||||
- delivery queue 当前 3/3 健康
|
||||
|
||||
尚缺的证据:
|
||||
|
||||
- controller acceptance 完成结果
|
||||
- worker acceptance 完成结果
|
||||
- playbook run 队列收口结果
|
||||
- log sync partial 覆盖问题的最终结论
|
||||
|
||||
## 一句话结论
|
||||
|
||||
项目已经从“接管闭环阶段”进入“上线前证据收口阶段”;当前真正拦在前面的,只剩 acceptance 与 playbook / log sync 这类运行证据,还不是代码能力问题。
|
||||
119
docs/ops_center_runtime/HANDOFF_20260419_0035.md
Normal file
119
docs/ops_center_runtime/HANDOFF_20260419_0035.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# HANDOFF 2026-04-19 00:35
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 跟完 acceptance run,拿到可签收终态
|
||||
|
||||
原因:
|
||||
|
||||
- acceptance 已全部发起
|
||||
- 当前接管不是问题
|
||||
- 当前真正卡住的是 acceptance 与 playbook run 收口
|
||||
|
||||
## 本轮已完成的步骤
|
||||
|
||||
已完成:
|
||||
|
||||
1. 对 `mainland-controller-01` 发起 acceptance
|
||||
2. 复核 `mainland-worker-01` acceptance run `pbr-137e8b258b`
|
||||
3. 复查:
|
||||
- `go-live-summary`
|
||||
- `stack-diagnosis`
|
||||
- `release-launchpad`
|
||||
4. 输出 acceptance 收口链判断
|
||||
|
||||
## 本轮执行摘要
|
||||
|
||||
### controller acceptance 结果
|
||||
|
||||
- `run_code = pbr-bfed43ea46`
|
||||
- 当前状态:`running`
|
||||
- 当前焦点:`health`
|
||||
- 当前说明:
|
||||
- `采集健康快照 当前处于排队中,建议先看事件和节点现场输出。`
|
||||
|
||||
### worker acceptance 结果
|
||||
|
||||
- `run_code = pbr-137e8b258b`
|
||||
- 当前状态:`running`
|
||||
- 当前焦点:`health`
|
||||
- 当前说明:
|
||||
- `采集健康快照 当前处于排队中,建议先看事件和节点现场输出。`
|
||||
|
||||
### go-live-summary 当前状态
|
||||
|
||||
- `go_live_status = attention`
|
||||
- `publish_status = attention`
|
||||
- `stack_status = attention`
|
||||
- `launchpad_status = attention`
|
||||
- `next_step_action_code = focus_playbook_run`
|
||||
|
||||
### stack-diagnosis 当前状态
|
||||
|
||||
- `surface_status = healthy`
|
||||
- `automation_status = attention`
|
||||
- `stack_status = attention`
|
||||
- `issue_total = 2`
|
||||
- `blocking_issue_total = 0`
|
||||
- `next_step_action_code = focus_playbook_run`
|
||||
|
||||
### release-launchpad 当前推荐动作
|
||||
|
||||
- `status = blocked`
|
||||
- `recommended_action_code = run_acceptance`
|
||||
- `recommended_target_node_code = mainland-controller-01`
|
||||
- 当前推荐摘要:
|
||||
- `Node Agent 已在线,可以直接跑 onboarding.acceptance 做标准接管验收。`
|
||||
|
||||
### log_sync_state`
|
||||
|
||||
- 当前仍为:`partial_coverage`
|
||||
- 未覆盖节点:
|
||||
- `mainland-worker-01`
|
||||
- `mainland-controller-01`
|
||||
|
||||
## 当前是否可上线签收
|
||||
|
||||
当前结论:
|
||||
|
||||
- 还不可上线签收
|
||||
|
||||
## 若仍不可签收,唯一剩余阻塞是什么
|
||||
|
||||
唯一剩余阻塞:
|
||||
|
||||
- acceptance playbook run 尚未完成,没有形成可签收终态
|
||||
|
||||
更具体地说:
|
||||
|
||||
- `pbr-bfed43ea46` 仍在运行
|
||||
- `pbr-137e8b258b` 仍在运行
|
||||
- 两条 run 都停在排队中的 `health` 步骤
|
||||
|
||||
当前没有出现明确失败,但也没有成功收口。
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 正式发布动作
|
||||
- 新功能开发
|
||||
- 新模块 / 新页面
|
||||
- 任何与 acceptance 收口无关的实现
|
||||
|
||||
## 下一轮若继续,第一步先做什么
|
||||
|
||||
下一轮第一步只做:
|
||||
|
||||
- 再次检查 `pbr-bfed43ea46` 与 `pbr-137e8b258b` 是否进入终态
|
||||
|
||||
如果 acceptance 仍卡在排队:
|
||||
|
||||
- 只记录阻塞点、影响范围和建议下一步
|
||||
- 不扩展实现来绕过阻塞
|
||||
|
||||
## 一句话结论
|
||||
|
||||
acceptance 收口链已经全部发起,但两条验收编排都还停在队列中;当前离上线签收只差“acceptance 形成终态证据”,不是差功能,不是差接管,也不是差发布包。
|
||||
135
docs/ops_center_runtime/HANDOFF_20260419_0050.md
Normal file
135
docs/ops_center_runtime/HANDOFF_20260419_0050.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# HANDOFF 2026-04-19 00:50 CST
|
||||
|
||||
## 本轮目标
|
||||
|
||||
只处理 acceptance 队列不消费问题,不扩功能,不新增页面或专题文档。
|
||||
|
||||
## 本轮完成
|
||||
|
||||
### 1. 定位并修复 acceptance 队列卡死
|
||||
|
||||
定位结果:
|
||||
|
||||
- 两台大陆节点都在持续请求 `/api/v1/ops/agent/pull?limit=1`
|
||||
- 控制面收到请求,但 acceptance job 长时间停留在 `queued`
|
||||
- 数据库中存在大量 `idle in transaction`
|
||||
- 事务卡在:
|
||||
- `UPDATE ops_job_steps ...`
|
||||
- 随后又在新连接里 `INSERT INTO ops_job_events ...`
|
||||
|
||||
代码修复:
|
||||
|
||||
- 文件:
|
||||
- [domain-api/app/services/ops_agent_service.py](/www/wwwroot/getDomain/domain-api/app/services/ops_agent_service.py)
|
||||
- 修改点:
|
||||
- `agent_pull_jobs`
|
||||
- `agent_mark_job_started`
|
||||
- `agent_complete_job`
|
||||
- 修复方式:
|
||||
- 把 `append_ops_job_event(...)` 从事务内部移到 `conn.commit()` 之后执行
|
||||
|
||||
### 2. 补充最小回归测试
|
||||
|
||||
- 文件:
|
||||
- [domain-api/tests/test_ops_agent_service.py](/www/wwwroot/getDomain/domain-api/tests/test_ops_agent_service.py)
|
||||
- 新增测试:
|
||||
- `test_agent_pull_jobs_commits_before_appending_event`
|
||||
- `test_agent_mark_job_started_commits_before_appending_event`
|
||||
- `test_agent_complete_job_commits_before_appending_event`
|
||||
- 验证结果:
|
||||
- `cd /www/wwwroot/getDomain/domain-api && /opt/domaincheck/domainCheck/.venv/bin/python -m unittest tests.test_ops_agent_service -q`
|
||||
- `Ran 27 tests ... OK`
|
||||
|
||||
### 3. 运行态验证
|
||||
|
||||
- `domaincheck-api` 已完成强制切换到新版本进程
|
||||
- 新进程:
|
||||
- `MainPID = 614403`
|
||||
- 运行态日志已确认:
|
||||
- `job 36 / 41` 开始执行
|
||||
- 已出现 `start / events / complete`
|
||||
|
||||
## 当前 acceptance 结果
|
||||
|
||||
### `mainland-worker-01`
|
||||
|
||||
- run:
|
||||
- `pbr-137e8b258b`
|
||||
- 当前状态:
|
||||
- `attention`
|
||||
- 结果:
|
||||
- `4 success + 1 failed`
|
||||
- 唯一失败步骤:
|
||||
- `node_agent_logs`
|
||||
- 失败原因:
|
||||
- `No journal files were opened due to insufficient permissions`
|
||||
|
||||
### `mainland-controller-01`
|
||||
|
||||
- run:
|
||||
- `pbr-bfed43ea46`
|
||||
- 当前状态:
|
||||
- `attention`
|
||||
- 结果:
|
||||
- `4 success + 1 failed`
|
||||
- 唯一失败步骤:
|
||||
- `node_agent_logs`
|
||||
- 失败原因:
|
||||
- `No journal files were opened due to insufficient permissions`
|
||||
|
||||
## 当前总检状态
|
||||
|
||||
`go-live-summary`:
|
||||
|
||||
- `go_live_status = attention`
|
||||
- `publish_status = attention`
|
||||
- `stack_status = attention`
|
||||
- `launchpad_status = attention`
|
||||
- `log_sync_state = full_capture`
|
||||
|
||||
`stack-diagnosis`:
|
||||
|
||||
- `surface_status = healthy`
|
||||
- `automation_status = attention`
|
||||
- `stack_status = attention`
|
||||
- `issue_total = 1`
|
||||
- `blocking_issue_total = 0`
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 修复远端 Node Agent 读取 `journalctl` 的权限
|
||||
|
||||
## 当前是否可上线签收
|
||||
|
||||
结论:
|
||||
|
||||
- 还不可上线签收
|
||||
|
||||
唯一剩余阻塞:
|
||||
|
||||
- 两条 acceptance run 都因为 `node_agent_logs` 权限不足而未全绿
|
||||
|
||||
## 下一轮若继续,必须先做什么
|
||||
|
||||
只做这一件事:
|
||||
|
||||
- 处理 `domaincheck-node-agent` 所在服务账号的 journal 读取权限
|
||||
|
||||
推荐最小方向:
|
||||
|
||||
- 让运行 Node Agent 的账号具备读取 systemd journal 的权限
|
||||
- 然后重跑 acceptance,或只补采失败日志步骤
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
- 不要回退这次热修复
|
||||
- 不要重新 bootstrap
|
||||
- 不要重装大陆机器
|
||||
- 不要扩控制面功能
|
||||
- 不要进入正式发布
|
||||
|
||||
## 本轮一句话结论
|
||||
|
||||
接管主链已经打通,acceptance 队列事务 bug 已修复;当前只剩远端 `journalctl` 权限问题,解决后即可继续冲刺上线签收。
|
||||
156
docs/ops_center_runtime/HANDOFF_20260419_0101.md
Normal file
156
docs/ops_center_runtime/HANDOFF_20260419_0101.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# HANDOFF 2026-04-19 01:01
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 完成 `B2-Journal Permission Closure`
|
||||
|
||||
原因:
|
||||
|
||||
- 接管链路已经闭合
|
||||
- acceptance 队列不消费问题已经修复
|
||||
- 当前两条 acceptance run 只剩同一个失败步骤:
|
||||
- `node_agent_logs`
|
||||
|
||||
## 本轮处理结论
|
||||
|
||||
本轮没有继续扩展控制面,也没有新增页面或模块。
|
||||
|
||||
本轮只做了两件事:
|
||||
|
||||
1. 把剩余阻塞进一步收敛为明确的环境落点:
|
||||
- `domaincheck-node-agent.service` 以 `www:www` 运行
|
||||
- 现网 unit 没有给 `www` 补 `journalctl` 所需的读取权限
|
||||
2. 在仓库中的 Node Agent systemd 模板加入:
|
||||
- `SupplementaryGroups=systemd-journal`
|
||||
|
||||
文件变更:
|
||||
|
||||
- `domain-api/deploy/systemd/domain-node-agent.service`
|
||||
|
||||
## 当前状态
|
||||
|
||||
当前摘要:
|
||||
|
||||
- `pending_bootstrap = 0`
|
||||
- `agent_ready = 3`
|
||||
- `remote_access_ready = 3`
|
||||
- `managed_enabled = 3`
|
||||
- `log_sync_state = full_capture`
|
||||
|
||||
acceptance 摘要:
|
||||
|
||||
- `mainland-worker-01`
|
||||
- `run_code = pbr-137e8b258b`
|
||||
- `status = attention`
|
||||
- `4 success + 1 failed`
|
||||
- 唯一失败步骤:`node_agent_logs`
|
||||
- `mainland-controller-01`
|
||||
- `run_code = pbr-bfed43ea46`
|
||||
- `status = attention`
|
||||
- `4 success + 1 failed`
|
||||
- 唯一失败步骤:`node_agent_logs`
|
||||
|
||||
## 当前唯一剩余阻塞
|
||||
|
||||
唯一剩余阻塞:
|
||||
|
||||
- 两台大陆节点尚未刷新新的 Node Agent systemd unit
|
||||
|
||||
准确卡点:
|
||||
|
||||
- 代码仓库里已经补了 `SupplementaryGroups=systemd-journal`
|
||||
- 但远端节点上的 `/etc/systemd/system/domaincheck-node-agent.service` 还需要重新安装并重启服务
|
||||
|
||||
阻塞分类:
|
||||
|
||||
- 环境 / 权限问题
|
||||
|
||||
不是以下问题:
|
||||
|
||||
- 不是 SSH 问题
|
||||
- 不是 agent offline
|
||||
- 不是 acceptance 队列不消费
|
||||
- 不是控制面接口 404
|
||||
|
||||
## 下一轮若继续,第一步先做什么
|
||||
|
||||
下一轮第一步只做这一件事:
|
||||
|
||||
- 在 `mainland-controller-01` 与 `mainland-worker-01` 上重新安装最新 Node Agent unit,并重启 `domaincheck-node-agent`
|
||||
|
||||
然后依次做:
|
||||
|
||||
1. 确认 unit 已带 `SupplementaryGroups=systemd-journal`
|
||||
2. 重跑两台节点 acceptance
|
||||
3. 复核:
|
||||
- `go-live-summary`
|
||||
- `stack-diagnosis`
|
||||
- `release-launchpad`
|
||||
4. 输出上线签收证据摘要
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 当前阶段是最后一段 acceptance 收口
|
||||
- 需要稳定处理运行证据与状态对账
|
||||
- 不需要切到超高推理
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 新功能
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强项
|
||||
- 新专题文档
|
||||
- 正式发布动作
|
||||
|
||||
## 给用户的下一任务卡片
|
||||
|
||||
按下面这张任务卡,在两台大陆节点执行:
|
||||
|
||||
```text
|
||||
任务名:B2-Journal Permission Closure / 节点 Unit 刷新
|
||||
|
||||
目标:
|
||||
1. 让 domaincheck-node-agent 具备 journal 读取权限
|
||||
2. 为 acceptance 清掉 node_agent_logs 的最后失败点
|
||||
|
||||
执行节点:
|
||||
- mainland-controller-01
|
||||
- mainland-worker-01
|
||||
|
||||
执行步骤:
|
||||
1. 进入最新代码目录
|
||||
2. 重新安装最新 unit 文件到 /etc/systemd/system/domaincheck-node-agent.service
|
||||
3. daemon-reload
|
||||
4. restart domaincheck-node-agent
|
||||
5. 输出 unit 关键行与服务状态
|
||||
|
||||
执行命令:
|
||||
cd /www/wwwroot/getDomain
|
||||
install -m 0644 domain-api/deploy/systemd/domain-node-agent.service /etc/systemd/system/domaincheck-node-agent.service
|
||||
systemctl daemon-reload
|
||||
systemctl restart domaincheck-node-agent
|
||||
systemctl cat domaincheck-node-agent | grep -E '^(User|Group|SupplementaryGroups)='
|
||||
systemctl status domaincheck-node-agent --no-pager -l
|
||||
journalctl -u domaincheck-node-agent -n 60 --no-pager
|
||||
|
||||
回传给 Codex 的结果:
|
||||
1. systemctl cat 中是否出现 SupplementaryGroups=systemd-journal
|
||||
2. systemctl status 是否 active (running)
|
||||
3. journalctl 是否还出现 insufficient permissions
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
项目现在不缺接管能力,也不缺控制面能力;真正剩下的只是把两台大陆节点上的 Node Agent unit 刷新到最新,然后重跑 acceptance 把最后一个 `node_agent_logs` 失败点清掉。
|
||||
126
docs/ops_center_runtime/HANDOFF_20260419_0107.md
Normal file
126
docs/ops_center_runtime/HANDOFF_20260419_0107.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# HANDOFF 2026-04-19 01:07
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 执行 `C1-Acceptance Re-run`
|
||||
|
||||
原因:
|
||||
|
||||
- `B2-Journal Permission Closure` 在运行态上已经具备完成证据
|
||||
- 两台节点都已出现:
|
||||
- `logs.collect ok=True`
|
||||
- `domaincheck-node-agent` 重启成功
|
||||
- `registered: Agent 注册成功`
|
||||
- 当前只剩旧 acceptance 结果尚未被新运行态覆盖
|
||||
|
||||
## 本轮确认到的运行态证据
|
||||
|
||||
`mainland-controller-01`:
|
||||
|
||||
- 旧执行记录中已经出现:
|
||||
- `action=logs.collect ok=True`
|
||||
- 之后又完成:
|
||||
- `domaincheck-node-agent.service` 停止 / 启动
|
||||
- `starting node agent`
|
||||
- `registered: Agent 注册成功`
|
||||
|
||||
`mainland-worker-01`:
|
||||
|
||||
- 旧执行记录中已经出现:
|
||||
- `action=logs.collect ok=True`
|
||||
- 之后也完成:
|
||||
- `domaincheck-node-agent.service` 停止 / 启动
|
||||
- `starting node agent`
|
||||
- `registered: Agent 注册成功`
|
||||
|
||||
## 当前判断
|
||||
|
||||
当前可以做出的最小结论:
|
||||
|
||||
- 日志权限收口在运行面已经打通
|
||||
- Node Agent 当前在线且能重新注册
|
||||
- 不需要再回头排查 SSH、bootstrap、heartbeat、队列消费
|
||||
|
||||
当前还不能直接签收上线的唯一原因:
|
||||
|
||||
- 控制面上仍保留旧 acceptance run 的 `attention` 结果
|
||||
|
||||
## 下一轮若继续,第一步先做什么
|
||||
|
||||
下一轮第一步只做这一件事:
|
||||
|
||||
- 分别对 `mainland-controller-01` 和 `mainland-worker-01` 重跑 acceptance
|
||||
|
||||
然后依次做:
|
||||
|
||||
1. 记录新的 acceptance `run_code`
|
||||
2. 确认两条 run 是否全绿
|
||||
3. 复核:
|
||||
- `go-live-summary`
|
||||
- `stack-diagnosis`
|
||||
- `release-launchpad`
|
||||
4. 输出上线签收证据摘要
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 当前还是高耦合收口阶段
|
||||
- 但已经不需要切超高推理
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 新功能
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强项
|
||||
- 新专题文档
|
||||
- 正式发布动作
|
||||
|
||||
## 给用户的下一任务卡片
|
||||
|
||||
按下面这张任务卡继续:
|
||||
|
||||
```text
|
||||
任务名:C1-Acceptance Re-run / 两台大陆节点验收重跑
|
||||
|
||||
目标:
|
||||
1. 用新的运行态覆盖旧 acceptance 失败结果
|
||||
2. 确认 mainland-controller-01 与 mainland-worker-01 是否都已通过标准接管验收
|
||||
3. 为上线签收准备最终证据
|
||||
|
||||
执行位置:
|
||||
- 海外控制面主机
|
||||
|
||||
执行命令:
|
||||
cd /www/wwwroot/getDomain
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-acceptance-run http://127.0.0.1:8100 mainland-controller-01 cli
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-acceptance-run http://127.0.0.1:8100 mainland-worker-01 cli
|
||||
|
||||
然后继续执行:
|
||||
curl -s http://127.0.0.1:8100/api/v1/ops/go-live-summary
|
||||
echo
|
||||
curl -s http://127.0.0.1:8100/api/v1/ops/stack-diagnosis
|
||||
echo
|
||||
curl -s http://127.0.0.1:8100/api/v1/ops/release-launchpad
|
||||
|
||||
回传给 Codex 的结果:
|
||||
1. controller 新的 acceptance run_code 和最终状态
|
||||
2. worker 新的 acceptance run_code 和最终状态
|
||||
3. go-live-summary 当前状态
|
||||
4. stack-diagnosis 当前状态
|
||||
5. release-launchpad 当前推荐动作
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
当前项目已经越过“日志权限修复”这一步,下一步不需要再修环境,只需要把两台大陆节点的 acceptance 重跑一遍,用新结果完成上线前签收判断。
|
||||
133
docs/ops_center_runtime/HANDOFF_20260419_0115.md
Normal file
133
docs/ops_center_runtime/HANDOFF_20260419_0115.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# HANDOFF 2026-04-19 01:15
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 执行 `D1-Evidence Convergence`
|
||||
|
||||
原因:
|
||||
|
||||
- 大陆两台 acceptance 已经全绿
|
||||
- 当前不再是接管链路问题
|
||||
- 当前剩余的是“上线签收证据口径”没有完全收敛
|
||||
|
||||
## 本轮已完成
|
||||
|
||||
`mainland-controller-01`:
|
||||
|
||||
- acceptance 新 run:
|
||||
- `pbr-9ce5c85f17`
|
||||
- 最终结果:
|
||||
- `status = success`
|
||||
- `5 success / 0 failed`
|
||||
|
||||
`mainland-worker-01`:
|
||||
|
||||
- acceptance 新 run:
|
||||
- `pbr-389abd618c`
|
||||
- 最终结果:
|
||||
- `status = success`
|
||||
- `5 success / 0 failed`
|
||||
|
||||
总检现状:
|
||||
|
||||
- `go_live_status = attention`
|
||||
- `stack_status = attention`
|
||||
- `publish_status = attention`
|
||||
- `launchpad_status = attention`
|
||||
- `log_sync_state = partial_coverage`
|
||||
- `log_sync_missing_node_codes = [overseas-control-01]`
|
||||
- `stack_diagnosis.issue_total = 2`
|
||||
- `stack_diagnosis.blocking_issue_total = 0`
|
||||
|
||||
## 当前判断
|
||||
|
||||
当前已经可以确认:
|
||||
|
||||
- 大陆节点接管闭环已完成
|
||||
- acceptance 已通过
|
||||
- Node Agent 日志权限问题已真实解除
|
||||
|
||||
当前还不能直接签收上线的原因只有一类:
|
||||
|
||||
- 证据口径还没完全收敛
|
||||
|
||||
具体表现为两处:
|
||||
|
||||
- `overseas-control-01` 还没有补齐日志样本,导致 `log_sync_state = partial_coverage`
|
||||
- `stack-diagnosis / release-launchpad` 仍保留历史 attention / stale 推荐
|
||||
|
||||
## 下一轮若继续,第一步先做什么
|
||||
|
||||
下一轮第一步只做这一件事:
|
||||
|
||||
- 给 `overseas-control-01` 补一轮场景日志样本
|
||||
|
||||
然后依次做:
|
||||
|
||||
1. 复查 `go-live-summary`
|
||||
2. 复查 `stack-diagnosis`
|
||||
3. 复查 `release-launchpad`
|
||||
4. 判断 attention 是否已收敛到可上线签收
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 当前还是收口判断阶段
|
||||
- 需要稳定地辨别“真实阻塞”和“口径残留”
|
||||
- 但还不需要切到超高推理
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 新功能
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强项
|
||||
- 新专题文档
|
||||
- 正式发布动作
|
||||
|
||||
## 下一个任务卡
|
||||
|
||||
```text
|
||||
任务名:D1-Evidence Convergence / overseas-control-01 日志补样与总检复核
|
||||
|
||||
目标:
|
||||
1. 补齐 overseas-control-01 的场景日志样本
|
||||
2. 观察 go-live-summary 是否从 partial_coverage 收敛
|
||||
3. 观察 stack-diagnosis 与 release-launchpad 是否仍保留历史残留口径
|
||||
4. 判断是否达到可上线签收状态
|
||||
|
||||
执行位置:
|
||||
- 海外控制面主机
|
||||
|
||||
执行命令:
|
||||
cd /www/wwwroot/getDomain
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh scene-node-log http://127.0.0.1:8100 overseas-control-01 120 full
|
||||
|
||||
然后继续执行:
|
||||
curl -s http://127.0.0.1:8100/api/v1/ops/go-live-summary
|
||||
echo
|
||||
curl -s http://127.0.0.1:8100/api/v1/ops/stack-diagnosis
|
||||
echo
|
||||
curl -s http://127.0.0.1:8100/api/v1/ops/releases/launchpad
|
||||
|
||||
回传给 Codex 的结果:
|
||||
1. overseas-control-01 场景日志是否成功拉到样本
|
||||
2. go-live-summary 当前状态
|
||||
3. stack-diagnosis 当前 issue_total / blocking_issue_total
|
||||
4. release-launchpad 当前推荐动作
|
||||
5. 当前是否已经达到可上线签收
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
acceptance 这一关已经过了;下一轮不该再回头修大陆节点,而是只把 `overseas-control-01` 的日志样本和总检残留口径收敛掉。
|
||||
128
docs/ops_center_runtime/HANDOFF_20260419_0121.md
Normal file
128
docs/ops_center_runtime/HANDOFF_20260419_0121.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# HANDOFF 2026-04-19 01:21
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 执行 `E1-Historical Signal Convergence`
|
||||
|
||||
原因:
|
||||
|
||||
- `overseas-control-01` 的日志样本已经补齐
|
||||
- `go-live-summary.log_sync_state` 已恢复为 `full_capture`
|
||||
- 当前不再是样本缺口问题,而是历史 attention 口径未完全收敛
|
||||
|
||||
## 本轮已完成
|
||||
|
||||
日志样本补齐:
|
||||
|
||||
- 已执行 `log-sync-recover`
|
||||
- 已执行 `run_inspection_participating`
|
||||
- 新巡检 run:
|
||||
- `pbr-df533c6f4a`
|
||||
- `overseas-control-01`:
|
||||
- `scene-log status = full_capture`
|
||||
- `line_count = 1`
|
||||
|
||||
总检变化:
|
||||
|
||||
- `go-live-summary`
|
||||
- `log_sync_state: partial_coverage -> full_capture`
|
||||
- `log_sync_missing_node_codes: [overseas-control-01] -> []`
|
||||
- `stack-diagnosis`
|
||||
- `issue_total: 2 -> 1`
|
||||
- `blocking_issue_total = 0`
|
||||
- `playbook_runs.problem_runs_total`
|
||||
- `4 -> 3`
|
||||
|
||||
## 当前判断
|
||||
|
||||
当前已经可以确认:
|
||||
|
||||
- 大陆节点接管闭环已完成
|
||||
- acceptance 已通过
|
||||
- participating 节点日志样本覆盖已完成
|
||||
|
||||
当前还不能直接签收上线的原因只有一类:
|
||||
|
||||
- 历史 playbook / launchpad attention 口径还没完全消化掉
|
||||
|
||||
具体表现为两处:
|
||||
|
||||
- `stack-diagnosis` 还剩:
|
||||
- `playbook_runs_need_attention`
|
||||
- `release-launchpad` 还保留旧推荐:
|
||||
- `run_acceptance`
|
||||
- `mainland-controller-01`
|
||||
|
||||
## 下一轮若继续,第一步先做什么
|
||||
|
||||
下一轮第一步只做这一件事:
|
||||
|
||||
- 聚焦 `focus_playbook_run`
|
||||
|
||||
然后依次做:
|
||||
|
||||
1. 查清 `problem_runs_total = 3` 是不是纯历史旧 run
|
||||
2. 复查 `stack-diagnosis`
|
||||
3. 复查 `release-launchpad`
|
||||
4. 判断当前是否已经达到可上线签收
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 当前已经进入最后的收口判断阶段
|
||||
- 需要高质量区分“真阻塞”和“历史口径残留”
|
||||
- 还不需要切超高推理
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 新功能
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强项
|
||||
- 新专题文档
|
||||
- 正式发布动作
|
||||
|
||||
## 下一个任务卡
|
||||
|
||||
```text
|
||||
任务名:E1-Historical Signal Convergence / 历史 playbook attention 收口
|
||||
|
||||
目标:
|
||||
1. 确认 stack-diagnosis 剩余的唯一告警是不是纯历史旧 run
|
||||
2. 判断 release-launchpad 的旧 acceptance 推荐是否只是残留口径
|
||||
3. 为上线签收做最后判断
|
||||
|
||||
执行位置:
|
||||
- 海外控制面主机
|
||||
|
||||
执行命令:
|
||||
cd /www/wwwroot/getDomain
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 focus_playbook_run
|
||||
echo
|
||||
bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 open_playbook_run_latest_events
|
||||
echo
|
||||
curl -s http://127.0.0.1:8100/api/v1/ops/stack-diagnosis
|
||||
echo
|
||||
curl -s http://127.0.0.1:8100/api/v1/ops/releases/launchpad
|
||||
|
||||
回传给 Codex 的结果:
|
||||
1. focus_playbook_run 指向的具体 run_code
|
||||
2. 该 run 是否是历史旧 run
|
||||
3. stack-diagnosis 当前 issue_total
|
||||
4. release-launchpad 当前推荐动作
|
||||
5. 当前是否已经达到可上线签收
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
日志样本缺口已经补上了;下一轮不该再碰接管和日志链路,而是只把最后那条历史 attention 口径清掉。
|
||||
129
docs/ops_center_runtime/HANDOFF_20260419_0225.md
Normal file
129
docs/ops_center_runtime/HANDOFF_20260419_0225.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# HANDOFF 2026-04-19 02:25
|
||||
|
||||
## 本轮完成了什么
|
||||
|
||||
本轮只收口了“大陆 controller 无法 `pull_tasks`”这一条链。
|
||||
|
||||
实际完成:
|
||||
|
||||
1. 修复 `domaincheck-node-agent` 读取不到同步目标地址的问题
|
||||
2. 以 `www` 提交并推送:
|
||||
- `74dc009`
|
||||
- `fix: inherit sync env in node agent`
|
||||
3. 在两台大陆节点刷新 `domaincheck-node-agent.service`
|
||||
4. 重启并验证:
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
5. 从海外控制面再次发起:
|
||||
- `runtime.pull_tasks`
|
||||
- `job_id = 87`
|
||||
6. 验证 `mainland-controller-01` 返回成功:
|
||||
- `pull_state = success`
|
||||
- `items_total = 50`
|
||||
7. 验证大陆两台节点当前都处于:
|
||||
- `participation_state = running`
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 收敛检测总览统计口径
|
||||
|
||||
原因:
|
||||
|
||||
- 现在不是“没跑”
|
||||
- 而是“已经跑了,但总览没完整体现大陆执行量”
|
||||
|
||||
## 当前状态摘要
|
||||
|
||||
当前结论:
|
||||
|
||||
- 检测执行链已跑通
|
||||
- 大陆 controller 已能拉任务
|
||||
- 大陆 controller / worker 已进入执行中
|
||||
|
||||
直接证据:
|
||||
|
||||
- `ops/nodes`
|
||||
- `mainland-controller-01`
|
||||
- `items_total = 200`
|
||||
- `items_running = 5`
|
||||
- `mainland-worker-01`
|
||||
- `items_total = 70`
|
||||
- `items_running = 5`
|
||||
- `job 87`
|
||||
- `runtime.pull_tasks`
|
||||
- `status = success`
|
||||
|
||||
## 当前唯一剩余问题
|
||||
|
||||
唯一剩余问题:
|
||||
|
||||
- `detect/queue-summary`
|
||||
- `detect/job/active`
|
||||
|
||||
仍主要沿用旧的海外活跃任务口径,没有把大陆“拉批后本地执行”的量体现在同一汇总里。
|
||||
|
||||
这会导致页面观感像“大陆没跑”,但实际上已经在跑。
|
||||
|
||||
## 下一轮如果继续,只做什么
|
||||
|
||||
下一轮只做这一件事:
|
||||
|
||||
- 对齐以下三处的数据口径:
|
||||
- `ops/nodes`
|
||||
- `detect/queue-summary`
|
||||
- `detect/job/active`
|
||||
|
||||
目标:
|
||||
|
||||
- 让后台页面既能显示大陆节点正在执行
|
||||
- 又能把这部分执行量合并进统一检测进度
|
||||
|
||||
## 现在不要做的事情
|
||||
|
||||
不要做:
|
||||
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 运维中枢增强
|
||||
- 正式发布
|
||||
- 与检测总览收口无关的任何工作
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 当前是数据口径排查与小范围实现
|
||||
- 不需要切超高
|
||||
|
||||
## 给下一轮的任务卡
|
||||
|
||||
```text
|
||||
任务名:G1-检测总览口径统一批
|
||||
|
||||
目标:
|
||||
1. 查清 ops/nodes 与 detect/job/active 的数据来源差异
|
||||
2. 明确大陆 controller 拉批执行为什么没有进入统一检测总览
|
||||
3. 修好后再跑一轮小批量检测验证
|
||||
|
||||
范围限制:
|
||||
1. 只做检测总览口径统一
|
||||
2. 不新增页面
|
||||
3. 不扩展控制面功能
|
||||
4. 不进入发布动作
|
||||
|
||||
完成判定:
|
||||
1. 点击启动检测后
|
||||
2. 后台能看到大陆节点参与
|
||||
3. detect/queue-summary 不再只显示 overseas-control-01 与 unassigned
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
这轮已经把“大陆 controller 拉不到任务”这个硬阻塞清掉了;现在真正剩下的不是执行问题,而是后台统计口径还没把大陆执行量完整显示出来。
|
||||
122
docs/ops_center_runtime/HANDOFF_20260419_0233.md
Normal file
122
docs/ops_center_runtime/HANDOFF_20260419_0233.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# HANDOFF 2026-04-19 02:33
|
||||
|
||||
## 本轮完成了什么
|
||||
|
||||
本轮只处理了一个问题:
|
||||
|
||||
- Detect 页面没有把大陆节点参与展示出来
|
||||
|
||||
实际完成:
|
||||
|
||||
1. 后端补出分布式显示口径
|
||||
2. 前端 Detect 页面切到优先显示分布式口径
|
||||
3. 本地重启 `domaincheck-api`
|
||||
4. 重新验证 Detect 接口
|
||||
|
||||
## 本轮关键结果
|
||||
|
||||
`detect/job/active` 现在新增:
|
||||
|
||||
- `distributed_node_stats`
|
||||
- `display_items_claimed`
|
||||
- `display_items_running`
|
||||
|
||||
当前接口结果:
|
||||
|
||||
- `display_items_claimed = 34`
|
||||
- `display_items_running = 14`
|
||||
|
||||
当前已显示节点:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
- `overseas-control-01`
|
||||
- `unassigned`
|
||||
|
||||
`detect/queue-summary` 现在新增:
|
||||
|
||||
- `queue.display_claimed = 34`
|
||||
- `queue.display_running = 14`
|
||||
|
||||
并且 `nodes` 已包含大陆 controller / worker。
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 检测账本统一
|
||||
|
||||
原因:
|
||||
|
||||
- 现在页面显示已经基本正常
|
||||
- 剩下的不是“看不见”,而是“中央账本和分布式执行账本还没真正合并”
|
||||
|
||||
## 当前状态结论
|
||||
|
||||
当前可以明确说:
|
||||
|
||||
- 检测能跑
|
||||
- 大陆节点确实参与了
|
||||
- Detect 页面现在已经能直接看见大陆参与
|
||||
|
||||
## 当前唯一剩余问题
|
||||
|
||||
唯一剩余问题:
|
||||
|
||||
- 目前仍是双账本:
|
||||
- 中央 `detect_job_items`
|
||||
- 分布式 runtime / projection 显示口径
|
||||
|
||||
所以:
|
||||
|
||||
- 页面观感已收口
|
||||
- 账本一致性还没完全收口
|
||||
|
||||
## 下一轮如果继续,只做什么
|
||||
|
||||
下一轮只做这一件事:
|
||||
|
||||
- 明确并实现“中央派发账本”与“大陆执行账本”的统一规则
|
||||
|
||||
优先原则:
|
||||
|
||||
- 不发散
|
||||
- 不扩新页面
|
||||
- 不碰发布动作
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 下一轮是账本统一策略与最小实现
|
||||
- 仍不需要切超高
|
||||
|
||||
## 给下一轮的任务卡
|
||||
|
||||
```text
|
||||
任务名:H1-检测账本统一设计与最小落地批
|
||||
|
||||
目标:
|
||||
1. 查清 detect_job_items 与 runtime/projection 的最终一致关系
|
||||
2. 决定 pull / ack / result sync 后中央账本如何更新
|
||||
3. 只做最小一致性修复,不扩功能
|
||||
|
||||
范围限制:
|
||||
1. 不新增页面
|
||||
2. 不扩控制面功能
|
||||
3. 不进入发布动作
|
||||
4. 不并行做别的方向
|
||||
|
||||
完成判定:
|
||||
1. Detect 页面显示正确
|
||||
2. Detect 中央账本与大陆执行账本不再明显分叉
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
这轮已经把“大陆在跑但页面像没跑”的问题收掉了;下一轮真正该做的,不是继续修显示,而是把检测账本本身统一起来。
|
||||
127
docs/ops_center_runtime/HANDOFF_20260419_0240.md
Normal file
127
docs/ops_center_runtime/HANDOFF_20260419_0240.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# HANDOFF 2026-04-19 02:40
|
||||
|
||||
## 本轮完成了什么
|
||||
|
||||
本轮只处理了一个问题:
|
||||
|
||||
- Detect 主统计还是“中央原值 + display 附加值”双轨,Runtime / Detect 不够统一
|
||||
|
||||
实际完成:
|
||||
|
||||
1. 新增有效账本聚合逻辑
|
||||
2. `active_job` 主字段切到统一后的有效值
|
||||
3. 保留 `raw_*` 原始中央账本字段
|
||||
4. 新增针对统一规则的后端单测
|
||||
5. 重启 `domaincheck-api`
|
||||
6. 重新验证线上接口
|
||||
|
||||
## 本轮关键结果
|
||||
|
||||
`detect/job/active` 现在主字段直接返回:
|
||||
|
||||
- `items_total = 1000`
|
||||
- `items_pending = 931`
|
||||
- `items_claimed = 34`
|
||||
- `items_running = 14`
|
||||
- `items_completed = 21`
|
||||
|
||||
同时保留原始中央账本:
|
||||
|
||||
- `raw_items_pending = 950`
|
||||
- `raw_items_claimed = 25`
|
||||
- `raw_items_running = 4`
|
||||
|
||||
`node_stats` / `distributed_node_stats` 当前已统一为:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
- `overseas-control-01`
|
||||
- `unassigned = 680`
|
||||
|
||||
`detect/queue-summary` 当前主字段:
|
||||
|
||||
- `pending = 931`
|
||||
- `claimed = 34`
|
||||
- `running = 14`
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 决定是否继续进入 item 级结果回写统一
|
||||
|
||||
原因:
|
||||
|
||||
- 当前主统计已经基本统一
|
||||
- 剩下真正没闭环的是 `detect_result_projection -> detect_job_items`
|
||||
|
||||
## 当前状态结论
|
||||
|
||||
当前可以明确说:
|
||||
|
||||
- 检测能跑
|
||||
- 大陆节点确实参与了
|
||||
- Detect 页面和主统计都更接近真实执行态
|
||||
- Runtime / Queue / Detect 主摘要开始吃同一套有效账本
|
||||
|
||||
## 当前唯一剩余问题
|
||||
|
||||
唯一剩余问题:
|
||||
|
||||
- 目前还是“聚合统一”
|
||||
- 还不是“逐条 item 最终一致”
|
||||
|
||||
所以:
|
||||
|
||||
- 主观感受和主统计已经收口
|
||||
- 底层逐条账本还没完全收口
|
||||
|
||||
## 下一轮如果继续,只做什么
|
||||
|
||||
下一轮只做这一件事:
|
||||
|
||||
- 查清是否要把 `detect_result_projection` 最小映射回 `detect_job_items`
|
||||
|
||||
优先原则:
|
||||
|
||||
- 不发散
|
||||
- 不扩新页面
|
||||
- 不碰发布动作
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 下一轮是 item 级账本映射策略
|
||||
- 仍然是高复杂度,但还没到必须切超高
|
||||
|
||||
## 给下一轮的任务卡
|
||||
|
||||
```text
|
||||
任务名:I1-detect_result_projection 到 detect_job_items 的最小映射设计批
|
||||
|
||||
目标:
|
||||
1. 查清当前 detect_result_projection 能提供哪些聚合字段
|
||||
2. 判断是否足以做 item 级状态回写,还是只能做批次级回写
|
||||
3. 只做最小一致性设计,不重做执行链
|
||||
|
||||
范围限制:
|
||||
1. 不新增页面
|
||||
2. 不扩控制面功能
|
||||
3. 不进入发布动作
|
||||
4. 不并行做别的方向
|
||||
|
||||
完成判定:
|
||||
1. 给出 item 级统一是否可行的结论
|
||||
2. 如果可行,明确最小落点
|
||||
3. 如果暂不可行,明确缺的字段和最小补数方案
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
这轮已经把 Detect 主统计从“靠 display 补丁看懂”推进到“主字段直接统一可读”;下一轮真正该做的,只剩下是否继续把结果同步推进到 item 级逐条账本。
|
||||
135
docs/ops_center_runtime/HANDOFF_20260419_0243.md
Normal file
135
docs/ops_center_runtime/HANDOFF_20260419_0243.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# HANDOFF 2026-04-19 02:43
|
||||
|
||||
## 本轮完成了什么
|
||||
|
||||
本轮只做了一件事:
|
||||
|
||||
- 把 `I1-检测结果逐条回写设计批` 查到底,确认当前是否真的能做 item 级统一
|
||||
|
||||
实际结论:
|
||||
|
||||
- 现在还不能直接做 item 级回写
|
||||
|
||||
## 本轮关键证据
|
||||
|
||||
### 证据 1:`detect_result_projection` 只有聚合数据
|
||||
|
||||
当前只包含:
|
||||
|
||||
- `job`
|
||||
- `latest_event`
|
||||
- `queue`
|
||||
- `phase`
|
||||
|
||||
没有:
|
||||
|
||||
- `domain_id`
|
||||
- `job_item_id`
|
||||
- 逐条终态结果
|
||||
|
||||
### 证据 2:中央 `detect_run_events` 的逐条结果只有海外
|
||||
|
||||
当前中央看到的逐条事件只有:
|
||||
|
||||
- `overseas-control-01`
|
||||
- `domain_started`
|
||||
- `domain_completed`
|
||||
|
||||
中央没看到:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- 无 `domain_*`
|
||||
- `mainland-worker-01`
|
||||
- 无 `domain_*`
|
||||
|
||||
### 证据 3:所以当前不能直接回写 `detect_job_items`
|
||||
|
||||
原因不是逻辑不会写,而是中央没有大陆逐条输入。
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- `J1-大陆逐条结果同步前置批`
|
||||
|
||||
原因:
|
||||
|
||||
- item 级统一的真正阻塞点已经定位
|
||||
- 下一步必须先把大陆逐条结果送到中央
|
||||
|
||||
## 当前状态结论
|
||||
|
||||
当前可以明确说:
|
||||
|
||||
- 检测能跑
|
||||
- 大陆节点确实参与了
|
||||
- 主统计已经统一
|
||||
- 但 item 级回写现在还做不了
|
||||
|
||||
## 当前唯一剩余问题
|
||||
|
||||
唯一剩余问题:
|
||||
|
||||
- 大陆节点缺少逐条结果进入中央的最小同步通道
|
||||
|
||||
所以当前阶段已经从:
|
||||
|
||||
- “显示不对”
|
||||
|
||||
进入到:
|
||||
|
||||
- “逐条结果输入还没进中央”
|
||||
|
||||
## 下一轮如果继续,只做什么
|
||||
|
||||
下一轮只做这一件事:
|
||||
|
||||
- 给大陆执行链补最小逐条结果同步输入
|
||||
|
||||
优先原则:
|
||||
|
||||
- 不发散
|
||||
- 不扩页面
|
||||
- 不碰发布动作
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
原因:
|
||||
|
||||
- 下一轮是同步链最小设计与落地
|
||||
- 还不必切超高
|
||||
|
||||
## 给下一轮的任务卡
|
||||
|
||||
```text
|
||||
任务名:J1-大陆逐条结果同步前置批
|
||||
|
||||
目标:
|
||||
1. 让大陆节点把逐条检测终态送到中央
|
||||
2. 至少带回:
|
||||
- job_code
|
||||
- cycle_token
|
||||
- domain_id 或可稳定映射的 domain
|
||||
- result_status
|
||||
- finished_at
|
||||
3. 只补输入通道,不做最终 item 回写
|
||||
|
||||
范围限制:
|
||||
1. 不新增页面
|
||||
2. 不扩控制面功能
|
||||
3. 不进入发布动作
|
||||
4. 不并行做别的方向
|
||||
|
||||
完成判定:
|
||||
1. 中央能看到 mainland 节点的 domain_* 终态事件或等价逐条投影
|
||||
2. 后续再做 detect_job_items 回写时,不再缺输入
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
这轮已经把“为什么 item 级统一还做不了”彻底查清了;下一轮真正该做的,不是继续改统计,而是先把大陆逐条结果送进中央。
|
||||
97
docs/ops_center_runtime/HANDOFF_20260419_0251.md
Normal file
97
docs/ops_center_runtime/HANDOFF_20260419_0251.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# HANDOFF 2026-04-19 02:51
|
||||
|
||||
## 本轮完成了什么
|
||||
|
||||
本轮只做了 `J1-大陆逐条结果同步前置批` 的最小实现,不进入新页面、不扩控制面:
|
||||
|
||||
- `detect_result_projection` 新增 `recent_domain_events`
|
||||
- 中央 ingest `detect_result_projection` 时开始尝试把逐条事件写入 `detect_run_events`
|
||||
- 增加了 `import_fingerprint` 去重
|
||||
- 新增最小单测
|
||||
- 已重启中央 `domaincheck-api`
|
||||
|
||||
## 已完成验证
|
||||
|
||||
已完成:
|
||||
|
||||
- `python3 -m py_compile`
|
||||
- `python -m unittest tests.test_sync_record_service tests.test_sync_push_service`
|
||||
- 中央 `domaincheck-api` 重启成功
|
||||
|
||||
## 当前真实状态
|
||||
|
||||
要区分两层:
|
||||
|
||||
### 1. 代码闭环
|
||||
|
||||
这一层已经补上:
|
||||
|
||||
- 大陆侧投影格式支持逐条事件
|
||||
- 中央视角 ingest 支持把逐条事件落入 `detect_run_events`
|
||||
|
||||
### 2. 真实运行闭环
|
||||
|
||||
这一层还差最后一步:
|
||||
|
||||
- 大陆节点必须拉到最新代码
|
||||
- 然后继续运行同步
|
||||
- 中央才能真正看到 mainland `domain_*`
|
||||
|
||||
## 当前最高优先级
|
||||
|
||||
唯一最高优先级:
|
||||
|
||||
- 让大陆节点拉最新代码后,验证 `recent_domain_events -> central detect_run_events`
|
||||
|
||||
## 下一轮只做什么
|
||||
|
||||
下一轮只做以下最小动作:
|
||||
|
||||
1. 在大陆节点确认当前代码已是最新
|
||||
2. 触发或等待新的 `detect_result_projection`
|
||||
3. 检查中央最新 `detect_result_ingest.payload.projection.recent_domain_events`
|
||||
4. 检查中央 `detect_run_events` 是否出现:
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
- 对应 `domain_started/domain_completed/domain_failed/domain_blacklisted`
|
||||
|
||||
## 下一轮不要做什么
|
||||
|
||||
继续不要做:
|
||||
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强
|
||||
- 发布动作
|
||||
- item 级最终回写
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
## 给下一轮的最小任务卡
|
||||
|
||||
```text
|
||||
任务名:J1-大陆逐条结果同步前置批(验证轮)
|
||||
|
||||
目标:
|
||||
1. 确认大陆节点已拉到最新代码
|
||||
2. 确认最新 detect_result_projection 已含 recent_domain_events
|
||||
3. 确认中央 detect_run_events 已出现 mainland domain_* 事件
|
||||
|
||||
完成判定:
|
||||
1. detect_result_ingest.payload.projection.recent_domain_events 非空
|
||||
2. detect_run_events 中可查询到 mainland-controller-01 / mainland-worker-01 的 domain_* 事件
|
||||
|
||||
边界:
|
||||
1. 不做 item 级回写
|
||||
2. 不做新页面
|
||||
3. 不做控制面扩展
|
||||
```
|
||||
|
||||
## 一句话结论
|
||||
|
||||
这轮已经把“中央如何接并落大陆逐条事件”的代码闭环补上了;下一轮只差让大陆节点跑到这版代码并验证真实事件进中央。
|
||||
66
docs/ops_center_runtime/HANDOFF_20260419_0257.md
Normal file
66
docs/ops_center_runtime/HANDOFF_20260419_0257.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# HANDOFF 2026-04-19 02:57
|
||||
|
||||
## 本轮新增完成
|
||||
|
||||
在上一轮“中央可接收并落库逐条事件”基础上,这一轮又补了最后一个自动触发点:
|
||||
|
||||
- `app.sync_agent` 每个 tick 会自动产出 `detect_result_projection`
|
||||
- 不再依赖有人去访问 mainland 检测页面
|
||||
|
||||
## 当前真实判断
|
||||
|
||||
当前看到的中央证据是:
|
||||
|
||||
- `mainland-controller-01` / `mainland-worker-01` 心跳正常
|
||||
- `runtime_ingest.updated_at` 已刷新到 `2026-04-19 02:55:36`
|
||||
- `detect_result_ingest.updated_at` 仍停留在 `2026-04-17 16:57:32`
|
||||
- `detect_run_events` 里仍没有 mainland `domain_*`
|
||||
|
||||
这说明:
|
||||
|
||||
- mainland 同步链是活的
|
||||
- 但 अभी还没有跑到“自动产 detect_result_projection”的新代码
|
||||
|
||||
## 这轮后的唯一剩余动作
|
||||
|
||||
现在只剩一个最小外部动作:
|
||||
|
||||
1. mainland 相关节点拉最新代码
|
||||
2. 重启 `domaincheck-sync-agent`
|
||||
|
||||
建议最小命令:
|
||||
|
||||
```bash
|
||||
systemctl restart domaincheck-sync-agent
|
||||
sleep 3
|
||||
systemctl status domaincheck-sync-agent --no-pager -l
|
||||
journalctl -u domaincheck-sync-agent -n 80 --no-pager
|
||||
```
|
||||
|
||||
如果 service 名不是这个,再按机器当前实际 service 名执行。
|
||||
|
||||
## 重启后我下一轮只查什么
|
||||
|
||||
下一轮只查这 3 件事:
|
||||
|
||||
1. 最新 `detect_result_ingest.payload.projection.recent_domain_events` 是否非空
|
||||
2. `detect_run_events` 是否出现 mainland `domain_started/domain_completed/domain_failed/domain_blacklisted`
|
||||
3. `detect/job/active` 的 `recent_events` 是否开始出现 imported mainland 逐条事件
|
||||
|
||||
## 继续不要做什么
|
||||
|
||||
- 不做 item 级最终回写
|
||||
- 不做新页面
|
||||
- 不做控制面增强
|
||||
- 不做发布动作
|
||||
|
||||
## 推荐模型与推理等级
|
||||
|
||||
继续推荐:
|
||||
|
||||
- `GPT-5.4`
|
||||
- `high`
|
||||
|
||||
## 一句话结论
|
||||
|
||||
现在代码链路已经补到“mainland 拉新并重启 sync agent 后就该自动把逐条结果送进中央”;下一轮只差验证真正贯通。
|
||||
68
docs/ops_center_runtime/HANDOFF_20260419_0300.md
Normal file
68
docs/ops_center_runtime/HANDOFF_20260419_0300.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# HANDOFF 2026-04-19 03:00
|
||||
|
||||
## 本轮做了什么
|
||||
|
||||
本轮没有进入新实现,只做了中央只读复查:
|
||||
|
||||
1. 复查 mainland `detect_result_ingest`
|
||||
2. 复查 mainland `runtime_ingest`
|
||||
3. 复查中央 `detect_run_events`
|
||||
|
||||
## 本轮结论
|
||||
|
||||
结论已经非常明确:
|
||||
|
||||
- mainland 同步链是活的
|
||||
- 但 mainland 仍未真正跑到新版 `domaincheck-sync-agent`
|
||||
|
||||
## 证据
|
||||
|
||||
### 1. `runtime_ingest` 仍在刷新
|
||||
|
||||
- 最新 `updated_at` 到 `2026-04-19 02:59:12`
|
||||
|
||||
### 2. `detect_result_ingest` 没有刷新
|
||||
|
||||
- 最新 `updated_at` 仍停在 `2026-04-17 16:57:32`
|
||||
|
||||
### 3. mainland `domain_*` 仍为 0
|
||||
|
||||
- `detect_run_events`
|
||||
- mainland `domain_started/domain_completed/domain_failed/domain_blacklisted`
|
||||
- 当前 `count = 0`
|
||||
|
||||
## 当前唯一剩余动作
|
||||
|
||||
现在只剩一个外部动作:
|
||||
|
||||
1. mainland 节点拉最新代码
|
||||
2. 重启 `domaincheck-sync-agent`
|
||||
|
||||
建议直接执行:
|
||||
|
||||
```bash
|
||||
git pull
|
||||
systemctl restart domaincheck-sync-agent
|
||||
sleep 3
|
||||
systemctl status domaincheck-sync-agent --no-pager -l
|
||||
journalctl -u domaincheck-sync-agent -n 80 --no-pager
|
||||
```
|
||||
|
||||
## 你执行完后,我下一轮只查什么
|
||||
|
||||
我下一轮只查这 3 个结果:
|
||||
|
||||
1. `detect_result_ingest.payload.projection.recent_domain_events` 是否非空
|
||||
2. `detect_run_events` 是否出现 mainland `domain_*`
|
||||
3. `detect/job/active` 的 `recent_events` 是否开始出现 imported mainland 逐条事件
|
||||
|
||||
## 继续不要做什么
|
||||
|
||||
- 不做 item 级最终回写
|
||||
- 不做新页面
|
||||
- 不做控制面增强
|
||||
- 不做发布动作
|
||||
|
||||
## 一句话结论
|
||||
|
||||
现在代码已经补完,卡点不在中央,卡点只剩 mainland 端还没切到新版 `domaincheck-sync-agent`。
|
||||
96
docs/ops_center_runtime/HANDOFF_20260419_0308.md
Normal file
96
docs/ops_center_runtime/HANDOFF_20260419_0308.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# HANDOFF 2026-04-19 03:08
|
||||
|
||||
## 本轮做了什么
|
||||
|
||||
本轮没有进入新实现,只做了最小链路核查:
|
||||
|
||||
1. 复查中央 `detect/job/active`
|
||||
2. 复查中央 `ops/nodes`
|
||||
3. 复查 `go-live-summary` / `stack-diagnosis` / `release-launchpad`
|
||||
4. 复查最新 `onboarding.acceptance`
|
||||
5. 通过远端 Agent 对 `mainland-controller-01` 执行:
|
||||
- `service.status`
|
||||
- `logs.collect`
|
||||
目标服务:`domaincheck-sync-agent`
|
||||
|
||||
## 本轮结论
|
||||
|
||||
当前状态已经进一步推进:
|
||||
|
||||
- 检测任务在跑
|
||||
- 节点接管在跑
|
||||
- 最新 acceptance 已成功
|
||||
- `mainland-controller-01` 的 `domaincheck-sync-agent` 已重启成功
|
||||
- 重启后首轮已把 mainland 逐条结果推回中央
|
||||
|
||||
## 关键证据
|
||||
|
||||
### 1. 检测任务确实在跑
|
||||
|
||||
- 活跃任务:`detect-20260417170546-96023e`
|
||||
- 参与节点:
|
||||
- `mainland-worker-01`
|
||||
- `mainland-controller-01`
|
||||
- `overseas-control-01`
|
||||
|
||||
### 2. 最新 acceptance 已成功
|
||||
|
||||
- `pbr-9ce5c85f17`:成功
|
||||
- `pbr-389abd618c`:成功
|
||||
|
||||
说明:
|
||||
|
||||
- 接管验收不再是当前唯一主阻塞
|
||||
|
||||
### 3. sync-agent 服务已重启到新进程
|
||||
|
||||
远端只读结果:
|
||||
|
||||
- 服务:`domaincheck-sync-agent`
|
||||
- 状态:`active (running)`
|
||||
- 启动时间:`2026-04-19 16:09:52 CST`
|
||||
- 运行命令:
|
||||
- `/opt/domaincheck/domainCheck/.venv/bin/python -m app.sync_agent`
|
||||
|
||||
### 4. 重启后首轮结果投影已推送成功
|
||||
|
||||
最新日志显示:
|
||||
|
||||
- `detect_result_projection`
|
||||
- `batch_count = 1`
|
||||
- `success_count = 1`
|
||||
- `event_import.imported_count = 10`
|
||||
|
||||
### 5. 中央 mainland 逐条结果已出现
|
||||
|
||||
- 新增 `detect_result_ingest`
|
||||
- `id = 5382`
|
||||
- `created_at = 2026-04-19 03:10:14`
|
||||
- 近期 mainland `domain_*`
|
||||
- `count = 10`
|
||||
|
||||
## 下一轮唯一剩余动作
|
||||
|
||||
下一轮不要发散实现,只做持续性复查:
|
||||
|
||||
1. `/api/v1/runtime/sync-summary`
|
||||
2. `/api/v1/detect/job/active`
|
||||
3. mainland `domain_started/domain_completed/domain_failed/domain_blacklisted`
|
||||
4. `/api/v1/ops/go-live-summary`
|
||||
5. `/api/v1/ops/stack-diagnosis`
|
||||
|
||||
重点判断:
|
||||
|
||||
- mainland `domain_*` 是否持续增长
|
||||
- 总检 attention 是否已主要退化为历史残留
|
||||
|
||||
## 继续不要做什么
|
||||
|
||||
- 不做新页面
|
||||
- 不做控制面增强
|
||||
- 不做发布动作
|
||||
- 不做 item 级最终回写
|
||||
|
||||
## 一句话结论
|
||||
|
||||
`mainland-controller-01` 的 `domaincheck-sync-agent` 重启后,逐条结果同步已经打通;当前工作重点从“修链路”切换到“验证持续性与上线签收口径”。
|
||||
128
docs/ops_center_runtime/HANDOFF_20260419_0318.md
Normal file
128
docs/ops_center_runtime/HANDOFF_20260419_0318.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# HANDOFF 2026-04-19 03:18
|
||||
|
||||
## 本轮做了什么
|
||||
|
||||
本轮没有进入新实现,只做了运行态只读复查:
|
||||
|
||||
1. 对比一个完整 40 秒观察窗口前后的:
|
||||
- `/api/v1/detect/job/active`
|
||||
- `/api/v1/runtime/sync-summary`
|
||||
2. 复查中央 `detect_run_events`
|
||||
3. 复查:
|
||||
- `/api/v1/ops/go-live-summary`
|
||||
- `/api/v1/ops/stack-diagnosis`
|
||||
- `/api/v1/ops/activity-stream`
|
||||
4. 复查节点现场日志:
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
|
||||
## 本轮结论
|
||||
|
||||
这轮结论要纠偏:
|
||||
|
||||
- 接管链路基本完成
|
||||
- 同步链路已经打通过一次
|
||||
- 但检测执行面当前没有继续出新结果
|
||||
|
||||
因此当前主阻塞不再是“接管/同步未通”,而是:
|
||||
|
||||
- 检测执行停滞
|
||||
- 外部站点依赖或代理池可用性异常
|
||||
|
||||
## 关键证据
|
||||
|
||||
### 1. 三台节点都在参与,但近窗没有吞吐
|
||||
|
||||
活跃任务仍是:
|
||||
|
||||
- `detect-20260417170546-96023e`
|
||||
|
||||
参与节点:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
- `overseas-control-01`
|
||||
|
||||
但 40 秒观察窗口前后完全一致:
|
||||
|
||||
- `progress_percent = 2.1`
|
||||
- `completed = 21`
|
||||
- `running = 14`
|
||||
- `claimed = 34`
|
||||
- `pending = 931`
|
||||
|
||||
### 2. mainland 逐条结果没有继续增长
|
||||
|
||||
中央查询结果:
|
||||
|
||||
- mainland `domain_*` 事件数仍为 `10`
|
||||
- 最新 mainland `detect_result_ingest` 仍是:
|
||||
- `id = 5382`
|
||||
- `created_at = 2026-04-19 03:10:14`
|
||||
|
||||
说明:
|
||||
|
||||
- 首批同步成功过
|
||||
- 但后续没有继续流入新结果
|
||||
|
||||
### 3. go-live 与 stack 口径已经比之前更完整
|
||||
|
||||
当前:
|
||||
|
||||
- `remote_access_ready = 3/3`
|
||||
- `log_sync_state = full_capture`
|
||||
- `go_live_status = attention`
|
||||
|
||||
这说明:
|
||||
|
||||
- 基础运维骨架已经起来
|
||||
- attention 现在不能只归因于接管未完成
|
||||
|
||||
### 4. controller 现场日志已直接指向代理/外部依赖问题
|
||||
|
||||
`mainland-controller-01` 现场日志显示:
|
||||
|
||||
- `当前可用代理数: 0`
|
||||
- `最近结果: 刷新成功,可用 0 个`
|
||||
- 检测链包含:
|
||||
- 注册
|
||||
- 百度 site
|
||||
- 360 site
|
||||
- 站长之家
|
||||
- 爱站
|
||||
- 时光机
|
||||
|
||||
### 5. 页面上的“外部站点异常”与现场证据一致
|
||||
|
||||
从当前现场判断:
|
||||
|
||||
- 这不是页面误报
|
||||
- 而是执行面确实卡在外部依赖/代理可用性上
|
||||
|
||||
## 下一轮唯一应该做什么
|
||||
|
||||
下一轮不要发散实现,只做 `J2-检测执行停滞收口批`:
|
||||
|
||||
1. 继续只读确认:
|
||||
- `/api/v1/detect/job/active`
|
||||
- `/api/v1/runtime/sync-summary`
|
||||
- `/api/v1/ops/activity-stream`
|
||||
- `/api/v1/ops/nodes/{node_code}/scene-log`
|
||||
2. 必要时补一轮:
|
||||
- `domaincheck-worker` 运行日志取证
|
||||
3. 只判断三件事:
|
||||
- 是否仍然 `近窗吞吐 0`
|
||||
- 是否仍然 `可用代理数 0`
|
||||
- 是否仍然没有新 `domain_*` 事件
|
||||
|
||||
## 现在不要做什么
|
||||
|
||||
- 不做新页面
|
||||
- 不做控制面增强
|
||||
- 不做发布动作
|
||||
- 不做 item 级最终回写
|
||||
- 不把当前状态误判成“已稳定可签收”
|
||||
|
||||
## 一句话结论
|
||||
|
||||
当前项目已经不是“接不管、看不见、不同步”,而是“接管和同步都基本打通了,但检测执行卡在外部站点/代理可用性问题上,导致任务挂起且没有继续产出”。
|
||||
117
docs/ops_center_runtime/HANDOFF_20260419_0324.md
Normal file
117
docs/ops_center_runtime/HANDOFF_20260419_0324.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# HANDOFF 2026-04-19 03:24
|
||||
|
||||
## 本轮做了什么
|
||||
|
||||
本轮没有进入新实现,只做了执行面根因收紧:
|
||||
|
||||
1. 继续观察活跃检测任务是否前进
|
||||
2. 继续观察 mainland `domain_*` 是否增长
|
||||
3. 通过正式 `ops job` 远端采集:
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
的 `domaincheck-worker` 日志
|
||||
4. 再盯一个 35 秒窗口,看 full capture 打开后,源日志时间是否继续前进
|
||||
|
||||
## 本轮结论
|
||||
|
||||
这轮已经能把问题说得更准:
|
||||
|
||||
- 不是“日志没回来”
|
||||
- 不是“全量日志没开”
|
||||
- 而是日志链路已经通了,但执行进程没有继续产生日志
|
||||
|
||||
当前第一主阻塞:
|
||||
|
||||
- `mainland-controller-01` 代理池可用数为 0
|
||||
|
||||
次级问题:
|
||||
|
||||
- `mainland-worker-01` 的时光机依赖异常会降级继续执行
|
||||
|
||||
## 关键证据
|
||||
|
||||
### 1. full capture 是开的,但源日志没继续前进
|
||||
|
||||
当前:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `capture_at = 2026-04-19 03:21:59`
|
||||
- 源日志时间仍停在 `Apr 19 01:00:23`
|
||||
- `mainland-worker-01`
|
||||
- `capture_at = 2026-04-19 03:22:01`
|
||||
- 源日志时间仍停在 `Apr 19 02:19:56`
|
||||
|
||||
35 秒后再次复查:
|
||||
|
||||
- `capture_at` 没变化
|
||||
- `source_msg` 也没变化
|
||||
|
||||
说明:
|
||||
|
||||
- 日志回传本身不是主问题
|
||||
- 执行进程这段时间没有继续产生日志
|
||||
|
||||
### 2. controller 代理源能拉到数据,但所有代理都验不过
|
||||
|
||||
`mainland-controller-01` 的 `domaincheck-worker` 日志显示:
|
||||
|
||||
- 6 个代理源都能拉到原始代理
|
||||
- 抽样验证 24 个代理后:
|
||||
- `代理池刷新完成,共 0 个可用代理`
|
||||
- 失败集中在:
|
||||
- `ProxyError@https://m.baidu.com`
|
||||
- `Unable to connect to proxy`
|
||||
- `ConnectTimeoutError`
|
||||
|
||||
说明:
|
||||
|
||||
- 不是代理接口挂了
|
||||
- 是代理名单本身不可用
|
||||
|
||||
### 3. worker 还能跑,但时光机依赖异常会降级
|
||||
|
||||
`mainland-worker-01` 的 `domaincheck-worker` 日志显示:
|
||||
|
||||
- `时光机检测 外部依赖异常,步骤降级继续执行`
|
||||
- 同时仍可见:
|
||||
- `域名检测完成`
|
||||
- 收到新的控制消息时:
|
||||
- `收到启动检测指令,但检测任务已在运行,忽略重复启动`
|
||||
|
||||
说明:
|
||||
|
||||
- worker 不是完全不可用
|
||||
- 时光机异常存在,但不是最核心阻塞
|
||||
|
||||
### 4. 活跃任务仍然没有前进
|
||||
|
||||
- `progress_percent = 2.1`
|
||||
- `completed = 21`
|
||||
- `running = 14`
|
||||
- `claimed = 34`
|
||||
- `pending = 931`
|
||||
|
||||
并且 mainland `domain_*` 仍固定在 `10`
|
||||
|
||||
## 下一轮唯一应该做什么
|
||||
|
||||
继续只做 `J2-检测执行停滞收口批`:
|
||||
|
||||
1. 不扩功能
|
||||
2. 不改页面
|
||||
3. 只围绕 controller 代理池问题取证和恢复验证
|
||||
|
||||
唯一要确认的是:
|
||||
|
||||
- controller 代理池是否仍然 `可用 0`
|
||||
- 一旦代理恢复,`domain_*` 是否会继续增长
|
||||
|
||||
## 现在不要做什么
|
||||
|
||||
- 不把问题继续泛化成“外部站点都异常”
|
||||
- 不把问题误判为“日志回传没开”
|
||||
- 不做新页面、新模块、发布动作
|
||||
|
||||
## 一句话结论
|
||||
|
||||
当前项目不是“接管失败”,也不是“日志没回来”,而是“controller 侧拉到了代理名单,但代理全部校验失败,导致检测执行没有继续产生新结果”。
|
||||
122
docs/ops_center_runtime/HANDOFF_20260419_0332.md
Normal file
122
docs/ops_center_runtime/HANDOFF_20260419_0332.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# HANDOFF 2026-04-19 03:32
|
||||
|
||||
## 本轮做了什么
|
||||
|
||||
这轮没有扩功能,没有进新页面,也没有碰发布动作。
|
||||
|
||||
只做了两件事:
|
||||
|
||||
1. 把检测执行停滞的判断继续收紧
|
||||
2. 对 worker 控制消息链补上最小代码修复
|
||||
|
||||
## 当前最新判断
|
||||
|
||||
当前不是接管问题,也不是日志回传问题。
|
||||
|
||||
当前真实状态是:
|
||||
|
||||
- `remote_access_ready = 3/3`
|
||||
- `log_sync_state = full_capture`
|
||||
- 大陆首批结果同步已经成功过
|
||||
- 但检测任务没有持续前进
|
||||
|
||||
这个停滞目前有两层原因:
|
||||
|
||||
### 第一层:已确认的现场阻塞
|
||||
|
||||
- `mainland-controller-01` 代理池刷新后 `0 available`
|
||||
- 代理源可以拉到原始代理
|
||||
- 但抽样校验全部失败
|
||||
|
||||
这会直接影响 controller 侧吞吐。
|
||||
|
||||
### 第二层:刚补好的代码风险
|
||||
|
||||
之前存在一个运行态风险:
|
||||
|
||||
- 控制面发 `start_detection`
|
||||
- Redis `publish` 成功
|
||||
- 但 worker 如果漏收 pubsub 消息
|
||||
- pending 指令可能不会在运行态被再次消费
|
||||
|
||||
这会造成:
|
||||
|
||||
- 页面像是发起成功了
|
||||
- 但 worker 不一定真的继续推进
|
||||
|
||||
现在这处代码缺口已经补上,但还没有完成线上部署验证。
|
||||
|
||||
## 本轮代码修复
|
||||
|
||||
### 1. `worker_control_service`
|
||||
|
||||
文件:
|
||||
|
||||
- `domain-api/app/services/worker_control_service.py`
|
||||
|
||||
修复:
|
||||
|
||||
- 每条 worker 控制消息补 `request_id`
|
||||
- Redis `publish` 和 pending fallback 复用同一条消息体
|
||||
|
||||
### 2. `detect_worker`
|
||||
|
||||
文件:
|
||||
|
||||
- `domainCheck/detect_worker.py`
|
||||
|
||||
修复:
|
||||
|
||||
- 运行态心跳里周期性补偿消费 pending 控制消息
|
||||
- 真正收到控制消息后,按 `request_id` 清理 pending
|
||||
|
||||
### 3. 新增测试
|
||||
|
||||
文件:
|
||||
|
||||
- `domain-api/tests/test_worker_control_service.py`
|
||||
|
||||
验证目标:
|
||||
|
||||
- 确保 `send_worker_command(...)` 会生成并持久化 `request_id`
|
||||
|
||||
## 本地验证结果
|
||||
|
||||
已通过:
|
||||
|
||||
```bash
|
||||
PYTHONPATH=/www/wwwroot/getDomain/domain-api /opt/domaincheck/domainCheck/.venv/bin/python -m unittest domain-api/tests/test_worker_control_service.py
|
||||
python -m py_compile domainCheck/detect_worker.py domain-api/app/services/worker_control_service.py
|
||||
```
|
||||
|
||||
## 下一轮唯一该做什么
|
||||
|
||||
下一轮不要发散,只做最小部署验证:
|
||||
|
||||
1. 大陆节点拉最新代码
|
||||
2. 重启 `domaincheck-worker`
|
||||
3. 复查:
|
||||
- `/api/v1/detect/job/active`
|
||||
- `/api/v1/runtime/sync-summary`
|
||||
- controller / worker `scene-log`
|
||||
- 必要时再采集 `domaincheck-worker` 日志
|
||||
4. 只判断两件事:
|
||||
- 修复上线后,检测任务是否恢复推进
|
||||
- 如果仍不推进,是否只剩 controller 代理池 `0 available` 这个现场阻塞
|
||||
|
||||
## 现在不要做什么
|
||||
|
||||
- 不做新页面
|
||||
- 不做新模块
|
||||
- 不做控制面增强
|
||||
- 不做发布动作
|
||||
- 不把问题再泛化成“日志没回来”或“接管没完成”
|
||||
|
||||
## 一句话结论
|
||||
|
||||
当前最准确的状态是:
|
||||
|
||||
- 接管和同步基本已经闭合
|
||||
- 检测执行停滞仍然存在
|
||||
- worker 控制消息补偿链已补代码
|
||||
- 下一步只剩“拉代码重启 worker 后看任务是否恢复推进”
|
||||
142
docs/ops_center_runtime/HANDOFF_20260419_0341.md
Normal file
142
docs/ops_center_runtime/HANDOFF_20260419_0341.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# HANDOFF 2026-04-19 03:41
|
||||
|
||||
## 本轮做了什么
|
||||
|
||||
这轮没有扩功能,只沿着检测执行停滞的最小路径继续推进,完成了:
|
||||
|
||||
1. 将提交 `c33f4f1` 部署到:
|
||||
- `mainland-worker-01`
|
||||
- `mainland-controller-01`
|
||||
2. 重启两台大陆节点的 `domaincheck-worker`
|
||||
3. 验证 worker 控制消息补偿链是否在线上生效
|
||||
4. 排查 controller 为什么没有像 worker 一样顺滑接入控制链
|
||||
5. 修正 controller 运行环境中的 Redis 密码漂移
|
||||
6. 再次下发 `detect/start`,确认 controller 真正收到并执行新启动指令
|
||||
7. 再观察中央进度、recent events、sync-summary 是否继续前进
|
||||
|
||||
## 本轮关键结果
|
||||
|
||||
### 1. worker 控制消息补偿链已经线上生效
|
||||
|
||||
`mainland-worker-01` 明确出现:
|
||||
|
||||
- `发现待执行 Worker 控制指令`
|
||||
- `已接受检测启动指令`
|
||||
- `开始执行远程检测任务`
|
||||
|
||||
这说明:
|
||||
|
||||
- 上一轮代码修复不是只在本地成立
|
||||
- pending 控制消息补偿消费链已经在线上闭合
|
||||
|
||||
### 2. controller 原先确实存在运行环境漂移
|
||||
|
||||
`mainland-controller-01` 的 `/etc/default/domaincheck-worker` 原始状态:
|
||||
|
||||
- `REDIS_HOST=127.0.0.1`
|
||||
- `REDIS_PORT=6379`
|
||||
- `REDIS_PASSWORD=`
|
||||
|
||||
对应日志:
|
||||
|
||||
- `Authentication required`
|
||||
- `maximum recursion depth exceeded while calling a Python object`
|
||||
|
||||
这说明:
|
||||
|
||||
- controller 不是没重启
|
||||
- 也不是代码没生效
|
||||
- 而是本机 Redis 开了鉴权,但 worker 环境文件没带密码
|
||||
|
||||
### 3. controller 已完成最小修正并重新接上控制链
|
||||
|
||||
本轮已把 controller 的 `REDIS_PASSWORD` 补为:
|
||||
|
||||
- `Qazwe123..`
|
||||
|
||||
修正后再次重启,日志变为:
|
||||
|
||||
- `Redis 连接成功: 127.0.0.1:6379`
|
||||
- `已接受检测启动指令`
|
||||
- `开始执行远程检测任务`
|
||||
|
||||
之后再次触发 `/api/v1/detect/start`,controller 又出现:
|
||||
|
||||
- `发现待执行 Worker 控制指令`
|
||||
- `收到启动检测指令,但检测任务已在运行,忽略重复启动`
|
||||
|
||||
这说明:
|
||||
|
||||
- controller 的控制链也已经恢复
|
||||
- 现在不再是 Redis 断链问题
|
||||
|
||||
### 4. 当前唯一剩余阻塞已经进一步收紧
|
||||
|
||||
controller 当前最新现场日志反复出现:
|
||||
|
||||
- `代理已启用,但当前无可用代理`
|
||||
|
||||
这意味着当前唯一剩余主阻塞已经收紧为:
|
||||
|
||||
- `mainland-controller-01` 代理池没有可用代理
|
||||
|
||||
## 中央侧当前表现
|
||||
|
||||
正向信号:
|
||||
|
||||
- `remote_access_ready = 3/3`
|
||||
- `log_sync_state = full_capture`
|
||||
- `runtime/sync-summary` 最新记录继续增长到 `5491`
|
||||
- recent events 已刷新到更晚时间
|
||||
- `mainland-worker-01` 最新 domain_started 已推进到 `2026-04-19 16:37:00`
|
||||
|
||||
仍未恢复的信号:
|
||||
|
||||
- `items_completed = 21`
|
||||
- `items_claimed = 34`
|
||||
- `items_running = 14`
|
||||
- `items_pending = 931`
|
||||
- 短观察窗口内没有继续上涨
|
||||
|
||||
这说明:
|
||||
|
||||
- 控制链和同步链已经恢复到更健康状态
|
||||
- 但执行吞吐还没有恢复成“持续出结果”
|
||||
|
||||
## 当前结论
|
||||
|
||||
当前最准确的判断是:
|
||||
|
||||
- 接管问题:基本已闭合
|
||||
- 日志回传问题:已闭合
|
||||
- worker 控制消息漏收问题:已闭合
|
||||
- controller Redis 环境漂移:已闭合
|
||||
- 当前唯一剩余阻塞:`mainland-controller-01` 代理池无可用代理
|
||||
|
||||
## 下一轮唯一应该做什么
|
||||
|
||||
下一轮不要发散,只做 controller 代理收口:
|
||||
|
||||
1. 继续观察 controller `domaincheck-worker` 日志
|
||||
2. 重点看是否从:
|
||||
- `代理已启用,但当前无可用代理`
|
||||
转成:
|
||||
- 至少有 `1+` 可用代理
|
||||
3. 继续复查:
|
||||
- `/api/v1/detect/job/active`
|
||||
- `/api/v1/runtime/sync-summary`
|
||||
- `/api/v1/ops/nodes`
|
||||
4. 只判断一件事:
|
||||
- controller 代理恢复后,`items_completed` 是否继续增长
|
||||
|
||||
## 现在不要做什么
|
||||
|
||||
- 不扩页面
|
||||
- 不做新模块
|
||||
- 不做控制面增强
|
||||
- 不误判成“接管还没好”
|
||||
- 不继续围绕 worker 控制消息链做重复修复
|
||||
|
||||
## 一句话结论
|
||||
|
||||
这轮已经把系统从“控制链也有缺口”推进到了“控制链已恢复、只剩 controller 代理池无可用代理”。
|
||||
66
docs/ops_center_runtime/HANDOFF_20260419_0426.md
Normal file
66
docs/ops_center_runtime/HANDOFF_20260419_0426.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# HANDOFF 2026-04-19 04:26 CST
|
||||
|
||||
## 本轮完成
|
||||
|
||||
- 已修复 `runtime/status` 兼容层,恢复旧字段:
|
||||
- `api_online`
|
||||
- `worker_online`
|
||||
- `cluster_summary`
|
||||
- `thread_count`
|
||||
- 已重启中央 `domaincheck-api`
|
||||
- 已重新构建 `domain-web` 前端静态包
|
||||
- 已确认大陆双节点日志回传同时进入中央:
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
- 已确认大陆两台线程配置真实生效:
|
||||
- `mainland-controller-01 -> 100`
|
||||
- `mainland-worker-01 -> 50`
|
||||
|
||||
## 当前真实状态
|
||||
|
||||
- `/api/v1/runtime/status`
|
||||
- `api_online = true`
|
||||
- `worker_online = true`
|
||||
- `cluster_summary.online_worker_nodes = 3`
|
||||
- `/api/v1/detect/status`
|
||||
- `progress.pending = 163815`
|
||||
- `progress.completed = 51`
|
||||
- `progress.running = 10`
|
||||
- `remote_log_line_count = 240`
|
||||
- `remote_log_node_count = 2`
|
||||
- 近 5 分钟中央 `detect_debug_events`
|
||||
- `mainland-controller-01 -> worker_log`
|
||||
- `mainland-worker-01 -> worker_log`
|
||||
|
||||
## 当前结论
|
||||
|
||||
- “API 离线 / 本机 Worker 离线 / 有效执行节点 0” 已不是后端真实状态
|
||||
- “全量日志没回来” 已不是后端真实状态
|
||||
- “100/50 并发没有下发” 也不是后端真实状态
|
||||
- 当前剩余主问题已经收紧为:
|
||||
- 检测实际吞吐仍偏低
|
||||
- 代理可用性与任务分发节奏仍在限制体感并发
|
||||
|
||||
## 下一轮唯一任务
|
||||
|
||||
只做:`J2-检测执行吞吐收口`
|
||||
|
||||
顺序:
|
||||
|
||||
1. 强刷浏览器,确认新前端包已经生效
|
||||
2. 复查 Detect 页是否恢复:
|
||||
- API 在线
|
||||
- 本机 Worker 在线
|
||||
- 有效执行节点 > 0
|
||||
- 日志窗口出现双节点日志
|
||||
3. 若显示已恢复,再继续只排查:
|
||||
- 为什么实际执行吞吐仍低于 `100/50`
|
||||
- 重点看代理可用性、任务领取节奏、线程实际活跃数
|
||||
|
||||
## 现在不要做
|
||||
|
||||
- 不扩新页面
|
||||
- 不扩控制面功能
|
||||
- 不新增专题文档
|
||||
- 不进入发布动作
|
||||
- 不切新大方向
|
||||
104
docs/ops_center_runtime/HANDOFF_20260419_1334.md
Normal file
104
docs/ops_center_runtime/HANDOFF_20260419_1334.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# HANDOFF 2026-04-19 13:34 CST
|
||||
|
||||
## 本轮完成
|
||||
|
||||
- 已修复 controller `sync-agent pull_tasks` 只导 `domains`、不导本地执行队列的问题
|
||||
- 已让 controller 持续创建本地镜像任务:
|
||||
- `sync-overseas-7380`
|
||||
- `sync-overseas-7383`
|
||||
- `sync-overseas-7392`
|
||||
- 后续批次持续增加
|
||||
- 已重启两台大陆 `domaincheck-worker`
|
||||
- 已确认两台大陆节点都进入真实任务队列:
|
||||
- `mainland-controller-01 -> 从任务队列获取到 800 个需要检测的域名`
|
||||
- `mainland-worker-01 -> 从任务队列获取到 400 个需要检测的域名`
|
||||
- 已修复 controller `runtime/detect_runs.json` 属主错误:
|
||||
- `root:root -> www:www`
|
||||
- 已确认 `runtime_projection` 最新同步恢复成功:
|
||||
- `sync_state = success`
|
||||
- `runtime_projection -> 投影推送成功`
|
||||
|
||||
## 当前真实状态
|
||||
|
||||
当前 `/api/v1/ops/nodes` 已显示:
|
||||
|
||||
- `remote_access_ready = 3`
|
||||
- `participating = 3`
|
||||
- `dispatch_active = 1`
|
||||
|
||||
大陆两台当前状态:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `agent_state = online_busy`
|
||||
- `detect_runtime.max_threads = 100`
|
||||
- `processed_recent = 115`
|
||||
- `processed_per_minute = 7.67`
|
||||
- `is_current_participant = true`
|
||||
- `mainland-worker-01`
|
||||
- `agent_state = online_busy`
|
||||
- `detect_runtime.max_threads = 50`
|
||||
- `processed_recent = 632`
|
||||
- `processed_per_minute = 42.13`
|
||||
- `is_current_participant = true`
|
||||
|
||||
## 当前结论
|
||||
|
||||
- 大陆两台不是“在线但没干活”
|
||||
- 而是已经进入真实镜像队列执行
|
||||
- `100/50` 并发也不是停留在配置层,而是已经开始真实消费任务
|
||||
- 后台运行态同步链已经恢复
|
||||
|
||||
现在剩余问题已经收敛到:
|
||||
|
||||
- Detect 页面主计数 / 日志窗口是否完全跟上新的运行态
|
||||
- 恢复后的吞吐是否能持续稳定
|
||||
|
||||
## 一个关键口径说明
|
||||
|
||||
当前大陆执行是“镜像队列”模式:
|
||||
|
||||
- 海外待检测批次先被 controller 拉回大陆本地
|
||||
- 在大陆本地形成 `sync-overseas-*` 的 `detect_jobs/detect_job_items`
|
||||
- 再由大陆 worker 真正执行
|
||||
- 运行态和结果再同步回海外
|
||||
|
||||
所以现在不要再只盯中央原生 `detect_job_items.claimed/running` 判断大陆有没有参与。
|
||||
|
||||
应该优先看:
|
||||
|
||||
- `/api/v1/ops/nodes`
|
||||
- `processed_recent`
|
||||
- `processed_per_minute`
|
||||
- `detect_runtime.active_threads/max_threads`
|
||||
|
||||
## 下一轮唯一任务
|
||||
|
||||
只做:`J2-页面口径与吞吐稳定性收口`
|
||||
|
||||
顺序:
|
||||
|
||||
1. 继续观察 Detect 页面
|
||||
2. 确认日志窗口是否已经持续刷新
|
||||
3. 确认主计数是否开始跟随最新运行态
|
||||
4. 继续观察 1 到 2 个同步周期内:
|
||||
- `mainland-controller-01 processed_recent`
|
||||
- `mainland-worker-01 processed_recent`
|
||||
- `processed_per_minute`
|
||||
5. 若页面仍不跟,优先修页面读取口径,不扩功能
|
||||
|
||||
## 现在不要做
|
||||
|
||||
- 不扩新页面
|
||||
- 不扩控制面功能
|
||||
- 不新增模块
|
||||
- 不进入发布动作
|
||||
- 不切新方向
|
||||
|
||||
## 推荐模型
|
||||
|
||||
- 当前最合适:`GPT-5.4 + high`
|
||||
|
||||
原因:
|
||||
|
||||
- 现在主要是收口、验证、局部修复
|
||||
- 需要稳定推理,但不需要切到超高
|
||||
109
docs/ops_center_runtime/HANDOFF_20260419_1348.md
Normal file
109
docs/ops_center_runtime/HANDOFF_20260419_1348.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# HANDOFF 2026-04-19 13:48 CST
|
||||
|
||||
## 本轮完成
|
||||
|
||||
- 已定位并修复 `domainCheck/detect_worker.py` 的上下文绑定缺口:
|
||||
- `sync-pull` 控制消息只有
|
||||
- `target_job_id`
|
||||
- `target_job_code`
|
||||
- 旧逻辑只读取
|
||||
- `job_id`
|
||||
- `job_code`
|
||||
- 结果是 `mainland-worker-01` 明明已经在跑,但 `current_job_id` 为空,`worker_log` 被整段短路
|
||||
- 已把补丁同步到:
|
||||
- `mainland-controller-01:/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
- `mainland-worker-01:/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
- 已在两台大陆机完成:
|
||||
- `python -m py_compile /opt/domaincheck/domainCheck/detect_worker.py`
|
||||
- `systemctl restart domaincheck-worker`
|
||||
|
||||
## 当前硬证据
|
||||
|
||||
### 1. mainland worker 日志回传已恢复
|
||||
|
||||
当前 `/api/v1/runtime/debug-events` 已出现:
|
||||
|
||||
- `mainland-worker-01 -> 开始执行检测任务,来源: redis-control`
|
||||
- `mainland-worker-01 -> 开始执行域名检测任务,正在加载配置`
|
||||
- `mainland-worker-01 -> 开始检测,正在刷新代理池`
|
||||
- `mainland-worker-01 -> 代理池刷新完成,共 7 个可用代理,来源链接 6 个,原始 265 个,验证 150 个`
|
||||
- `mainland-worker-01 -> 从任务队列获取到 400 个需要检测的域名`
|
||||
- `mainland-worker-01 -> 开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 1/50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 2/50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 3/50`
|
||||
|
||||
### 2. Detect 页面远端日志已经恢复双节点
|
||||
|
||||
当前 `/api/v1/detect/status` 已显示:
|
||||
|
||||
- `remote_log_node_count = 2`
|
||||
- `remote_log_nodes = ["mainland-controller-01", "mainland-worker-01"]`
|
||||
|
||||
最近日志样本:
|
||||
|
||||
- `mainland-worker-01 -> 从任务队列获取到 400 个需要检测的域名`
|
||||
- `mainland-worker-01 -> 开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 1/50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 2/50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 3/50`
|
||||
- `mainland-controller-01 -> 当前实际线程数量: 1/100 ... 3/100`
|
||||
|
||||
### 3. 三台节点仍保持参与态
|
||||
|
||||
当前 `/api/v1/ops/nodes` 摘要:
|
||||
|
||||
- `online = 3`
|
||||
- `agent_ready = 3`
|
||||
- `remote_access_ready = 3`
|
||||
- `participating = 3`
|
||||
- `dispatch_active = 1`
|
||||
|
||||
## 当前判断
|
||||
|
||||
已经闭合:
|
||||
|
||||
- 大陆节点真实执行
|
||||
- mainland worker 日志回传
|
||||
- Detect 页面远端日志窗口只显示 controller 的问题
|
||||
|
||||
仍待收口:
|
||||
|
||||
- Detect 页面主计数:
|
||||
- `pending = 163678`
|
||||
- `completed = 195`
|
||||
- `running = 3`
|
||||
- 当前这些主计数还没有和这轮大陆执行立即同步推进
|
||||
|
||||
因此当前剩余唯一主问题已经缩成:
|
||||
|
||||
- `detect_result_projection / 结果统计回推` 是否还存在延迟或聚合口径缺口
|
||||
|
||||
## 下一轮唯一任务
|
||||
|
||||
只做:`J2-结果计数收口批`
|
||||
|
||||
顺序:
|
||||
|
||||
1. 复查 `detect_result_projection` 最新推送是否持续成功
|
||||
2. 复查 mainland 共享库里 `sync-overseas-*` 任务的完成/失败数量是否增长
|
||||
3. 复查 overseas `detect/status.progress` 是否跟着推进
|
||||
4. 若日志继续推进但主计数仍不动,只修结果统计回推口径,不扩功能
|
||||
|
||||
## 现在不要做
|
||||
|
||||
- 不扩新页面
|
||||
- 不扩控制面功能
|
||||
- 不新增模块
|
||||
- 不切新方向
|
||||
- 不直接进入发布动作
|
||||
|
||||
## 推荐模型
|
||||
|
||||
- 当前继续用:`GPT-5.4 + high`
|
||||
|
||||
原因:
|
||||
|
||||
- 现在是收口型问题
|
||||
- 需要稳定排查与小范围补丁
|
||||
- 不需要切超高推理
|
||||
65
docs/ops_center_runtime/HANDOFF_20260419_1416.md
Normal file
65
docs/ops_center_runtime/HANDOFF_20260419_1416.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# HANDOFF 2026-04-19 14:16 CST
|
||||
|
||||
## 本轮完成
|
||||
|
||||
- 已修复 `detect_worker.py` 中“代理不足反向限制并发”的热路径:
|
||||
- 代理池不足时改为后台补货
|
||||
- 不再因为 `current_pool_size < thread_count/2` 而同步刷新、拖慢线程拉起
|
||||
- 已对线程创建阶段的运行态 / worker_log 做节流:
|
||||
- 不再每起一个线程就同步打一轮重日志
|
||||
- 避免远端日志回传本身把并发拉低
|
||||
- 已把上述修复部署到:
|
||||
- overseas 当前 live 运行目录 `/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
- repo 目录 `/www/wwwroot/getDomain/domainCheck/detect_worker.py`
|
||||
- `mainland-controller-01`
|
||||
- `mainland-worker-01`
|
||||
- 已补上“真实活跃检测线程计数”逻辑到代码文件中
|
||||
|
||||
## 当前结果
|
||||
|
||||
- `mainland-controller-01`
|
||||
- 海外后台当前已能看到:
|
||||
- `active_threads ~= 99~100`
|
||||
- `max_threads = 100`
|
||||
- 结论:
|
||||
- controller 的 `100` 并发已经真实跑起来
|
||||
- `mainland-worker-01`
|
||||
- 已重新接到新批次:
|
||||
- `source_record_id = 7679`
|
||||
- `target_job_code = sync-overseas-7679`
|
||||
- 最新日志已出现:
|
||||
- `开始执行域名检测任务`
|
||||
- `开始检测,刷新代理池`
|
||||
- `代理池刷新完成,共 23 个可用代理`
|
||||
- `开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- 本机进程线程量:
|
||||
- `152`
|
||||
- 结论:
|
||||
- worker 已重新进入真实执行
|
||||
- 但 overseas 后台对 `mainland-worker-01.active_threads/current_load` 的显示仍偏低
|
||||
|
||||
## 当前剩余问题
|
||||
|
||||
- 不是 controller 并发限制问题
|
||||
- 当前唯一剩余的运行面收口点是:
|
||||
- `mainland-worker-01` 的运行态上报 / 后台显示口径仍未完全对齐
|
||||
- 同时仍需继续观察:
|
||||
- Detect 页面主计数 `pending/completed/running`
|
||||
- 结果统计回推是否继续推进
|
||||
|
||||
## 下一轮建议
|
||||
|
||||
只继续做这两件事:
|
||||
|
||||
- 追 `mainland-worker-01` 的运行态采集链:
|
||||
- 为什么本机已进入新批次执行,但海外后台仍显示 `active_threads = 2`
|
||||
- 继续核对 Detect 主计数与结果回推:
|
||||
- 判断是统计延迟、投影延迟,还是任务结果尚未进入中央口径
|
||||
|
||||
不要做:
|
||||
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强
|
||||
- 发布动作
|
||||
- 新专题文档
|
||||
52
docs/ops_center_runtime/HANDOFF_20260419_1421.md
Normal file
52
docs/ops_center_runtime/HANDOFF_20260419_1421.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# HANDOFF_20260419_1421
|
||||
|
||||
更新时间:2026-04-19 14:21 CST
|
||||
|
||||
## 本轮完成
|
||||
|
||||
- 已完成检测页前端布局收口并上线验证:
|
||||
- `任务日志控制台` 已上移到事件列表前
|
||||
- `检测事件流` 已改成独立滚动区域
|
||||
- 事件表已限制最大高度,避免页面被长列表持续撑长
|
||||
- 已在真实线上静态目录重新构建:
|
||||
- `/www/wwwroot/getDomain/domain-web/dist`
|
||||
- 已验证线上 Nginx 实际指向该目录:
|
||||
- `/www/server/panel/vhost/nginx/domaincheck_3201.conf`
|
||||
- `/www/server/panel/vhost/nginx/domaincheck_152.53.37.118.conf`
|
||||
- 已验证本机线上端口可返回新页面:
|
||||
- `curl -I http://127.0.0.1:3201/ -> 200`
|
||||
- `index.html` 最后修改时间已更新到本轮
|
||||
- 新资源:
|
||||
- `/assets/DetectView-B9S1WMRT.js`
|
||||
- `/assets/DetectView-BFxMNRNR.css`
|
||||
|
||||
## 当前判断
|
||||
|
||||
- 这轮前端布局任务已经闭环
|
||||
- 如果浏览器仍显示旧布局,优先判断为缓存未刷新
|
||||
- 当前更值得继续追的不是页面结构,而是:
|
||||
- `mainland-worker-01` 运行态上报口径
|
||||
- Detect 主计数推进
|
||||
- 并发真实吞吐继续拉升
|
||||
|
||||
## 下一步建议
|
||||
|
||||
下一轮继续只围绕检测执行收口:
|
||||
|
||||
- 复核 `mainland-worker-01` 为什么本机线程已拉起,但后台 `active_threads/current_load` 仍偏低
|
||||
- 继续比对:
|
||||
- `/api/v1/detect/status`
|
||||
- `/api/v1/runtime/debug-events`
|
||||
- `/api/v1/ops/nodes`
|
||||
- 继续验证 Detect 页面主计数是否跟随真实执行推进
|
||||
|
||||
## 本轮关键命令证据
|
||||
|
||||
```bash
|
||||
cd /opt/domaincheck/domain-web && npm run build
|
||||
curl -I http://127.0.0.1:3201/
|
||||
curl http://127.0.0.1:3201/
|
||||
rg -n "event-stream-panel|任务日志控制台|检测事件流" \
|
||||
/www/wwwroot/getDomain/domain-web/dist/assets/DetectView-BFxMNRNR.css \
|
||||
/www/wwwroot/getDomain/domain-web/dist/assets/DetectView-B9S1WMRT.js
|
||||
```
|
||||
54
docs/ops_center_runtime/HANDOFF_20260419_1429.md
Normal file
54
docs/ops_center_runtime/HANDOFF_20260419_1429.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# HANDOFF_20260419_1429
|
||||
|
||||
更新时间:2026-04-19 14:29 CST
|
||||
|
||||
## 本轮完成
|
||||
|
||||
- 已修复代理链“配置已下发但长期停留未刷新”的问题
|
||||
- `domaincheck-worker` 现在会在以下时机主动刷新代理池:
|
||||
- worker 启动后
|
||||
- `proxy_config`
|
||||
- `thread_count`
|
||||
- `node_thread_counts`
|
||||
- `runtime_settings`
|
||||
- 以上配置更新后
|
||||
- 已重启:
|
||||
- `domaincheck-worker`
|
||||
- `domaincheck-api`
|
||||
- 已完成一次真实代理池刷新并拿到明确结果:
|
||||
- 原始代理数:`202`
|
||||
- 抽样验证数:`24`
|
||||
- 可用代理数:`0`
|
||||
|
||||
## 当前状态
|
||||
|
||||
- 当前后台不再显示误导性的“未刷新”
|
||||
- 当前真实状态为:
|
||||
- `proxy_runtime_label = 降级直连`
|
||||
- `proxy_runtime_reason = proxy_validation_zero`
|
||||
- `proxy_runtime_detail = 代理源最近返回了 202 个代理,已验证 24 个,但当前 0 个可用;系统已自动降级为直连继续执行;最近状态:刷新成功,可用 0 个`
|
||||
|
||||
## 关键判断
|
||||
|
||||
- 这批代理当前的主要问题不是“系统没去用”
|
||||
- 而是:
|
||||
- 代理源会返回很多 IP
|
||||
- 但 worker 实测校验时全部失败
|
||||
- 失败以 `ProxyError / ConnectTimeout` 为主
|
||||
|
||||
## 下一步建议
|
||||
|
||||
- 优先不要再纠结“为什么页面写未刷新”
|
||||
- 这一层已经修好
|
||||
- 下一轮如果继续优化代理,应只做以下两种之一:
|
||||
- 更换/补充代理供应组,重新验证可用率
|
||||
- 调整代理校验策略,但要接受更高的脏代理混入风险
|
||||
|
||||
## 现场证据
|
||||
|
||||
```text
|
||||
主动触发代理池刷新: worker_startup
|
||||
代理池链接拉取成功 ... 原始代理数: 50 / 50 / 0 / 50 / 2 / 50
|
||||
代理池验证已启用抽样模式,本次抽样 24 个代理进行可用性验证
|
||||
代理池刷新完成,共 0 个可用代理,来源链接 6 个
|
||||
```
|
||||
42
docs/ops_center_runtime/HANDOFF_20260419_1450.md
Normal file
42
docs/ops_center_runtime/HANDOFF_20260419_1450.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# HANDOFF_20260419_1450
|
||||
|
||||
更新时间:2026-04-19 14:50 CST
|
||||
|
||||
## 本轮完成
|
||||
|
||||
- 已继续优化代理链,不只停留在“看见 0 可用”
|
||||
- 已新增两项优化:
|
||||
- 扩展严格验证目标:
|
||||
- `baidu`
|
||||
- `m.baidu`
|
||||
- `qq`
|
||||
- `360`
|
||||
- 当严格验证 `0` 命中时,启用:
|
||||
- `宽松入池 + 快速隔离`
|
||||
|
||||
## 当前结果
|
||||
|
||||
- 当前最新代理刷新结果:
|
||||
- `proxy_last_refresh_total_items = 270`
|
||||
- `proxy_last_validated_count = 24`
|
||||
- `proxy_last_available_count = 2`
|
||||
- `proxy_last_refresh_status = 宽松入池 2 个(严格校验 0 命中)`
|
||||
- 后台当前已显示:
|
||||
- `available_proxy_count = 2`
|
||||
- `proxy_runtime_detail = 代理池当前可用 2 个代理,配置来源 6 个;最近状态:宽松入池 2 个(严格校验 0 命中)`
|
||||
|
||||
## 关键判断
|
||||
|
||||
- 严格校验下,这批代理整体质量依然偏差
|
||||
- 但现在已经不再是完全 `0` 可用
|
||||
- 系统已成功放出少量试跑代理,可以继续观察:
|
||||
- 是否带动检测吞吐
|
||||
- 是否很快被失败隔离重新打回 `0`
|
||||
|
||||
## 下一步
|
||||
|
||||
- 优先观察这 `2` 个试跑代理是否真的参与检测执行
|
||||
- 如果能参与并带来吞吐,再继续逐步放宽
|
||||
- 如果很快再次掉回 `0`,下一轮就应转到:
|
||||
- 补代理供应组
|
||||
- 或按地区/分组拆分代理质量统计
|
||||
64
docs/ops_center_runtime/HANDOFF_20260419_1454.md
Normal file
64
docs/ops_center_runtime/HANDOFF_20260419_1454.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# HANDOFF 2026-04-19 14:54 CST
|
||||
|
||||
## 本轮目标
|
||||
|
||||
把代理链从“预验证优先”切到用户指定的最小高效路径:
|
||||
|
||||
- 只去掉过期 / 非法代理
|
||||
- 不再单独做可用性预验证
|
||||
- 直接投入真实检测
|
||||
- 失败即淘汰并触发补刷
|
||||
|
||||
## 本轮已完成
|
||||
|
||||
- 已修改 [detect_worker.py](/www/wwwroot/getDomain/domainCheck/detect_worker.py)
|
||||
- `refresh_proxy_pool()`
|
||||
- 移除预验证入池逻辑
|
||||
- 仅做过期 / 非法 / 去重过滤
|
||||
- 直接把代理源返回结果入池
|
||||
- `remove_proxy()`
|
||||
- 代理失败后不再留在当前池尾部
|
||||
- 直接从当前池移除
|
||||
- 保留失败标记并在低水位时触发补刷
|
||||
- 已重启 `domaincheck-worker`
|
||||
- 已确认 worker 新日志进入运行态
|
||||
|
||||
## 最新运行证据
|
||||
|
||||
- worker 最新日志:
|
||||
- `代理池刷新完成,共 270 个入池代理,来源链接 6 个,原始 270 个,去过期 0 个,非法 0 个`
|
||||
- API 最新状态:
|
||||
- `available_proxy_count = 270`
|
||||
- `proxy_last_refresh_status = 直入池 270 个(跳过预验证)`
|
||||
- `proxy_last_validated_count = 0`
|
||||
- `proxy_runtime_reason = healthy`
|
||||
|
||||
## 当前判断
|
||||
|
||||
- 这轮目标已经完成
|
||||
- 代理链现在已经符合“直接跑任务,失败就丢弃代理并换新”的要求
|
||||
- 下一步不该再回头做单独代理预验证
|
||||
|
||||
## 下一步主任务
|
||||
|
||||
唯一主任务:
|
||||
|
||||
- 继续观察真实检测吞吐是否随直入池策略抬升
|
||||
- 重点看:
|
||||
- `/api/v1/detect/status`
|
||||
- `/api/v1/ops/nodes`
|
||||
- 检测页主计数 `pending/completed/running`
|
||||
- 失败代理淘汰后是否能持续自动补池
|
||||
|
||||
## 若下一轮继续
|
||||
|
||||
优先处理:
|
||||
|
||||
- “并发已下发但主计数不明显推进”的统计 / 调度口径问题
|
||||
|
||||
不要处理:
|
||||
|
||||
- 不要重新加回重预验证逻辑
|
||||
- 不要扩展新页面
|
||||
- 不要扩展控制面新模块
|
||||
- 不要发散到发布链或新专题文档
|
||||
107
docs/ops_center_runtime/HANDOFF_20260419_2053.md
Normal file
107
docs/ops_center_runtime/HANDOFF_20260419_2053.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# HANDOFF_20260419_2053
|
||||
|
||||
更新时间:2026-04-19 20:53 CST
|
||||
|
||||
## 本轮完成
|
||||
|
||||
- 修复发布打包遗漏:
|
||||
- 最新发布包现在已包含 `domainCheck/`
|
||||
- 最新正式签收包:
|
||||
- `domaincheck_release_20260419_205437`
|
||||
- 修复发布任务观测性:
|
||||
- `domain-api/app/services/ops_release_executor_core.py`
|
||||
- 发布目录不可写时显式失败
|
||||
- 增加 `ExecStart` 与 `current` 软链对齐观测
|
||||
- `domain-api/app/node_agent.py`
|
||||
- 增加 job 级兜底异常回写,避免任务假性卡死
|
||||
- 将卡死的 worker 发布任务纠正为真实失败:
|
||||
- `release_id = 6`
|
||||
- `rollout_id = 5`
|
||||
- `job_id = 204`
|
||||
- 当前已从假 `running` 回正为 `failed`
|
||||
- 本次失败对应的 Release 版本:
|
||||
- `domaincheck_release_20260419_203933`
|
||||
|
||||
## 今晚新增关键结论
|
||||
|
||||
### 1. worker 发布失败的真实原因已明确
|
||||
|
||||
- `mainland-worker-01`
|
||||
- node-agent 日志:
|
||||
- `2026-04-19 20:40:15 [node-agent] loop error: [Errno 13] Permission denied: '/opt/domaincheck/downloads'`
|
||||
- 对应发布任务:
|
||||
- `job 204 = failed`
|
||||
- `rollout 5 = failed`
|
||||
- 当前失败原因已经正式回写:
|
||||
- `install_root not writable: /opt/domaincheck/downloads`
|
||||
|
||||
### 2. mainland 两台节点都不符合当前 ReleaseHub 发布模型
|
||||
|
||||
- `mainland-worker-01`
|
||||
- `domaincheck-worker` 当前启动路径:
|
||||
- `/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
- `mainland-controller-01`
|
||||
- `domaincheck-worker` 当前启动路径:
|
||||
- `/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
|
||||
这意味着:
|
||||
|
||||
- 当前线上服务不是跑在
|
||||
- `/opt/domaincheck/current/domainCheck/...`
|
||||
- 所以即使发布成功切了 `current` 软链
|
||||
- 也不会自动让现有 systemd 服务切到新版本
|
||||
|
||||
### 3. worker 当前不是新版本高吞吐样本
|
||||
|
||||
- `mainland-worker-01`
|
||||
- `Active since = 2026-04-19 18:18:50 CST`
|
||||
- `Main PID = 635924`
|
||||
- `CPU = 18.994s`
|
||||
- 最近日志仍停留在旧代码行号:
|
||||
- `_run_detect_register:2465`
|
||||
- `detect_domain:2947`
|
||||
- `start_redis_subscription:3590`
|
||||
|
||||
说明:
|
||||
|
||||
- worker 仍是旧进程
|
||||
- 当前不能把它当成“已切新包并真实参与高吞吐”的有效证据
|
||||
|
||||
## 结论
|
||||
|
||||
当前唯一主阻塞不是前端、不是统计口径、也不是单纯并发参数。
|
||||
|
||||
当前唯一主阻塞是:
|
||||
|
||||
- mainland 节点 `deploy.release` 目录权限不满足
|
||||
- mainland 节点 `domaincheck-worker` 的 systemd `ExecStart` 与 ReleaseHub 的 `current` 发布模型不一致
|
||||
|
||||
在这两个问题修正前:
|
||||
|
||||
- 不建议继续对 mainland 节点做正式 rollout
|
||||
- 不建议继续把 worker 统计口径偏差当成纯展示层问题
|
||||
|
||||
## 下一步唯一建议
|
||||
|
||||
1. 先修 mainland 节点发布基座
|
||||
- 让 node-agent 对 `/opt/domaincheck/downloads`、`/opt/domaincheck/releases` 有写权限
|
||||
- 或明确改成一个 node-agent 真正可写的发布根目录
|
||||
2. 再统一 `domaincheck-worker.service`
|
||||
- 让 `ExecStart` 指向 `/opt/domaincheck/current/domainCheck/detect_worker.py`
|
||||
- 不再直指 `/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
3. 完成后重新发起:
|
||||
- worker rollout
|
||||
- 验证 PID 切换
|
||||
- 验证代码行号切换到当前版本
|
||||
- 再看吞吐和 CPU 利用率
|
||||
|
||||
## 本轮改动文件
|
||||
|
||||
- `package_domain_release.sh`
|
||||
- `verify_domain_release.sh`
|
||||
- `package_domain_release.ps1`
|
||||
- `verify_domain_release.ps1`
|
||||
- `domain-api/app/services/ops_release_executor_core.py`
|
||||
- `domain-api/app/node_agent.py`
|
||||
- `docs/ops_center_runtime/TASK_BOARD.md`
|
||||
- `docs/ops_center_runtime/IMPLEMENTATION_STATUS.md`
|
||||
102
docs/ops_center_runtime/HANDOFF_20260419_2117.md
Normal file
102
docs/ops_center_runtime/HANDOFF_20260419_2117.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# HANDOFF_20260419_2117
|
||||
|
||||
更新时间:2026-04-19 21:17 CST
|
||||
|
||||
## 本轮结论
|
||||
|
||||
`mainland-worker-01` 的最新正式 rollout 已完成根因收口:
|
||||
|
||||
- `release_id = 7`
|
||||
- `rollout_id = 6`
|
||||
- `job_id = 211`
|
||||
|
||||
执行结果:
|
||||
|
||||
- 发布包下载成功
|
||||
- `/opt/domaincheck/downloads/domaincheck_release_20260419_205437.tar.gz`
|
||||
- release 解压成功
|
||||
- `/opt/domaincheck/releases/domaincheck_release_20260419_205437`
|
||||
- `current` 软链切换成功
|
||||
- `/opt/domaincheck/current -> /opt/domaincheck/releases/domaincheck_release_20260419_205437`
|
||||
- 最终失败在:
|
||||
- `systemctl restart domaincheck-worker`
|
||||
|
||||
控制面失败结果原文:
|
||||
|
||||
- `restart failed: domaincheck-worker`
|
||||
- `Failed to restart domaincheck-worker.service: Interactive authentication required.`
|
||||
|
||||
## 真实根因
|
||||
|
||||
不是发布包问题,也不是目录权限问题了。
|
||||
|
||||
当前根因是:
|
||||
|
||||
- `domaincheck-node-agent` 运行身份仍是 `www`
|
||||
- 它具备下载、解压、切换 `current` 的权限
|
||||
- 但不具备执行 systemd 服务重启的权限
|
||||
|
||||
所以当前所有以下动作在 mainland 机器上都会有同类风险:
|
||||
|
||||
- `deploy.release`
|
||||
- `service.restart`
|
||||
- 任何依赖 node-agent 直接操作 systemd 的动作
|
||||
|
||||
## 本轮已做代码修正
|
||||
|
||||
已修改:
|
||||
|
||||
- `domain-api/deploy/systemd/domain-node-agent.service`
|
||||
- `User=root`
|
||||
- `Group=root`
|
||||
- `domain-api/deploy/multi-region/fix_mainland_release_base.sh`
|
||||
- 安装 node-agent drop-in 时补齐:
|
||||
- `User=root`
|
||||
- `Group=root`
|
||||
|
||||
已验证:
|
||||
|
||||
- `bash -n domain-api/deploy/multi-region/fix_mainland_release_base.sh`
|
||||
|
||||
## 现场下一步
|
||||
|
||||
下一步不要再重复发起新的 rollout,先把 `mainland-worker-01` 的 node-agent 切到 root。
|
||||
|
||||
建议现场执行:
|
||||
|
||||
```bash
|
||||
mkdir -p /etc/systemd/system/domaincheck-node-agent.service.d
|
||||
cat >/etc/systemd/system/domaincheck-node-agent.service.d/runtime-user.conf <<'EOF'
|
||||
[Service]
|
||||
User=root
|
||||
Group=root
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl restart domaincheck-node-agent
|
||||
systemctl status domaincheck-node-agent --no-pager -l
|
||||
```
|
||||
|
||||
完成后应立即复查:
|
||||
|
||||
```bash
|
||||
systemctl show domaincheck-node-agent -p User -p Group
|
||||
journalctl -u domaincheck-node-agent -n 80 --no-pager -l
|
||||
```
|
||||
|
||||
预期结果:
|
||||
|
||||
- `domaincheck-node-agent` 以 `root` 身份运行
|
||||
- 心跳恢复,`mainland-worker-01` 不再是 `stale`
|
||||
- 后续再发起 `deploy.release` 时,能够闭环到 `systemctl restart domaincheck-worker`
|
||||
|
||||
## 当前判断
|
||||
|
||||
当前主阻塞只剩一个:
|
||||
|
||||
- mainland node-agent 权限模型未切到 root
|
||||
|
||||
这个问题修完后,再重新发起 worker rollout,才有资格继续看:
|
||||
|
||||
- `domaincheck-worker` 是否切到新 PID
|
||||
- health check 是否通过
|
||||
- rollout 6 之后的 acceptance 是否可继续
|
||||
95
docs/ops_center_runtime/HANDOFF_20260419_2125.md
Normal file
95
docs/ops_center_runtime/HANDOFF_20260419_2125.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# HANDOFF_20260419_2125
|
||||
|
||||
更新时间:2026-04-19 21:25 CST
|
||||
|
||||
## 本轮结果
|
||||
|
||||
`mainland-worker-01` 的 release rollout 已正式成功收口。
|
||||
|
||||
关键信息:
|
||||
|
||||
- `release_id = 7`
|
||||
- `rollout_id = 7`
|
||||
- `job_id = 214`
|
||||
|
||||
最终状态:
|
||||
|
||||
- `job 214 = success`
|
||||
- `rollout 7 = completed`
|
||||
- `mainland-worker-01.agent_state = online_busy`
|
||||
|
||||
## 成功证据
|
||||
|
||||
控制面 `job events` 已记录:
|
||||
|
||||
- `event_type = agent_completed`
|
||||
- `summary_text = release deployed`
|
||||
|
||||
结果载荷中已确认:
|
||||
|
||||
- `release_version = domaincheck_release_20260419_205437`
|
||||
- `restart_results`
|
||||
- `domaincheck-worker.returncode = 0`
|
||||
- `health_check.ok = true`
|
||||
- `services_checked = ["domaincheck-worker"]`
|
||||
- `execstart_alignment.mismatched_services = []`
|
||||
|
||||
说明这次已经完整走通:
|
||||
|
||||
1. 下载发布包
|
||||
2. 解压 release
|
||||
3. 切换 `/opt/domaincheck/current`
|
||||
4. 重启 `domaincheck-worker`
|
||||
5. 健康检查通过
|
||||
|
||||
## 为什么这次成功
|
||||
|
||||
不是发布逻辑变化了,而是现网权限问题被修掉了。
|
||||
|
||||
上一轮失败根因:
|
||||
|
||||
- `domaincheck-node-agent` 以 `www` 身份运行
|
||||
- 无法执行 `systemctl restart domaincheck-worker`
|
||||
- systemd 返回:
|
||||
- `Interactive authentication required`
|
||||
|
||||
本轮修复:
|
||||
|
||||
- `mainland-worker-01`
|
||||
- `domaincheck-node-agent` 已切为:
|
||||
- `User=root`
|
||||
- `Group=root`
|
||||
|
||||
## 当前剩余项
|
||||
|
||||
唯一建议立即同步的预防动作:
|
||||
|
||||
- 在 `mainland-controller-01` 上,也把 `domaincheck-node-agent` 切成 `root`
|
||||
|
||||
原因:
|
||||
|
||||
- worker 已经验证这就是 release 闭环最后一层权限门槛
|
||||
- controller 如果后续参与自身发布 / restart,同样会遇到同类 systemd 权限问题
|
||||
|
||||
建议执行:
|
||||
|
||||
```bash
|
||||
mkdir -p /etc/systemd/system/domaincheck-node-agent.service.d
|
||||
cat >/etc/systemd/system/domaincheck-node-agent.service.d/runtime-user.conf <<'EOF'
|
||||
[Service]
|
||||
User=root
|
||||
Group=root
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl restart domaincheck-node-agent
|
||||
systemctl show domaincheck-node-agent -p User -p Group
|
||||
```
|
||||
|
||||
## 当前判断
|
||||
|
||||
关于 mainland worker 的发布链,已经不再是阻塞项。
|
||||
|
||||
现在可以进入下一步:
|
||||
|
||||
- 再决定是否对 `mainland-controller-01` 做同样 root 切换
|
||||
- 然后继续 controller acceptance / rollout 收口
|
||||
563
docs/ops_center_runtime/HANDOFF_20260420_1920.md
Normal file
563
docs/ops_center_runtime/HANDOFF_20260420_1920.md
Normal file
@@ -0,0 +1,563 @@
|
||||
# HANDOFF_20260420_1920
|
||||
|
||||
更新时间:2026-04-20 19:20 CST
|
||||
|
||||
## 本轮结论
|
||||
|
||||
这轮最重要的收口已经完成:
|
||||
|
||||
- 已确认当前工作机 `/www/wwwroot/getDomain` 所在主机是海外测试控制面,不是国内 `mainland-controller-01`
|
||||
- 已把“假冒 mainland-controller-01”的本机配置纠正为 `overseas-control-01`
|
||||
- 已把真正的 `mainland-controller-01` 重新接回控制面,并完成一次成功的远端发布
|
||||
- 已修正 `mainland-controller-01` 的 node-agent 身份上报问题
|
||||
- 现在控制面里看到的 `mainland-controller-01` 已经是真实主机:
|
||||
- `hostname = mainland-controller-01`
|
||||
- `ip = 121.204.244.188`
|
||||
|
||||
一句话说当前状态:
|
||||
|
||||
“主线已经从‘节点身份混乱’推进到‘真 controller 已经对正并重新进场’,下一步应只盯 controller 真机吞吐和 worker 恢复,不要再回展示层。”
|
||||
|
||||
## 当前环境认知
|
||||
|
||||
### 1. 当前 Codex 所在机器不是大陆 controller
|
||||
|
||||
本地执行结果:
|
||||
|
||||
- `hostname = v2202604268673447256`
|
||||
- `nproc = 12`
|
||||
|
||||
这台机器是海外控制面测试机,不是用户说的 112 核 controller。
|
||||
|
||||
真正的国内 controller 是:
|
||||
|
||||
- `node_code = mainland-controller-01`
|
||||
- `ssh_host = 121.204.244.188`
|
||||
|
||||
真正的国内 worker 是:
|
||||
|
||||
- `node_code = mainland-worker-01`
|
||||
- `ssh_host = 121.204.244.248`
|
||||
|
||||
### 2. 本机服务身份已经纠正
|
||||
|
||||
为避免海外测试机继续伪装成 mainland controller,已经改过这些环境文件:
|
||||
|
||||
- `/etc/default/domaincheck-worker`
|
||||
- `/etc/default/domaincheck-node-agent`
|
||||
- `/etc/default/domaincheck-api`
|
||||
|
||||
修正后的核心值:
|
||||
|
||||
- `NODE_CODE=overseas-control-01`
|
||||
- `NODE_REGION=overseas`
|
||||
- `SYNC_PUSH_ENABLED=false`
|
||||
|
||||
并且已经执行过:
|
||||
|
||||
- 停止本机 `domaincheck-worker`
|
||||
- 停止本机 `domaincheck-node-agent`
|
||||
- 重启本机 `domaincheck-api`
|
||||
|
||||
当前海外控制面 API 进程环境已确认是:
|
||||
|
||||
- `NODE_CODE=overseas-control-01`
|
||||
- `NODE_REGION=overseas`
|
||||
|
||||
## 本轮已完成的关键修复
|
||||
|
||||
## A. 修复 controller node-agent 上报 localhost / 127.0.0.1
|
||||
|
||||
修改文件:
|
||||
|
||||
- [domain-api/app/node_agent.py](/www/wwwroot/getDomain/domain-api/app/node_agent.py)
|
||||
|
||||
修复内容:
|
||||
|
||||
- `_hostname()` 不再优先相信 `localhost`
|
||||
- `_ip()` 不再使用容易得到 `127.0.0.1` 的旧逻辑
|
||||
- 优先通过控制面地址推导本机出口 IP
|
||||
- 回退时也会过滤 loopback
|
||||
|
||||
本轮新增/补过的测试:
|
||||
|
||||
- [domain-api/tests/test_node_agent_delivery_queue.py](/www/wwwroot/getDomain/domain-api/tests/test_node_agent_delivery_queue.py)
|
||||
|
||||
注意:
|
||||
|
||||
- 当前仓库里这份修复已经在真 controller 上生效
|
||||
- handover 已显示:
|
||||
- `agent_hostname = mainland-controller-01`
|
||||
- `agent_ip = 121.204.244.188`
|
||||
- `cluster_hostname = mainland-controller-01`
|
||||
- `cluster_ip = 121.204.244.188`
|
||||
|
||||
## B. 修复 control 节点发布健康检查窗口过短
|
||||
|
||||
修改文件:
|
||||
|
||||
- [domain-api/app/services/ops_release_service.py](/www/wwwroot/getDomain/domain-api/app/services/ops_release_service.py)
|
||||
|
||||
修改目标:
|
||||
|
||||
- control 节点发布时,`domaincheck-api` 启动偏慢,旧健康检查窗口太短,会误判失败并回滚
|
||||
|
||||
代码里已改成:
|
||||
|
||||
- `health_check_timeout_seconds = 20`
|
||||
- `health_check_retries = 6`
|
||||
- `health_check_interval_seconds = 3`
|
||||
|
||||
但要注意一个坑:
|
||||
|
||||
- 这份代码虽然已改进源码
|
||||
- 海外控制面的运行中 API 进程还没有通过这份新源码重新部署
|
||||
- 所以 `smart-rollout-preview` 里看到的默认值一度仍然是旧的 `10 / 2 / 2`
|
||||
|
||||
因此本轮实际是通过“手工 remote-agent deploy job 显式带长窗口 payload”打通了 controller 发布。
|
||||
|
||||
## C. 真 controller 发布已经成功一次
|
||||
|
||||
成功任务:
|
||||
|
||||
- `job_id = 331`
|
||||
- `job_code = ops-20260420183116-c33723`
|
||||
- `action = deploy.release`
|
||||
- `target_node_code = mainland-controller-01`
|
||||
- `execution_mode = remote-agent`
|
||||
- `status = success`
|
||||
|
||||
本次使用的 release:
|
||||
|
||||
- `release_id = 27`
|
||||
- `release_version = domaincheck_release_20260420_182916`
|
||||
|
||||
发布结果要点:
|
||||
|
||||
- 发布包下载成功
|
||||
- checksum 校验成功
|
||||
- `/opt/domaincheck/current` 切换成功
|
||||
- `domaincheck-api / domaincheck-worker / domaincheck-sync-agent` 重启成功
|
||||
- 健康检查最终通过
|
||||
|
||||
尤其要记住:
|
||||
|
||||
- 这次成功不是靠 smart rollout 默认值
|
||||
- 是通过显式下发以下健康窗口打通的:
|
||||
- `health_check_timeout_seconds = 20`
|
||||
- `health_check_retries = 6`
|
||||
- `health_check_interval_seconds = 3`
|
||||
|
||||
## D. controller node-agent 已经重新连回
|
||||
|
||||
后续又触发了:
|
||||
|
||||
- `job_id = 332`
|
||||
- `action = service.restart`
|
||||
- `payload.service_name = domaincheck-node-agent`
|
||||
|
||||
这个任务本身还停留在 `running`,原因很正常:
|
||||
|
||||
- node-agent 在“执行重启自己”的过程中会打断自身回执链
|
||||
- 所以作业状态可能不会自然收尾
|
||||
|
||||
但实际效果已经发生:
|
||||
|
||||
- API 日志已看到 `121.204.244.188` 在 `2026-04-20 18:35:16` 重新开始:
|
||||
- `POST /api/v1/ops/agent/heartbeat`
|
||||
- `POST /api/v1/ops/agent/pull?limit=1`
|
||||
|
||||
因此这条 job 332 可以视为“结果已生效,但状态未优雅回写”的典型自重启任务。
|
||||
|
||||
## 当前实机状态
|
||||
|
||||
按最新控制面查询:
|
||||
|
||||
### mainland-controller-01
|
||||
|
||||
- `agent_online = true`
|
||||
- `cluster_status = busy`
|
||||
- `agent_hostname = mainland-controller-01`
|
||||
- `agent_ip = 121.204.244.188`
|
||||
- `current_load` 在本轮观察中约 `210 - 233`
|
||||
- `detect_runtime.active_threads` 在本轮观察中约 `210 - 233 / 2000`
|
||||
- 已经有持续日志回传
|
||||
|
||||
### mainland-worker-01
|
||||
|
||||
- node-agent 在线
|
||||
- 但当前没有真正参与检测
|
||||
- 控制面返回的 `detect_runtime` 错误为:
|
||||
- `connection to server at "127.0.0.1", port 5432 failed: Connection refused`
|
||||
|
||||
这意味着:
|
||||
|
||||
- worker 机现在不是主要算力来源
|
||||
- 目前真正吃任务的是 `mainland-controller-01`
|
||||
|
||||
## 当前主线瓶颈
|
||||
|
||||
目前主线已经不是“谁是 controller”了,当前瓶颈明确是下面两个:
|
||||
|
||||
1. `mainland-worker-01` 未恢复到可参与检测状态
|
||||
2. `mainland-controller-01` 虽然真实线程已抬到 200+,但控制面队列视角仍存在:
|
||||
- `claimed` 偏高
|
||||
- `running/completed` 推进不够理想
|
||||
- 吞吐没有完全吃透机器
|
||||
|
||||
也就是说:
|
||||
|
||||
- “节点身份问题”已基本打穿
|
||||
- “发布链路问题”已基本打穿
|
||||
- 下一步该只盯“真 controller 吞吐”和“worker 恢复”
|
||||
|
||||
## 本轮新增发现
|
||||
|
||||
### 1. mainland-worker-01 的 `127.0.0.1:5432` 更像是 node-agent 侧遥测链路问题
|
||||
|
||||
本轮继续排查后,发现这个问题至少有两层:
|
||||
|
||||
1. `domainCheck` 默认配置本身就是:
|
||||
- `DB_HOST = localhost`
|
||||
2. worker 机上的 `domaincheck-node-agent` systemd unit 当前只加载:
|
||||
- `/etc/default/domaincheck-api`
|
||||
- `/etc/default/domaincheck-node-agent`
|
||||
|
||||
但大陆 worker 快速安装脚本真正写入数据库与 Redis 指向的是:
|
||||
|
||||
- `/etc/default/domaincheck-worker`
|
||||
|
||||
也就是说,worker 机上很可能出现这种情况:
|
||||
|
||||
- `domaincheck-worker` 进程拿到的是正确的 `DB_HOST=${MAINLAND_CONTROLLER_IP}`
|
||||
- 但 `domaincheck-node-agent` 没有继承 `/etc/default/domaincheck-worker`
|
||||
- node-agent 内部去跑 `get_detect_status()` 时,就会落回 `domain-api` 默认配置:
|
||||
- `db_host = 127.0.0.1`
|
||||
|
||||
于是控制面上看到的现象就变成:
|
||||
|
||||
- `mainland-worker-01 agent 在线`
|
||||
- 但 `detect_runtime` 里报:
|
||||
- `connection to server at "127.0.0.1", port 5432 failed: Connection refused`
|
||||
|
||||
### 2. node-agent 当前把“DB 查询失败”和“worker 进程离线”混成了一种失败
|
||||
|
||||
`domain-api/app/node_agent.py` 里的 `_detect_runtime_snapshot()` 原来是:
|
||||
|
||||
- `get_detect_status()` 和 `detect_worker_runtime()` 放在同一个总 `try` 里
|
||||
|
||||
这会导致:
|
||||
|
||||
- 只要前面的 DB 查询失败
|
||||
- 后面的 worker systemd 运行态也一起被吞掉
|
||||
- 最终上报成:
|
||||
- `worker_online = false`
|
||||
- `service_running = false`
|
||||
|
||||
即使真实情况其实可能只是:
|
||||
|
||||
- worker 服务还活着
|
||||
- 只是 node-agent 在采集 detect status 时查错 DB 了
|
||||
|
||||
### 3. 本轮已在源码里补的最小修复
|
||||
|
||||
已修改:
|
||||
|
||||
- [domain-api/app/node_agent.py](/www/wwwroot/getDomain/domain-api/app/node_agent.py)
|
||||
- [domain-api/deploy/systemd/domain-node-agent.service](/www/wwwroot/getDomain/domain-api/deploy/systemd/domain-node-agent.service)
|
||||
- [domain-api/tests/test_node_agent_delivery_queue.py](/www/wwwroot/getDomain/domain-api/tests/test_node_agent_delivery_queue.py)
|
||||
|
||||
修复内容:
|
||||
|
||||
1. `_detect_runtime_snapshot()` 改成分层降级:
|
||||
- 先拿 `detect_worker_runtime()`
|
||||
- 再单独尝试 `get_detect_status()`
|
||||
- 即使 detect status 因 DB 异常失败,也保留真实的 worker service 运行态
|
||||
2. `domaincheck-node-agent.service` 追加:
|
||||
- `EnvironmentFile=-/etc/default/domaincheck-worker`
|
||||
|
||||
这样 worker 机上的 node-agent 也能直接继承 worker 真实使用的 `DB_HOST / REDIS_HOST`。
|
||||
|
||||
### 4. 这次修复的生效边界
|
||||
|
||||
要特别注意:
|
||||
|
||||
- `node_agent.py` 代码修复可以通过常规 release 进入真实运行目录并生效
|
||||
- 但 `domaincheck-node-agent.service` 属于 `/etc/systemd/system/` 下的系统级 unit 文件
|
||||
- 常规 `deploy.release` 只会切换 `/opt/domaincheck/current`,不会自动重装 systemd unit
|
||||
|
||||
所以这两项应分开看:
|
||||
|
||||
1. `node_agent.py`:
|
||||
- 可以走最小 release 先上真机
|
||||
2. `domain-node-agent.service`:
|
||||
- 需要后续补 systemd unit 落地动作
|
||||
- 至少要包含:
|
||||
- 覆盖 unit 文件或 drop-in
|
||||
- `systemctl daemon-reload`
|
||||
- `systemctl restart domaincheck-node-agent`
|
||||
|
||||
### 5. 本轮测试结果
|
||||
|
||||
已通过的焦点测试:
|
||||
|
||||
- `PYTHONPATH=/www/wwwroot/getDomain/domain-api /opt/domaincheck/domainCheck/.venv/bin/python -m unittest tests.test_node_agent_delivery_queue -v`
|
||||
|
||||
结果:
|
||||
|
||||
- `11 tests`
|
||||
- `OK`
|
||||
|
||||
新增验证点:
|
||||
|
||||
- `test_detect_runtime_snapshot_degrades_to_worker_runtime_when_detect_status_fails`
|
||||
|
||||
它验证了:
|
||||
|
||||
- 即使 `get_detect_status()` 抛出
|
||||
- `connection to server at "127.0.0.1", port 5432 failed`
|
||||
- node-agent 依然会保留:
|
||||
- `worker_online = true`
|
||||
- `service_running = true`
|
||||
- `phase_detail = active/running`
|
||||
|
||||
## 本轮最小发布动作
|
||||
|
||||
### 1. 已生成新发布包
|
||||
|
||||
本轮最小修复已重新打包:
|
||||
|
||||
- `release_version = domaincheck_release_20260420_215734`
|
||||
- `release_id = 28`
|
||||
|
||||
生成结果:
|
||||
|
||||
- `archive = /www/wwwroot/getDomain/release/domaincheck_release_20260420_215734.tar.gz`
|
||||
- `sha256 = ad2c41625503dab1efaeadbf0641c8f6875a3cad0581a3b9c7835ccc37cdc718`
|
||||
|
||||
### 2. 已向真节点发起最小 release 下发
|
||||
|
||||
本轮只为把 `node_agent.py` 先推进真实运行目录,已创建:
|
||||
|
||||
- `job_id = 335`
|
||||
- `target = mainland-controller-01`
|
||||
- `action = deploy.release`
|
||||
- `job_id = 336`
|
||||
- `target = mainland-worker-01`
|
||||
- `action = deploy.release`
|
||||
|
||||
这两条 job 都已经越过“等待拉取”,进入了 agent 执行阶段,并至少记录到:
|
||||
|
||||
- `executor_received`
|
||||
- `deploy_download_started`
|
||||
|
||||
说明:
|
||||
|
||||
- 真 controller 和真 worker 都已经接到了这版最小 release
|
||||
- 当前至少已经在真实节点上进入下载/发布链
|
||||
|
||||
### 3. 这次发布的真实目标
|
||||
|
||||
这次发布不是为了一次性解决所有 worker 恢复问题,而是为了先把下面这条代码修复推到真节点:
|
||||
|
||||
- `domain-api/app/node_agent.py`
|
||||
|
||||
目的:
|
||||
|
||||
- 即使 worker 节点的 `detect_status` 查询因 DB 指向错误失败
|
||||
- node-agent 也不再把真实的 worker service 运行态一并吞掉
|
||||
- 控制面能先看到更接近真实的 `worker_online / service_running`
|
||||
|
||||
### 4. 这次发布的限制
|
||||
|
||||
这次最小 release 暂时还不能自动完成下面这件事:
|
||||
|
||||
- 把 `/etc/systemd/system/domaincheck-node-agent.service` 更新为新版本
|
||||
|
||||
原因:
|
||||
|
||||
- 常规 `deploy.release` 切的是 `/opt/domaincheck/current`
|
||||
- 不会自动重装 systemd unit
|
||||
|
||||
因此当前判断是:
|
||||
|
||||
1. `node_agent.py` 代码修复:
|
||||
- 已经进入真实节点发布链
|
||||
2. `domaincheck-node-agent.service` 的 `EnvironmentFile=-/etc/default/domaincheck-worker`:
|
||||
- 仍需要后续单独补系统级落地动作
|
||||
|
||||
### 5. 当前发布观察结论
|
||||
|
||||
截至本次交接整理时:
|
||||
|
||||
- `job 335 / 336` 已启动执行
|
||||
- 但尚未在本轮记录中拿到最终 `success / failed` 收尾结论
|
||||
- 因此后续接手时,先做的第一件事之一,就是复查这两条 job 的最终状态与事件流
|
||||
|
||||
## 当前不要再踩的坑
|
||||
|
||||
### 1. 不要再把本机当成 mainland-controller-01
|
||||
|
||||
当前工作机是海外测试控制面,只负责:
|
||||
|
||||
- API
|
||||
- 控制面
|
||||
- 同步接收
|
||||
|
||||
不是 112 核大陆 controller。
|
||||
|
||||
### 2. 不要直接用本机 Python service 函数创建 deploy job
|
||||
|
||||
坑点:
|
||||
|
||||
- 直接在 shell 里跑本地 Python 服务函数时,读取到的 `settings.node_code` 可能不是运行中 API 进程的真实环境
|
||||
- 之前就出现过把 job 错判为 `local-runtime` 的情况
|
||||
|
||||
正确做法:
|
||||
|
||||
- 优先通过“正在运行的 API HTTP 接口”创建 job
|
||||
- 不要优先走本机 Python service 入口
|
||||
|
||||
推荐路径:
|
||||
|
||||
- `POST /api/v1/ops/releases/from-package/latest`
|
||||
- `POST /api/v1/ops/jobs`
|
||||
- `POST /api/v1/ops/jobs/{job_id}/dispatch`
|
||||
|
||||
### 3. 不要把 job 332 当成硬故障
|
||||
|
||||
`job 332` 是 `service.restart domaincheck-node-agent`。
|
||||
|
||||
它卡在 `running` 不代表没生效,反而更像:
|
||||
|
||||
- node-agent 重启了自己
|
||||
- 回执链没能把 job 收尾
|
||||
|
||||
判断是否真的生效,应看:
|
||||
|
||||
- API 日志里有没有来自 `121.204.244.188` 的 heartbeat/pull
|
||||
- handover 里 `agent_hostname / agent_ip` 是否已刷新
|
||||
|
||||
### 4. 不要再回展示层
|
||||
|
||||
当前最值钱的推进方向仍然是:
|
||||
|
||||
- controller 真机吞吐
|
||||
- claim/running/completed 推进
|
||||
- worker 恢复
|
||||
|
||||
不要把额度再耗在页面、文案、展示层结构上。
|
||||
|
||||
## 这轮动过的关键文件
|
||||
|
||||
最关键的源码文件:
|
||||
|
||||
- [domain-api/app/node_agent.py](/www/wwwroot/getDomain/domain-api/app/node_agent.py)
|
||||
- [domain-api/app/services/ops_release_service.py](/www/wwwroot/getDomain/domain-api/app/services/ops_release_service.py)
|
||||
- [domain-api/tests/test_node_agent_delivery_queue.py](/www/wwwroot/getDomain/domain-api/tests/test_node_agent_delivery_queue.py)
|
||||
|
||||
此外,工作区还存在大量其他未提交改动,不要随意回滚:
|
||||
|
||||
- `domain-api/`
|
||||
- `domain-web/`
|
||||
- `domainCheck/`
|
||||
- `docs/ops_center_runtime/`
|
||||
|
||||
这是一个脏工作区,接手时必须小心,不要用破坏性 git 命令。
|
||||
|
||||
## 建议下一个 Codex 只做的两件事
|
||||
|
||||
### 任务 1:恢复 mainland-worker-01
|
||||
|
||||
目标:
|
||||
|
||||
- 让 `mainland-worker-01` 从“agent 在线但不参与检测”恢复到可执行检测
|
||||
|
||||
先查方向:
|
||||
|
||||
- 为什么它在本地检测态里访问 `127.0.0.1:5432` 失败
|
||||
- 是本机 PostgreSQL 没启
|
||||
- 还是 worker 的运行配置仍然错误指向本地 DB
|
||||
- 还是它本来就不该走本地 PostgreSQL,而应走远端/统一控制链
|
||||
|
||||
验收标准:
|
||||
|
||||
- `mainland-worker-01.detect_runtime.worker_online = true`
|
||||
- `mainland-worker-01.detect_runtime.active_threads > 0`
|
||||
- 能稳定进入参与节点
|
||||
|
||||
### 任务 2:继续抬 mainland-controller-01 真吞吐
|
||||
|
||||
目标:
|
||||
|
||||
- 只盯真 controller 的任务推进链,不碰页面
|
||||
|
||||
重点看:
|
||||
|
||||
- `claimed -> running -> completed` 是否持续推进
|
||||
- `items_claimed` 是否能下降
|
||||
- `processed_recent / processed_per_minute` 是否能抬起来
|
||||
- `active_threads` 与 `completed` 是否成正相关
|
||||
|
||||
验收标准:
|
||||
|
||||
- controller 持续有真实 completed 增长
|
||||
- running/claimed 更贴近“持续补位”而不是堆积
|
||||
- 机器性能使用能继续往上抬
|
||||
|
||||
## 可直接复用的验证点
|
||||
|
||||
### 1. 看节点 handover
|
||||
|
||||
接口:
|
||||
|
||||
- `GET /api/v1/ops/nodes/mainland-controller-01/handover`
|
||||
|
||||
这一项已经能确认:
|
||||
|
||||
- 当前是不是对到了真 controller
|
||||
- agent/ip/hostname 是否正确
|
||||
- 当前 load / detect_runtime 是否在动
|
||||
|
||||
### 2. 看节点列表
|
||||
|
||||
接口:
|
||||
|
||||
- `GET /api/v1/ops/nodes`
|
||||
|
||||
重点字段:
|
||||
|
||||
- `agent_hostname`
|
||||
- `agent_ip`
|
||||
- `cluster_hostname`
|
||||
- `cluster_ip`
|
||||
- `detect_runtime.active_threads`
|
||||
- `current_load`
|
||||
|
||||
### 3. 看海外控制面 API 日志
|
||||
|
||||
已验证有效:
|
||||
|
||||
- `journalctl -u domaincheck-api -n 200 --no-pager`
|
||||
|
||||
尤其可以筛:
|
||||
|
||||
- `121.204.244.188`
|
||||
- `/api/v1/ops/agent/heartbeat`
|
||||
- `/api/v1/ops/agent/pull`
|
||||
|
||||
### 4. 发布 controller 的正确方式
|
||||
|
||||
推荐继续使用运行中的 API HTTP 接口,而不是本地 Python service 调用。
|
||||
|
||||
## 交接结论
|
||||
|
||||
这一轮真正解决掉的,不是“性能问题”本身,而是它前面最大的认知阻塞:
|
||||
|
||||
- 之前一直有一部分判断建立在“本机就是 controller”这个错误前提上
|
||||
- 现在这个前提已经纠正
|
||||
- 真 controller 已经重新纳入控制面,而且身份上报正确、远端发布成功、线程也已经真实抬起来
|
||||
|
||||
接手人从这里继续时,应该把主线收缩成一句话:
|
||||
|
||||
“只盯 `mainland-controller-01` 的真实吞吐推进,并恢复 `mainland-worker-01`,不要再回展示层,也不要再把海外 12 核测试机当成主算力机。”
|
||||
483
docs/ops_center_runtime/IMPLEMENTATION_STATUS.md
Normal file
483
docs/ops_center_runtime/IMPLEMENTATION_STATUS.md
Normal file
@@ -0,0 +1,483 @@
|
||||
# IMPLEMENTATION_STATUS
|
||||
|
||||
更新时间:2026-04-19 21:25 CST
|
||||
|
||||
## 当前真实状态
|
||||
|
||||
阶段判断:
|
||||
|
||||
- 海外单脑接管能力:约 `97%`
|
||||
- 发布闭环真实可用度:约 `65%~70%`
|
||||
- 分布式检测真实执行能力:约 `80%~85%`
|
||||
- 距离“可稳定上线并放心用后台发起检测”:约 `78%~82%`
|
||||
|
||||
## 21:17 最新校正
|
||||
|
||||
刚完成的 `mainland-worker-01` 正式 rollout 已给出最终根因:
|
||||
|
||||
- `job 211 / rollout 6 / release 7`
|
||||
- 发布包下载成功
|
||||
- release 解压成功
|
||||
- `current` 软链切换成功
|
||||
- 最终失败在服务重启:
|
||||
- `restart failed: domaincheck-worker`
|
||||
- `Failed to restart domaincheck-worker.service: Interactive authentication required.`
|
||||
|
||||
这说明:
|
||||
|
||||
- 当前 ReleaseHub 主链路本身已可推进到“切换 current”
|
||||
- 真正未闭环的是 mainland node-agent 的 systemd 权限
|
||||
- 只要 node-agent 仍以 `www` 运行,后续 `deploy.release / service.restart` 都会在 systemd 这一跳失败
|
||||
|
||||
已完成的代码侧修正:
|
||||
|
||||
- `domain-api/deploy/systemd/domain-node-agent.service`
|
||||
- 改为 `User=root`
|
||||
- 改为 `Group=root`
|
||||
- `domain-api/deploy/multi-region/fix_mainland_release_base.sh`
|
||||
- 改为给 node-agent drop-in 写入 `User=root` / `Group=root`
|
||||
|
||||
因此当前真实上线完成度需要再补一句校正:
|
||||
|
||||
- 发布闭环真实可用度:
|
||||
- 不是“发布包模型还没修”
|
||||
- 而是“node-agent 权限模型还差最后一次现网切换”
|
||||
|
||||
## 21:25 最新进展
|
||||
|
||||
worker 侧的现网切换已经完成验证成功:
|
||||
|
||||
- `mainland-worker-01`
|
||||
- 已把 `domaincheck-node-agent` 切为 `root`
|
||||
- 随后重新发起:
|
||||
- `rollout_id = 7`
|
||||
- `job_id = 214`
|
||||
- 最终结果:
|
||||
- `job 214 = success`
|
||||
- `rollout 7 = completed`
|
||||
|
||||
正式成功证据:
|
||||
|
||||
- `agent_completed`
|
||||
- `summary_text = release deployed`
|
||||
- `restart_results[domaincheck-worker].returncode = 0`
|
||||
- `health_check.ok = true`
|
||||
- `systemd ExecStart` 已对齐:
|
||||
- `/opt/domaincheck/current/domainCheck/detect_worker.py`
|
||||
|
||||
因此当前关于发布闭环的真实判断应更新为:
|
||||
|
||||
- worker 发布闭环:
|
||||
- 已从“卡在 systemd restart 权限”推进到“真实成功”
|
||||
- 当前剩余风险不再在 worker
|
||||
- 当前剩余预防项在 controller:
|
||||
- `domaincheck-node-agent` 也应同步切为 `root`
|
||||
|
||||
## 顶部校正
|
||||
|
||||
今天晚上的最新结论,需要覆盖前面一部分偏乐观判断:
|
||||
|
||||
- 最新发布包问题已经定位并修复:
|
||||
- 之前发布包漏掉了 `domainCheck/`
|
||||
- 现在最新签收包 `domaincheck_release_20260419_205437` 已经包含 `domainCheck/`
|
||||
- 但对 `mainland-worker-01` 的正式发布验证证明:
|
||||
- 线上 mainland 节点目前还不满足现有 ReleaseHub 发布模型
|
||||
- 已确认的真实阻塞有两个:
|
||||
- `deploy.release` 在 `mainland-worker-01` 上会因为
|
||||
- `Permission denied: /opt/domaincheck/downloads`
|
||||
- 而直接失败
|
||||
- mainland 两台节点当前 `domaincheck-worker` 的 `ExecStart` 都直接指向:
|
||||
- `/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
- 而不是 `/opt/domaincheck/current/domainCheck/detect_worker.py`
|
||||
|
||||
这两个事实组合起来说明:
|
||||
|
||||
- 当前发布链虽然在控制面上已经成型
|
||||
- 但 mainland 线上节点的安装形态还是旧模式
|
||||
- 所以当前不能再把“已能稳定 rollout 新版本”算进上线完成度
|
||||
|
||||
## 今晚新增硬证据
|
||||
|
||||
- `mainland-worker-01`
|
||||
- `job 204 / rollout 5` 已正式失败回写
|
||||
- 失败原因已收口为:
|
||||
- `install_root not writable: /opt/domaincheck/downloads`
|
||||
- 只读核验得到的实际服务状态仍是旧进程:
|
||||
- `Active since Sun 2026-04-19 18:18:50 CST`
|
||||
- `Main PID = 635924`
|
||||
- `CPU = 18.994s`
|
||||
- 说明 worker 当前并没有切到新包,也没有形成可信的新吞吐样本
|
||||
- `mainland-controller-01`
|
||||
- 当前 `domaincheck-worker` 虽然在高负载运行
|
||||
- 但服务启动路径同样是:
|
||||
- `/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
- 说明 controller 也没有对齐 `current` 软链发布模型
|
||||
|
||||
## 本轮代码侧新增收口
|
||||
|
||||
- 已补齐发布包构建:
|
||||
- `package_domain_release.sh`
|
||||
- `verify_domain_release.sh`
|
||||
- `package_domain_release.ps1`
|
||||
- `verify_domain_release.ps1`
|
||||
- 现在发布包会包含 `domainCheck/`
|
||||
- 已补齐发布执行器的失败可观测性:
|
||||
- `domain-api/app/services/ops_release_executor_core.py`
|
||||
- 现在会在发布目录不可写时显式返回失败结果
|
||||
- 同时补充 `ExecStart` 与 `current` 软链的对齐观测
|
||||
- 已补齐 node-agent 的兜底失败回写:
|
||||
- `domain-api/app/node_agent.py`
|
||||
- 避免以后再出现任务已经炸掉但控制面一直卡在 `running`
|
||||
|
||||
## 本轮最新结论
|
||||
|
||||
新增结论:
|
||||
|
||||
- 检测页观察面已完成一轮线上收口:
|
||||
- `任务日志控制台` 已移到事件表上方
|
||||
- `检测事件流` 已改成独立滚动区
|
||||
- 已在真实线上静态目录重建生产包并通过本机 `3201` 端口验证
|
||||
- 当前如果用户仍看到旧布局,优先判断为浏览器缓存而不是部署未生效
|
||||
- 代理链已完成策略切换:
|
||||
- worker 启动后会主动刷新代理池
|
||||
- 配置更新后也会主动刷新代理池
|
||||
- 后台已能区分:
|
||||
- `等待首刷`
|
||||
- `proxy_validation_zero`
|
||||
- `直入池`
|
||||
- 当前本机最新真实结果是:
|
||||
- 原始代理 `270`
|
||||
- 预验证 `0`
|
||||
- 直入池 `270`
|
||||
- 说明当前问题已经从“代理校验过严导致池为空”切换为“真实任务内动态淘汰失效代理”
|
||||
|
||||
- `mainland-controller-01`
|
||||
- 已确认解除“代理不足即同步刷新、反向压死并发”的旧限制
|
||||
- 海外后台当前已能看到:
|
||||
- `active_threads = 99~100`
|
||||
- `max_threads = 100`
|
||||
- 说明 controller 的 `100` 并发已经真实生效
|
||||
- `mainland-worker-01`
|
||||
- 已重新部署最新版 `detect_worker.py`
|
||||
- 已重新接收新的 `sync-pull` 批次并重进检测:
|
||||
- `开始执行域名检测任务`
|
||||
- `开始检测,刷新代理池`
|
||||
- `代理池刷新完成,共 23 个可用代理`
|
||||
- `开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- 当前 worker 进程本机线程量已到:
|
||||
- `152` 个 OS 线程
|
||||
- 说明它并不是没启动,而是已经进入新批次执行
|
||||
- 当前剩余偏差:
|
||||
- overseas 后台对 `mainland-worker-01.active_threads/current_load` 的显示仍偏低
|
||||
- 这已经从“真实执行问题”收敛为“运行态上报 / 显示口径问题”
|
||||
|
||||
这一轮不是只修了显示问题,而是把“大陆节点真实执行 + worker 日志回传”一起补齐了。
|
||||
|
||||
当前最新结论:
|
||||
|
||||
- controller 的 `pull_tasks -> 本地队列` 断点已经修通
|
||||
- 两台大陆 worker 都已经进入真实镜像队列执行
|
||||
- `mainland-worker-01` 的 `worker_log` 已开始直接回灌 overseas `detect_debug_events`
|
||||
- `runtime_projection` 权限问题已经修复,后台运行态同步恢复
|
||||
- `/api/v1/ops/nodes` 已能证明 controller 的高并发真实生效
|
||||
- 当前剩余问题已经收敛为:
|
||||
- `mainland-worker-01` 运行态显示口径仍需继续对齐
|
||||
- 检测页主计数口径是否完全跟上
|
||||
- 结果统计回推是否持续稳定
|
||||
|
||||
## 当前证据拆分
|
||||
|
||||
### 1. 代码闭环
|
||||
|
||||
已经完成:
|
||||
|
||||
- `sync_push_service.ingest_detect_task_projection`
|
||||
- 不再只导入 `domains`
|
||||
- 已改为同时创建本地 `detect_jobs`
|
||||
- 已改为同时创建本地 `detect_job_items`
|
||||
- 已把 `target_job_id / target_job_code / queued_count / worker_start_ok` 回写到同步结果
|
||||
- `sync_agent`
|
||||
- controller 现在会在每轮 `pull_tasks` 后自动唤起本地 worker
|
||||
- `detect_worker._set_active_cycle_context`
|
||||
- 已兼容 `sync-pull` 控制消息
|
||||
- 不再只读取 `job_id / job_code`
|
||||
- 现在会回退读取 `target_job_id / target_job_code`
|
||||
- 运行态同步链
|
||||
- controller `runtime/detect_runs.json` 权限已修正为 `www:www`
|
||||
- `runtime_projection` 已恢复成功推送
|
||||
|
||||
本地代码验证已通过:
|
||||
|
||||
- `python -m py_compile domain-api/app/services/sync_push_service.py`
|
||||
- `python -m py_compile domain-api/app/services/runtime_control_service.py`
|
||||
- `python -m py_compile domain-api/app/sync_agent.py`
|
||||
- `python -m py_compile domainCheck/detect_worker.py`
|
||||
|
||||
### 2. 接管 / 外部条件闭环
|
||||
|
||||
已经完成:
|
||||
|
||||
- `remote_access_ready = 3/3`
|
||||
- `ssh_ready = 2`
|
||||
- 大陆 controller / worker 都可远程运维
|
||||
- controller `domaincheck-sync-agent` 在线
|
||||
- mainland 两台 `domaincheck-node-agent` 在线
|
||||
|
||||
当前仍依赖你额外输入的部分:
|
||||
|
||||
- 暂无新的 SSH / 接管前置输入缺口
|
||||
- 如果页面仍显示旧状态,最多只需要你浏览器强刷确认,不需要再补 SSH 信息
|
||||
|
||||
### 2.1 前端部署闭环
|
||||
|
||||
已经完成:
|
||||
|
||||
- 在线静态根目录确认:
|
||||
- `/www/wwwroot/getDomain/domain-web/dist`
|
||||
- 在线 Nginx 配置确认:
|
||||
- `/www/server/panel/vhost/nginx/domaincheck_3201.conf`
|
||||
- `/www/server/panel/vhost/nginx/domaincheck_152.53.37.118.conf`
|
||||
- 生产包重建确认:
|
||||
- `vite build` 成功
|
||||
- 线上资源确认:
|
||||
- `DetectView-B9S1WMRT.js`
|
||||
- `DetectView-BFxMNRNR.css`
|
||||
|
||||
说明:
|
||||
|
||||
- 检测页布局调整不是只停留在源码
|
||||
- 已经进入线上可访问静态产物
|
||||
|
||||
### 2.2 代理运行态闭环
|
||||
|
||||
已经完成:
|
||||
|
||||
- worker 启动即触发代理池首刷
|
||||
- 配置变更后自动补刷
|
||||
- API 状态页已能准确显示:
|
||||
- `proxy_not_refreshed_yet`
|
||||
- `proxy_validation_zero`
|
||||
- `宽松入池`
|
||||
|
||||
当前最新证据:
|
||||
|
||||
- `proxy_last_refresh_status = 直入池 270 个(跳过预验证)`
|
||||
- `proxy_last_refresh_total_items = 270`
|
||||
- `proxy_last_validated_count = 0`
|
||||
- `proxy_last_available_count = 270`
|
||||
|
||||
说明:
|
||||
|
||||
- 代理配置本身已成功下发
|
||||
- 代理源接口本身也能返回大量原始代理
|
||||
- 当前不再把“预验证是否通过”作为入池门槛
|
||||
- 现在改为让真实检测来完成失效代理淘汰
|
||||
|
||||
### 3. 检测执行闭环
|
||||
|
||||
这一块现在已经从“怀疑恢复”进入“确认恢复”:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- 已出现:
|
||||
- `从任务队列获取到 800 个需要检测的域名`
|
||||
- `最大线程数: 100`
|
||||
- `当前实际线程数量: 1/100 ... 6/100`
|
||||
- `mainland-worker-01`
|
||||
- 已出现:
|
||||
- `从任务队列获取到 400 个需要检测的域名`
|
||||
- `开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- `当前实际线程数量: 1/50 ... 3/50`
|
||||
- `开始检测域名: 0-demagogo.com`
|
||||
- `开始检测域名: 00123321.com`
|
||||
- `开始检测域名: 001dm.com`
|
||||
|
||||
这说明:
|
||||
|
||||
- `100/50` 已不是“配置已写入但没生效”
|
||||
- 它已经进入真实任务消费
|
||||
- worker 的远端日志也已经跟着真实执行一起回传
|
||||
|
||||
### 4. 海外后台可视证据
|
||||
|
||||
`/api/v1/ops/nodes` 当前已显示:
|
||||
|
||||
- `summary.remote_access_ready = 3`
|
||||
- `summary.participating = 3`
|
||||
- `summary.dispatch_active = 1`
|
||||
|
||||
并且大陆两台都已经被判定为真实参与者:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `agent_state = online_busy`
|
||||
- `participation_state = recent_throughput`
|
||||
- `processed_recent = 115`
|
||||
- `processed_per_minute = 7.67`
|
||||
- `detect_runtime.max_threads = 100`
|
||||
- `mainland-worker-01`
|
||||
- `agent_state = online_busy`
|
||||
- `participation_state = recent_throughput`
|
||||
- `processed_recent = 632`
|
||||
- `processed_per_minute = 42.13`
|
||||
- `detect_runtime.max_threads = 50`
|
||||
|
||||
这说明:
|
||||
|
||||
- 海外后台已经不只是看到“在线”
|
||||
- 现在已经能看到大陆节点的实际吞吐
|
||||
|
||||
## 本轮新增硬证据
|
||||
|
||||
### 证据 1:controller 的镜像队列已经真正落库
|
||||
|
||||
`sync-agent` 现场日志已出现:
|
||||
|
||||
- `target_job_code = sync-overseas-7380`
|
||||
- `queued_count = 200`
|
||||
- `worker_start_ok = True`
|
||||
|
||||
并持续产生:
|
||||
|
||||
- `sync-overseas-7383`
|
||||
- `sync-overseas-7386`
|
||||
- `sync-overseas-7392`
|
||||
- `sync-overseas-7417`
|
||||
|
||||
说明:
|
||||
|
||||
- 大陆 controller 现在不是只拉数据
|
||||
- 而是在持续形成可执行批次
|
||||
|
||||
### 证据 2:两台大陆 worker 都已转入真实队列
|
||||
|
||||
现场日志已明确出现:
|
||||
|
||||
- controller:
|
||||
- `从任务队列获取到 800 个需要检测的域名`
|
||||
- worker:
|
||||
- `从任务队列获取到 400 个需要检测的域名`
|
||||
|
||||
说明:
|
||||
|
||||
- 当前不是兼容旧链路假运行
|
||||
- 是镜像队列真运行
|
||||
|
||||
### 证据 3:runtime_projection 已恢复成功
|
||||
|
||||
修复前:
|
||||
|
||||
- `refresh runtime_projection failed: [Errno 13] Permission denied`
|
||||
|
||||
修复后:
|
||||
|
||||
- 最新 `sync-agent` 日志已出现:
|
||||
- `sync_state = success`
|
||||
- `runtime_projection -> 投影推送成功`
|
||||
|
||||
说明:
|
||||
|
||||
- 后台运行态刷新和日志窗口不再被 controller 本地权限卡死
|
||||
|
||||
### 证据 4:`mainland-worker-01` 的 `worker_log` 已进入 overseas
|
||||
|
||||
`/api/v1/runtime/debug-events` 当前已能看到:
|
||||
|
||||
- `mainland-worker-01 -> 开始执行检测任务,来源: redis-control`
|
||||
- `mainland-worker-01 -> 开始执行域名检测任务,正在加载配置`
|
||||
- `mainland-worker-01 -> 开始检测,正在刷新代理池`
|
||||
- `mainland-worker-01 -> 代理池刷新完成,共 7 个可用代理,来源链接 6 个,原始 265 个,验证 150 个`
|
||||
- `mainland-worker-01 -> 从任务队列获取到 400 个需要检测的域名`
|
||||
- `mainland-worker-01 -> 开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 1/50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 2/50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 3/50`
|
||||
|
||||
说明:
|
||||
|
||||
- worker 的真实执行链已经进入 overseas 的日志视图
|
||||
- “后台看不到大陆 worker 在干活”这一层已经闭合
|
||||
|
||||
## 当前口径说明
|
||||
|
||||
这里有一个非常关键的判断口径已经变化:
|
||||
|
||||
- 大陆节点当前执行的是“海外任务在大陆本地落镜像队列,再把运行态和结果同步回海外”
|
||||
- 因此不能再只盯中央原生 `detect_job_items.claimed/running`
|
||||
- 现在应该同时看:
|
||||
- `/api/v1/ops/nodes`
|
||||
- `processed_recent`
|
||||
- `processed_per_minute`
|
||||
- `detect_runtime.active_threads/max_threads`
|
||||
- 大陆 controller 本地 `sync-overseas-*` 队列
|
||||
|
||||
如果只看中央原生队列,会误判“大陆没有参与”。
|
||||
|
||||
## 当前已闭合的问题
|
||||
|
||||
已闭合:
|
||||
|
||||
- controller `pull_tasks` 只导入 domain、不导入本地队列
|
||||
- 大陆 worker 长时间卡在旧检测会话导致忽略新启动指令
|
||||
- controller `runtime_projection` 因文件属主错误无法推送
|
||||
- 大陆两台“在线但不确定是否真实执行”的状态模糊
|
||||
|
||||
## 当前剩余问题
|
||||
|
||||
当前剩余问题已经缩成两个最小项:
|
||||
|
||||
- Detect 页面主计数 `pending/completed/running` 是否继续推进
|
||||
- 结果统计回推是否稳定,而不只是日志链路先恢复
|
||||
|
||||
换句话说:
|
||||
|
||||
- 现在不是接管问题
|
||||
- 不是链路不通问题
|
||||
- 不是日志完全回不来问题
|
||||
- 而是最后一层“主计数推进 + 结果统计收口”问题
|
||||
|
||||
## 当前是否可以继续跑检测测试
|
||||
|
||||
当前结论:
|
||||
|
||||
- 可以继续跑检测测试
|
||||
- 而且现在已经具备“后台可观测 + 大陆真实参与”的条件
|
||||
|
||||
## 当前是否建议直接上线
|
||||
|
||||
当前结论:
|
||||
|
||||
- 已接近可上线状态
|
||||
- 但我仍建议把它视为“准上线收口态”,不是最终完全签收态
|
||||
|
||||
原因:
|
||||
|
||||
- 主执行链已经恢复
|
||||
- 但还需要再确认 1 到 2 个同步周期内页面口径与吞吐稳定性
|
||||
|
||||
## 当前优先级判断
|
||||
|
||||
最高优先级:
|
||||
|
||||
- `J2-检测执行收口批`
|
||||
|
||||
当前不应继续推进:
|
||||
|
||||
- 新控制面功能
|
||||
- 新模块
|
||||
- 新页面
|
||||
- 发布动作
|
||||
- 与检测执行收口无关的工作
|
||||
|
||||
## 完成下一轮后的预期
|
||||
|
||||
如果下一轮确认:
|
||||
|
||||
- Detect 页面主计数已跟上
|
||||
- 日志窗口持续刷新
|
||||
- `detect_result_projection` 持续推进
|
||||
- `processed_recent / processed_per_minute` 持续增长
|
||||
|
||||
则整体可上线程度预计可提升到:
|
||||
|
||||
- `96%~98%`
|
||||
|
||||
在那之前,当前口径应保持保守。
|
||||
41
docs/ops_center_runtime/NIGHT_PACKAGE_20260419_0121.md
Normal file
41
docs/ops_center_runtime/NIGHT_PACKAGE_20260419_0121.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# NIGHT PACKAGE 2026-04-19 01:21
|
||||
|
||||
执行窗口:
|
||||
|
||||
- 开始时间:`2026-04-19 01:21 CST`
|
||||
- 截止时间:`2026-04-20 12:00 CST`
|
||||
|
||||
范围边界:
|
||||
|
||||
- 只围绕当前收口目标执行
|
||||
- 不进入新实现
|
||||
- 不扩展控制面功能
|
||||
- 不新增页面、模块或专题文档
|
||||
|
||||
夜间任务包内容:
|
||||
|
||||
1. 周期性复查:
|
||||
- `go-live-summary`
|
||||
- `stack-diagnosis`
|
||||
- `release-launchpad`
|
||||
- `playbook-runs`
|
||||
- `overseas-control-01 scene-log`
|
||||
2. 若日志样本再次出现缺口:
|
||||
- 自动执行 `log-sync-recover`
|
||||
- 自动执行一次 `run_inspection_participating`
|
||||
3. 若只剩历史 `playbook_runs_need_attention`:
|
||||
- 最多补 3 轮安全的 `inspection.standard`
|
||||
- 目的仅为刷新近期成功 run,推动历史告警窗口收敛
|
||||
4. 到达以下任一条件即停止:
|
||||
- 到 `2026-04-20 12:00 CST`
|
||||
- 或者:
|
||||
- `log_sync_state = full_capture`
|
||||
- `issue_total = 0`
|
||||
- `problem_runs_total = 0`
|
||||
|
||||
输出位置:
|
||||
|
||||
- 运行日志目录:
|
||||
- [docs/ops_center_runtime/night_runs](/www/wwwroot/getDomain/docs/ops_center_runtime/night_runs)
|
||||
- 停止后自动生成报告:
|
||||
- `night_run_*_report.md`
|
||||
564
docs/ops_center_runtime/TASK_BOARD.md
Normal file
564
docs/ops_center_runtime/TASK_BOARD.md
Normal file
@@ -0,0 +1,564 @@
|
||||
# TASK_BOARD
|
||||
|
||||
更新时间:2026-04-19 21:25 CST
|
||||
|
||||
## 2026-04-20 主线切换说明
|
||||
|
||||
从这一刻开始,当前工作重心正式切回:
|
||||
|
||||
- 先跑通主任务流程
|
||||
- 先推进 7 个大任务的测试与验收
|
||||
- 并发、代理、DB 往返、展示层等细节优化先封存,不再抢主线
|
||||
|
||||
细节优化不删除,统一视为 backlog:
|
||||
|
||||
- worker pool 持续补位
|
||||
- claimed 回弹压缩
|
||||
- 高频 DB 更新继续合并
|
||||
- 代理失败链和等待窗口继续压缩
|
||||
- 运营视角页面继续细化
|
||||
|
||||
这些后续继续做,但不再打断主任务验收顺序。
|
||||
|
||||
当前主口径:
|
||||
|
||||
1. 大任务 1 真实验收闭环
|
||||
2. 大任务 2 controller 编排闭环
|
||||
3. 大任务 3 统一结果状态机闭环
|
||||
4. 大任务 4 本地控制状态 + syncer/finalizer 闭环
|
||||
5. 大任务 5 固定 worker pool 落地
|
||||
6. 大任务 6 时光机一期接入
|
||||
7. 大任务 7 运营视角面板闭环
|
||||
|
||||
## 21:17 最新补充
|
||||
|
||||
刚刚这轮真实 rollout 已经把 mainland worker 的最后一层阻塞拿实:
|
||||
|
||||
- `mainland-worker-01`
|
||||
- `release_id = 7`
|
||||
- `rollout_id = 6`
|
||||
- `job_id = 211`
|
||||
- 发布链路并不是卡在下载或解压:
|
||||
- 发布包 `domaincheck_release_20260419_205437` 已下载到 `/opt/domaincheck/downloads`
|
||||
- release 已解压到 `/opt/domaincheck/releases/domaincheck_release_20260419_205437`
|
||||
- `/opt/domaincheck/current` 已切到新 release
|
||||
- 最终失败点已经明确:
|
||||
- `restart failed: domaincheck-worker`
|
||||
- systemd 原因:
|
||||
- `Interactive authentication required`
|
||||
- 这说明当前 mainland 节点的 `domaincheck-node-agent` 虽然能写发布目录,但因为以 `www` 身份运行,无法执行:
|
||||
- `systemctl restart domaincheck-worker`
|
||||
|
||||
当前新的唯一主阻塞已经进一步收敛为:
|
||||
|
||||
- node-agent systemd 运行身份不对
|
||||
- 需要把 `domaincheck-node-agent` 改成 `root` 运行,发布链最后一跳才能闭环
|
||||
|
||||
本轮已在仓库内同步修正:
|
||||
|
||||
- `domain-api/deploy/systemd/domain-node-agent.service`
|
||||
- `User=root`
|
||||
- `Group=root`
|
||||
- `domain-api/deploy/multi-region/fix_mainland_release_base.sh`
|
||||
- node-agent drop-in 现在也会显式写入:
|
||||
- `User=root`
|
||||
- `Group=root`
|
||||
|
||||
## 21:25 worker rollout 收口
|
||||
|
||||
`mainland-worker-01` 已完成新一轮正式 rollout 收口成功:
|
||||
|
||||
- `release_id = 7`
|
||||
- `rollout_id = 7`
|
||||
- `job_id = 214`
|
||||
|
||||
结果确认:
|
||||
|
||||
- `job 214 = success`
|
||||
- `rollout 7 = completed`
|
||||
- `mainland-worker-01` 已恢复为:
|
||||
- `agent_state = online_busy`
|
||||
- 最近心跳恢复正常
|
||||
|
||||
控制面完成证据:
|
||||
|
||||
- `agent_completed`
|
||||
- `summary_text = release deployed`
|
||||
- `restart_results`
|
||||
- `domaincheck-worker.returncode = 0`
|
||||
- `health_check.ok = true`
|
||||
- `execstart_alignment.mismatched_services = []`
|
||||
|
||||
这说明 worker 当前已经真正完成:
|
||||
|
||||
- 新包下载
|
||||
- release 解压
|
||||
- `current` 切换
|
||||
- `domaincheck-worker` 重启
|
||||
- 健康检查通过
|
||||
|
||||
当前关于 mainland rollout 的唯一剩余预防项变成:
|
||||
|
||||
- `mainland-controller-01` 也应该同步把 `domaincheck-node-agent` 切到 `root`
|
||||
- 否则后续 controller 自身执行 `deploy.release / service.restart` 时还会踩到同类 systemd 权限问题
|
||||
|
||||
## 顶部校正
|
||||
|
||||
今天晚上的最新排查已经把当前主阻塞重新定性,之前“大陆两台已经完全进入统一新镜像执行”的判断需要收紧。
|
||||
|
||||
当前新增硬结论:
|
||||
|
||||
- 最新正式发布包已经重打并签收通过:
|
||||
- `domaincheck_release_20260419_205437`
|
||||
- 发布包现在已经确实包含 `domainCheck/`
|
||||
- 对 `mainland-worker-01` 发起正式 smart rollout 后,真实失败原因已经拿到:
|
||||
- `job 204 / rollout 5`
|
||||
- 本次失败对应的正式 Release 版本仍是:
|
||||
- `domaincheck_release_20260419_203933`
|
||||
- 失败原因:
|
||||
- `Permission denied: /opt/domaincheck/downloads`
|
||||
- 该失败已通过正式 agent complete 回写,后台不再是假 `running`
|
||||
- `mainland-worker-01` 当前运行中的 `domaincheck-worker` 仍是旧进程:
|
||||
- `Main PID = 635924`
|
||||
- `Active since = 2026-04-19 18:18:50 CST`
|
||||
- `CPU = 18.994s`
|
||||
- 说明它不是高吞吐新进程,而是老进程长期挂着
|
||||
- `mainland-controller-01` 当前运行中的 `domaincheck-worker` 虽然活跃,但服务启动路径同样是:
|
||||
- `/opt/domaincheck/domainCheck/detect_worker.py`
|
||||
- 两台 mainland 节点当前 `domaincheck-worker` 的 systemd 启动路径都不是:
|
||||
- `/opt/domaincheck/current/domainCheck/detect_worker.py`
|
||||
|
||||
这意味着:
|
||||
|
||||
- 当前 ReleaseHub 的 `current -> release_version` 切换模型,与线上 mainland 节点的实际服务启动路径不一致
|
||||
- 即使发布包和签收链已经修好,线上节点也还没有具备“按当前发布模型热切版本”的条件
|
||||
- 当前唯一主阻塞已经从“并发参数是否下发”切换成:
|
||||
- mainland 节点发布权限/目录模型不匹配
|
||||
- mainland 节点服务启动路径与发布模型不匹配
|
||||
|
||||
## 当前主批次
|
||||
|
||||
唯一主批次:`J2-检测执行收口批`
|
||||
|
||||
目标:
|
||||
|
||||
- 不进入新页面
|
||||
- 不扩展控制面
|
||||
- 不新增发布动作
|
||||
- 只收口三件已经缩小到运行面的事情:
|
||||
- 大陆节点必须真正进入统一镜像队列,而不是停留在兼容旧链路
|
||||
- 后台必须能看到大陆节点的实时运行态与日志
|
||||
- `100/50` 并发配置要从“已下发”推进到“真实有参与吞吐”
|
||||
|
||||
## 本轮最新状态
|
||||
|
||||
### 20:53 最新阻塞结论
|
||||
|
||||
- `mainland-worker-01` smart rollout 已真实失败,不再继续误判为执行中
|
||||
- 失败证据:
|
||||
- node-agent 日志:
|
||||
- `2026-04-19 20:40:15 [node-agent] loop error: [Errno 13] Permission denied: '/opt/domaincheck/downloads'`
|
||||
- 发布任务:
|
||||
- `job 204 = failed`
|
||||
- 发布批次:
|
||||
- `rollout 5 = failed`
|
||||
- 当前不应该继续把精力放在前端展示或并发口径微调上
|
||||
- 当前必须先收口:
|
||||
- mainland 节点 `deploy.release` 所需目录权限
|
||||
- mainland 节点 systemd `ExecStart` 与 `/opt/domaincheck/current` 的一致性
|
||||
|
||||
这轮已经完成从“控制链打通”到“真实执行恢复 + worker 日志回传恢复”的关键跨越。
|
||||
|
||||
### 本轮前端已上线校验
|
||||
|
||||
- 检测页 `任务日志控制台` 已调整到事件列表上方
|
||||
- `检测事件流` 已改成独立滚动区:
|
||||
- 表格 `max-height = 320`
|
||||
- 避免事件越积越多把整个页面继续向下撑长
|
||||
- 已在线上实际静态目录重新构建:
|
||||
- `/www/wwwroot/getDomain/domain-web/dist`
|
||||
- 已确认线上 Nginx 指向该目录:
|
||||
- `domaincheck_3201.conf`
|
||||
- `domaincheck_152.53.37.118.conf`
|
||||
- 已通过 `http://127.0.0.1:3201/` 返回 `200` 且加载新资源:
|
||||
- `DetectView-B9S1WMRT.js`
|
||||
- `DetectView-BFxMNRNR.css`
|
||||
|
||||
### 本轮代理链已收口
|
||||
|
||||
- 已修复 worker 在“代理配置已下发但尚未开始检测”时长期停留 `未刷新` 的问题
|
||||
- `domaincheck-worker` 现在会在以下时机主动触发代理池刷新:
|
||||
- worker 启动后
|
||||
- `proxy_config / thread_count / node_thread_counts / runtime_settings` 更新后
|
||||
- 当前后台状态已不再误报“未刷新”
|
||||
- 代理策略已切到:
|
||||
- 只去掉过期 / 非法代理
|
||||
- 跳过预验证
|
||||
- 直接入池执行
|
||||
- 真实失败后立即淘汰并补刷
|
||||
- 最新实测结果已经明确:
|
||||
- 原始代理 `270` 个
|
||||
- 预验证 `0` 个
|
||||
- 当前可用代理 `270` 个
|
||||
- 最近状态:
|
||||
- `proxy_last_refresh_status = 直入池 270 个(跳过预验证)`
|
||||
- `available_proxy_count = 270`
|
||||
|
||||
### 本轮已完成
|
||||
|
||||
- `sync_push_service`
|
||||
- 已修复 `detect_task_ingest` 只落 `domains`、不落本地 `detect_jobs/detect_job_items` 的缺口
|
||||
- controller 现在会为拉回来的海外批次持续创建本地镜像任务:
|
||||
- `sync-overseas-7380`
|
||||
- `sync-overseas-7383`
|
||||
- `sync-overseas-7392`
|
||||
- 持续增长中
|
||||
- `mainland-controller-01`
|
||||
- 已重启 `domaincheck-worker`
|
||||
- 已明确进入真实队列:
|
||||
- `从任务队列获取到 800 个需要检测的域名`
|
||||
- `最大线程数: 100`
|
||||
- `当前实际线程数量: 1/100 ... 6/100`
|
||||
- `mainland-worker-01`
|
||||
- 已修复 `sync-pull` 控制消息上下文绑定缺口:
|
||||
- `detect_worker._set_active_cycle_context` 现在会读取
|
||||
- `target_job_id`
|
||||
- `target_job_code`
|
||||
- 已重启 `domaincheck-worker`
|
||||
- 已明确进入真实队列:
|
||||
- `从任务队列获取到 400 个需要检测的域名`
|
||||
- `最大线程数: 50`
|
||||
- `当前实际线程数量: 1/50 ... 3/50`
|
||||
- 已明确把运行日志回传到 overseas:
|
||||
- `开始执行检测任务,来源: redis-control`
|
||||
- `开始执行域名检测任务,正在加载配置`
|
||||
- `开始检测,正在刷新代理池`
|
||||
- `开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- `当前实际线程数量: 1/50`
|
||||
- `当前实际线程数量: 2/50`
|
||||
- `当前实际线程数量: 3/50`
|
||||
- `runtime_projection`
|
||||
- 已定位 controller `domain-api/runtime/detect_runs.json` 权限错误
|
||||
- 已把 `runtime` 目录和 `detect_runs.json` 改回 `www:www`
|
||||
- `domaincheck-sync-agent` 最新日志已从
|
||||
- `partial_success`
|
||||
- 变成:
|
||||
- `sync_state = success`
|
||||
- `runtime_projection -> 投影推送成功`
|
||||
- 海外控制面 `/api/v1/ops/nodes`
|
||||
- 现已明确看到三台节点都在参与
|
||||
- `remote_access_ready = 3`
|
||||
- `participating = 3`
|
||||
- `mainland-controller-01.is_current_participant = true`
|
||||
- `mainland-worker-01.is_current_participant = true`
|
||||
|
||||
### 当前最关键的新证据
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `processed_recent = 115`
|
||||
- `processed_per_minute = 7.67`
|
||||
- `detect_runtime.max_threads = 100`
|
||||
- `mainland-worker-01`
|
||||
- `processed_recent = 632`
|
||||
- `processed_per_minute = 42.13`
|
||||
- `detect_runtime.max_threads = 50`
|
||||
- `overseas-control-01`
|
||||
- 仍在执行中央原生队列
|
||||
- 当前判断:
|
||||
- 大陆节点已经不是“纸面在线”
|
||||
- 已经是真实参与检测执行
|
||||
|
||||
## 当前主判断
|
||||
|
||||
### 本轮新增结论
|
||||
|
||||
- `mainland-controller-01`
|
||||
- 已修复“代理数量不足反向限制并发”的热路径问题
|
||||
- 当前海外后台已稳定看到:
|
||||
- `active_threads ~= 99~100`
|
||||
- `max_threads = 100`
|
||||
- 说明 `100` 并发不再只是配置已下发,而是已进入真实运行态
|
||||
- `mainland-worker-01`
|
||||
- 已重新部署同版 `detect_worker.py`
|
||||
- 已重新接收到新的 `sync-pull` 批次:
|
||||
- `source_record_id = 7679`
|
||||
- `target_job_code = sync-overseas-7679`
|
||||
- 已完成代理抽样校验并进入:
|
||||
- `开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- 当前剩余问题已经缩成:
|
||||
- worker 本机已启动新批次并创建线程
|
||||
- 但海外后台对 `mainland-worker-01.active_threads` 的显示仍偏低,和本机进程线程量不完全一致
|
||||
|
||||
### 当前唯一剩余收口点
|
||||
|
||||
- 不再是 controller 并发限制问题
|
||||
- 当前唯一剩余收口点变成:
|
||||
- `mainland-worker-01` 的运行态上报口径仍需继续和真实执行量对齐
|
||||
- 以及检测主计数 `pending/completed/running` 继续推进
|
||||
|
||||
### 已经收口的部分
|
||||
|
||||
- 大陆节点不再停留在 `pending_bootstrap`
|
||||
- Agent + SSH 接管已经完成
|
||||
- `sync-agent pull_tasks` 已经真正生成本地镜像队列
|
||||
- 两台大陆 worker 已经真正吃到 `detect_job_items`
|
||||
- 后台运行态同步链已经恢复
|
||||
|
||||
### 当前剩余问题
|
||||
|
||||
- Detect 页面日志窗口已经不再是单节点
|
||||
- `/api/v1/detect/status` 已出现:
|
||||
- `remote_log_node_count = 2`
|
||||
- `remote_log_nodes = ["mainland-controller-01", "mainland-worker-01"]`
|
||||
- 当前剩余问题缩成一个最小点:
|
||||
- 检测页主计数 `pending/completed/running` 还没有跟着这轮大陆执行立即推进
|
||||
- 前端布局问题已收口,后续不再停留在“页面结构挡住观察”
|
||||
- 代理链当前也已收口到真实口径,不再停留在“配置有了但没刷新”
|
||||
- 下一步应继续观察这 `270` 个直入池代理在真实检测里的淘汰速度与吞吐提升
|
||||
- 现在更应该同时看:
|
||||
- `/api/v1/detect/status`
|
||||
- `/api/v1/runtime/debug-events`
|
||||
- `/api/v1/ops/nodes`
|
||||
- worker `current actual threads` 日志
|
||||
|
||||
## 下一步唯一主批次
|
||||
|
||||
唯一主批次保持为:`J2-检测执行收口批`
|
||||
|
||||
下一步只做:
|
||||
|
||||
- 继续观察 Detect 页面主计数是否跟上最新运行态
|
||||
- 继续确认 `detect_result_projection` / 结果统计回推是否稳定推进
|
||||
- 继续收口 `mainland-worker-01` 的运行态上报,使后台显示与本机真实线程量一致
|
||||
- 若仍有显示偏差,只修统计/上报口径,不新扩功能
|
||||
|
||||
## 候选批次
|
||||
|
||||
### Candidate J3
|
||||
|
||||
名称:结果计数收口批
|
||||
|
||||
进入条件:
|
||||
|
||||
- 节点已经真实执行
|
||||
- 日志窗口已经恢复
|
||||
- 但 Detect 页面主计数仍不前进
|
||||
|
||||
只做:
|
||||
|
||||
- 复核 `detect_result_projection`
|
||||
- 复核结果统计回推
|
||||
- 不改控制面结构
|
||||
|
||||
### Candidate J4
|
||||
|
||||
名称:吞吐稳定性观察批
|
||||
|
||||
进入条件:
|
||||
|
||||
- 页面口径已恢复
|
||||
- 继续确认大陆两节点吞吐是否稳定,不再回落
|
||||
|
||||
只做:
|
||||
|
||||
- 继续观察 `processed_recent`
|
||||
- 继续观察代理池质量
|
||||
- 继续观察 `active_threads/max_threads`
|
||||
|
||||
## 暂停项
|
||||
|
||||
以下任务现在不应继续推进:
|
||||
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 新发布动作
|
||||
- 新专题文档
|
||||
- 与检测执行收口无关的控制面增强
|
||||
|
||||
## 关键证据
|
||||
|
||||
### 证据 1:镜像队列已经落地
|
||||
|
||||
controller `sync-agent` 最新 `task pull tick` 已出现:
|
||||
|
||||
- `target_job_id`
|
||||
- `target_job_code`
|
||||
- `queued_count = 200`
|
||||
- `worker_start_ok = True`
|
||||
|
||||
说明:
|
||||
|
||||
- controller 现在不是只同步域名
|
||||
- 而是在本地持续创建可执行队列
|
||||
|
||||
### 证据 2:大陆 worker 已进入真实队列
|
||||
|
||||
现场日志已经明确出现:
|
||||
|
||||
- `mainland-controller-01 -> 从任务队列获取到 800 个需要检测的域名`
|
||||
- `mainland-worker-01 -> 从任务队列获取到 400 个需要检测的域名`
|
||||
|
||||
说明:
|
||||
|
||||
- “并发没起来”的主要根因已经修正
|
||||
- 它们不是在跑旧兼容链路
|
||||
|
||||
### 证据 3:运行态同步已恢复
|
||||
|
||||
controller `sync-agent` 最新日志已经出现:
|
||||
|
||||
- `sync_state = success`
|
||||
- `runtime_projection -> 投影推送成功`
|
||||
|
||||
说明:
|
||||
|
||||
- 后台运行态/日志窗口链路已经不再被权限错误卡死
|
||||
|
||||
### 证据 4:海外 `/ops/nodes` 已把大陆节点判定为真实参与者
|
||||
|
||||
当前海外控制面已经显示:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `online_busy`
|
||||
- `is_current_participant = true`
|
||||
- `processed_recent = 115`
|
||||
- `mainland-worker-01`
|
||||
- `online_busy`
|
||||
- `is_current_participant = true`
|
||||
- `processed_recent = 632`
|
||||
|
||||
说明:
|
||||
|
||||
- 现在大陆两台都已进入真实参与态
|
||||
- 下一步不再是接管问题,而是页面口径与吞吐稳定性问题
|
||||
|
||||
### 证据 5:Detect 页面远端日志已恢复双节点
|
||||
|
||||
当前 `/api/v1/detect/status` 已显示:
|
||||
|
||||
- `remote_log_node_count = 2`
|
||||
- `remote_log_nodes = ["mainland-controller-01", "mainland-worker-01"]`
|
||||
|
||||
最近日志样本已出现:
|
||||
|
||||
- `mainland-worker-01 -> 从任务队列获取到 400 个需要检测的域名`
|
||||
- `mainland-worker-01 -> 开始创建线程,当前批次域名数: 400,最大线程数: 50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 1/50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 2/50`
|
||||
- `mainland-worker-01 -> 当前实际线程数量: 3/50`
|
||||
|
||||
说明:
|
||||
|
||||
- worker 不再是“只在节点本地运行、页面看不到”
|
||||
- 检测页日志链已经真正接上 mainland worker
|
||||
|
||||
### 证据 6:full_capture 已开启,但源日志时间没有继续前进
|
||||
|
||||
节点现场日志最新可见记录仍停在较早时间:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- 最近样本集中在 `01:00:23`
|
||||
- `mainland-worker-01`
|
||||
- 最近样本集中在 `01:00:35`
|
||||
|
||||
额外 35 秒观察窗口结果:
|
||||
|
||||
- `capture_at` 没有继续前进
|
||||
- `source_msg` 里的源日志时间也没有继续前进
|
||||
|
||||
说明:
|
||||
|
||||
- 不是“全量日志没开”
|
||||
- 也不是“日志回传没回来”
|
||||
- 而是执行进程这段时间确实没有继续产生日志
|
||||
|
||||
### 证据 7:worker 控制消息补偿链已在线上验证生效
|
||||
|
||||
之前运行态存在一个真实风险:
|
||||
|
||||
- `runtime.start_detection` 成功只代表“控制消息已发布到 Redis”
|
||||
- 如果 worker 在线但恰好漏收了 pubsub 消息
|
||||
- pending 指令只在启动或重连时消费,就可能造成:
|
||||
- 页面显示“已启动”
|
||||
- 但 worker 实际没有进入新的执行流
|
||||
|
||||
当前已完成最小修复:
|
||||
|
||||
- 每条控制消息带 `request_id`
|
||||
- worker 心跳会主动补偿消费 pending 指令
|
||||
- worker 真正收到并处理后,会按 `request_id` 清理 pending
|
||||
|
||||
这一步现在已经不再是“待部署假设”,而是已被线上日志确认生效:
|
||||
|
||||
- `mainland-worker-01` 已从 pending 指令恢复执行
|
||||
- `mainland-controller-01` 在修正 Redis 环境后,也已重新接受并执行 `start_detection`
|
||||
|
||||
## 当前结论
|
||||
|
||||
当前结论要收敛成一句话:
|
||||
|
||||
- 接管链路已基本完成
|
||||
- 同步链路已至少成功贯通一次
|
||||
- 当前主阻塞仍是检测执行面没有恢复到“持续产出”
|
||||
- 但代码级控制链缺口已经闭合
|
||||
- 当前唯一剩余现场阻塞可以收紧为:
|
||||
- `mainland-controller-01` 代理池可用性为 `0`
|
||||
- worker 侧时光机异常仍是次级噪音,不应继续放大
|
||||
|
||||
## 下一步唯一主批次
|
||||
|
||||
唯一主批次维持为:`J2-检测执行停滞收口批`
|
||||
|
||||
本批次唯一目标:
|
||||
|
||||
- 保持当前不扩功能
|
||||
- 只围绕 controller 代理池可用性为 `0` 做收口
|
||||
- 继续观察修正后的 controller 是否开始产出 domain 级结果
|
||||
- 若仍无结果增长,则只给出代理层最小补救路径
|
||||
|
||||
## 候选批次
|
||||
|
||||
### Candidate J3
|
||||
|
||||
名称:检测执行恢复验证批
|
||||
|
||||
进入条件:
|
||||
|
||||
- `J2` 明确根因后
|
||||
- 代理或外部站点依赖恢复
|
||||
- 再观察 `domain_*` 是否重新增长
|
||||
|
||||
### Candidate J4
|
||||
|
||||
名称:上线签收证据批
|
||||
|
||||
进入条件:
|
||||
|
||||
- `J3` 确认检测重新持续产出
|
||||
- `go-live-summary` 只剩历史 attention
|
||||
|
||||
## 暂停项
|
||||
|
||||
继续暂停:
|
||||
|
||||
- 新页面
|
||||
- 新模块
|
||||
- 控制面增强
|
||||
- 发布动作
|
||||
- 与检测执行停滞无关的工作
|
||||
|
||||
## 下一轮唯一动作
|
||||
|
||||
下一轮唯一应该继续做的事情:
|
||||
|
||||
- 只做 controller 代理收口:
|
||||
- 继续复查 controller `domaincheck-worker` 日志
|
||||
- 观察是否从 `当前无可用代理` 转为有可用代理
|
||||
- 继续复查 `/api/v1/detect/job/active`
|
||||
- 继续复查 `/api/v1/runtime/sync-summary`
|
||||
- 继续复查 recent domain events 是否出现 controller / 新 completed
|
||||
- 唯一判断问题是:
|
||||
- controller 代理池恢复后,completed 是否开始继续增长
|
||||
- 是否仍是 `近窗吞吐 0`
|
||||
- 是否仍是 `controller 可用代理数 0`
|
||||
- 代理恢复后 `domain_*` 是否重新增长
|
||||
@@ -0,0 +1 @@
|
||||
680339
|
||||
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"base_url":"http://127.0.0.1:8100","generated_at":"2026-04-19 01:29:38","go_live_status":"attention","publish_ready":false,"publish_status":"attention","publish_status_label":"可发布但建议先复核","publish_summary":"当前没有硬阻断,但仍有上线前关注项,建议先完成复核再正式发版。","stack_status":"attention","contracts_ready":true,"contracts_total":11,"launchpad_status":"attention","launchpad_status_label":"待补执行面","launchpad_recommended_action_code":"fix_managed_nodes","launchpad_recommended_target_node_code":"","launchpad_recommended_recovery_label":"","launchpad_recommended_recovery_summary":"来自 overview.recommendation.primary_action_code","launchpad_onboarding_bootstrap_pending_nodes":0,"launchpad_onboarding_acceptance_ready_nodes":0,"route_surface_complete":true,"route_surface_missing_keys":[],"route_surface_declares_bootstrap_plan":true,"runtime_schema_stale":false,"repository_capabilities":{"supports_install_command_block":true,"supports_multi_layout_bootstrap":true},"managed_enabled":3,"remote_access_ready":3,"queue_dead_letter_nodes":0,"activity_start_delivery_issue_total":0,"participating_nodes_total":3,"log_sync_enabled":true,"log_sync_state":"full_capture","log_sync_mode":"full","log_sync_covered_nodes":3,"log_sync_missing_node_codes":[],"next_step_action_code":"focus_playbook_run","next_step_reason":"来自 overview.recommendation.primary_action_code","operator_lane":"ops_jobs","operator_title":"按总检默认下一步继续处理","operator_primary_command_key":"focus_playbook_run","publish_blocking_reasons":[],"publish_warnings":["stack_diagnosis=attention","release_launchpad=attention"],"blocking_reasons":[],"warnings":["stack_diagnosis=attention","release_launchpad=attention"],"recommended_commands":{"stack_summary":"bash domain-api/deploy/multi-region/check_ops_center_stack.sh http://127.0.0.1:8100 summary","contracts":"bash domain-api/deploy/multi-region/check_ops_contracts.sh http://127.0.0.1:8100","ops_plane":"bash domain-api/deploy/multi-region/check_ops_plane.sh http://127.0.0.1:8100","release_hub":"bash domain-api/deploy/multi-region/check_release_hub.sh http://127.0.0.1:8100","inspection":"bash domain-api/deploy/multi-region/check_ops_inspection.sh http://127.0.0.1:8100","overview":"bash domain-api/deploy/multi-region/drive_ops_center.sh overview http://127.0.0.1:8100","go_live_recover":"bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover http://127.0.0.1:8100","doctor_export":"bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-export /tmp/domaincheck-go-live http://127.0.0.1:8100","next_step":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 focus_playbook_run","log_sync_logs":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 open_worker_logs_participating","log_sync_inspection":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 run_inspection_participating"},"source_refs":{"stack_diagnosis_contract_key":"ops_stack_diagnosis_contract","contracts_registry_version":"2026-04-18","runtime_build_commit_sha":"246838ae4c07","release_focus_ref":{"kind":"release_hub","release_id":2,"release_version":"domaincheck_release_20260418_013833","channel":"stable","rollout_id":0,"rollout_code":"","section":"release_launchpad"}}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"node_code":"overseas-control-01","available":true,"status":"full_capture","status_label":"全量观察","status_type":"success","summary":"节点当前正在参与检测,已保留 1 条现场日志样本。","log_sync_enabled":true,"mode":"full","mode_label":"全量回传","records_total":0,"records_visible":0,"records_truncated":false,"records":[],"latest_record":{},"source_summary":{"node_code":"overseas-control-01","line_count":1,"key_line_count":0,"full_line_count":1,"last_at":"2026-04-19 01:20:35","last_line":"[2026-04-19 01:20:35] [overseas-control-01] 2026-04-19 01:00:18.866 | INFO | __main__:start_detection:2575 - 开始执行域名检测任务"},"missing_reason_code":"","missing_reason":"","node":{"node_code":"overseas-control-01","region":"overseas","role":"control","status":"busy","current_load":25,"last_heartbeat_at":"2026-04-19 01:29:45"},"participation":{"detect_participating":true,"participation_state":"running","participation_label":"执行中","participation_reason":"当前正在执行 4 项检测任务。","participation_bucket":"dispatch_active","participation_bucket_label":"执行/已领","is_dispatch_active":true},"contract_navigation":{"detail_endpoint_pattern":"/api/v1/ops/contracts/{contract_key}","primary_contract_key":"ops_observability_contract","contract_keys":["ops_observability_contract","ops_stack_diagnosis_contract"],"contracts":[{"key":"ops_observability_contract","title":"Ops Observability Contract","status":"active","version":"v1","summary":"冻结 execution scene / inspection overview / activity stream / delivery queue 的正式观察面 contract。","primary_endpoint":"/api/v1/ops/overview","schema_doc_path":"docs/schemas/ops_observability_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_observability_contract","discovery_endpoints":["/api/v1/ops/overview","/api/v1/ops/inspection-overview","/api/v1/ops/activity-stream","/api/v1/ops/nodes/{node_code}/scene-log","/api/v1/ops/nodes/{node_code}/delivery-queue","/api/v1/ops/nodes/{node_code}/delivery-queue/records","/api/v1/ops/nodes/{node_code}/delivery-queue/flush","/api/v1/ops/nodes/{node_code}/delivery-queue/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/discard"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","ops_driver_contract","ops_playbook_contract","ops_stack_diagnosis_contract"]},{"key":"ops_stack_diagnosis_contract","title":"Ops Stack Diagnosis Contract","status":"active","version":"v1","summary":"冻结海外单脑总检入口的统一诊断 contract,供页面、CLI、Codex、按钮共享同一份第一现场判断。","primary_endpoint":"/api/v1/ops/stack-diagnosis","schema_doc_path":"docs/schemas/ops_stack_diagnosis_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_stack_diagnosis_contract","discovery_endpoints":["/api/v1/ops/go-live-summary","/api/v1/ops/stack-diagnosis","/api/v1/ops/contracts","/api/v1/ops/link-snapshot","/api/v1/ops/overview","/api/v1/ops/nodes","/api/v1/ops/releases/launchpad","/api/v1/ops/playbook-runs","/api/v1/ops/activity-stream"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","release_hub_contract","ops_driver_contract","ops_playbook_contract","ops_observability_contract"]}]}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
|
||||
CYCLES="1"
|
||||
GO_LIVE_STATUS="attention"
|
||||
PUBLISH_READY="false"
|
||||
LOG_SYNC_STATE="full_capture"
|
||||
LOG_SYNC_MISSING_NODE_CODES=""
|
||||
STACK_STATUS="attention"
|
||||
ISSUE_TOTAL="1"
|
||||
BLOCKING_ISSUE_TOTAL="0"
|
||||
ISSUE_CODES="playbook_runs_need_attention"
|
||||
LAUNCHPAD_STATUS="blocked"
|
||||
LAUNCHPAD_RECOMMENDED_ACTION="run_acceptance"
|
||||
PROBLEM_RUNS_TOTAL="0"
|
||||
PROBLEM_RUN_CODE=""
|
||||
SCENE_STATUS="full_capture"
|
||||
SCENE_LINE_COUNT="1"
|
||||
GENERATED_AT="2026-04-19 01:29:38"
|
||||
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"base_url":"http://127.0.0.1:8100","generated_at":"2026-04-19 02:29:55","go_live_status":"attention","publish_ready":false,"publish_status":"attention","publish_status_label":"可发布但建议先复核","publish_summary":"当前没有硬阻断,但仍有上线前关注项,建议先完成复核再正式发版。","stack_status":"attention","contracts_ready":true,"contracts_total":11,"launchpad_status":"attention","launchpad_status_label":"待补执行面","launchpad_recommended_action_code":"fix_managed_nodes","launchpad_recommended_target_node_code":"","launchpad_recommended_recovery_label":"","launchpad_recommended_recovery_summary":"来自 overview.recommendation.primary_action_code","launchpad_onboarding_bootstrap_pending_nodes":0,"launchpad_onboarding_acceptance_ready_nodes":0,"route_surface_complete":true,"route_surface_missing_keys":[],"route_surface_declares_bootstrap_plan":true,"runtime_schema_stale":false,"repository_capabilities":{"supports_install_command_block":true,"supports_multi_layout_bootstrap":true},"managed_enabled":3,"remote_access_ready":3,"queue_dead_letter_nodes":0,"activity_start_delivery_issue_total":0,"participating_nodes_total":3,"log_sync_enabled":true,"log_sync_state":"full_capture","log_sync_mode":"full","log_sync_covered_nodes":3,"log_sync_missing_node_codes":[],"next_step_action_code":"focus_playbook_run","next_step_reason":"来自 overview.recommendation.primary_action_code","operator_lane":"ops_jobs","operator_title":"按总检默认下一步继续处理","operator_primary_command_key":"focus_playbook_run","publish_blocking_reasons":[],"publish_warnings":["stack_diagnosis=attention","release_launchpad=attention"],"blocking_reasons":[],"warnings":["stack_diagnosis=attention","release_launchpad=attention"],"recommended_commands":{"stack_summary":"bash domain-api/deploy/multi-region/check_ops_center_stack.sh http://127.0.0.1:8100 summary","contracts":"bash domain-api/deploy/multi-region/check_ops_contracts.sh http://127.0.0.1:8100","ops_plane":"bash domain-api/deploy/multi-region/check_ops_plane.sh http://127.0.0.1:8100","release_hub":"bash domain-api/deploy/multi-region/check_release_hub.sh http://127.0.0.1:8100","inspection":"bash domain-api/deploy/multi-region/check_ops_inspection.sh http://127.0.0.1:8100","overview":"bash domain-api/deploy/multi-region/drive_ops_center.sh overview http://127.0.0.1:8100","go_live_recover":"bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover http://127.0.0.1:8100","doctor_export":"bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-export /tmp/domaincheck-go-live http://127.0.0.1:8100","next_step":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 focus_playbook_run","log_sync_logs":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 open_worker_logs_participating","log_sync_inspection":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 run_inspection_participating"},"source_refs":{"stack_diagnosis_contract_key":"ops_stack_diagnosis_contract","contracts_registry_version":"2026-04-18","runtime_build_commit_sha":"246838ae4c07","release_focus_ref":{"kind":"release_hub","release_id":2,"release_version":"domaincheck_release_20260418_013833","channel":"stable","rollout_id":0,"rollout_code":"","section":"release_launchpad"}}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"node_code":"overseas-control-01","available":true,"status":"full_capture","status_label":"全量观察","status_type":"success","summary":"节点当前正在参与检测,已保留 1 条现场日志样本。","log_sync_enabled":true,"mode":"full","mode_label":"全量回传","records_total":0,"records_visible":0,"records_truncated":false,"records":[],"latest_record":{},"source_summary":{"node_code":"overseas-control-01","line_count":1,"key_line_count":0,"full_line_count":1,"last_at":"2026-04-19 01:20:35","last_line":"[2026-04-19 01:20:35] [overseas-control-01] 2026-04-19 01:00:18.866 | INFO | __main__:start_detection:2575 - 开始执行域名检测任务"},"missing_reason_code":"","missing_reason":"","node":{"node_code":"overseas-control-01","region":"overseas","role":"control","status":"busy","current_load":25,"last_heartbeat_at":"2026-04-19 02:30:02"},"participation":{"detect_participating":true,"participation_state":"running","participation_label":"执行中","participation_reason":"当前正在执行 4 项检测任务。","participation_bucket":"dispatch_active","participation_bucket_label":"执行/已领","is_dispatch_active":true},"contract_navigation":{"detail_endpoint_pattern":"/api/v1/ops/contracts/{contract_key}","primary_contract_key":"ops_observability_contract","contract_keys":["ops_observability_contract","ops_stack_diagnosis_contract"],"contracts":[{"key":"ops_observability_contract","title":"Ops Observability Contract","status":"active","version":"v1","summary":"冻结 execution scene / inspection overview / activity stream / delivery queue 的正式观察面 contract。","primary_endpoint":"/api/v1/ops/overview","schema_doc_path":"docs/schemas/ops_observability_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_observability_contract","discovery_endpoints":["/api/v1/ops/overview","/api/v1/ops/inspection-overview","/api/v1/ops/activity-stream","/api/v1/ops/nodes/{node_code}/scene-log","/api/v1/ops/nodes/{node_code}/delivery-queue","/api/v1/ops/nodes/{node_code}/delivery-queue/records","/api/v1/ops/nodes/{node_code}/delivery-queue/flush","/api/v1/ops/nodes/{node_code}/delivery-queue/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/discard"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","ops_driver_contract","ops_playbook_contract","ops_stack_diagnosis_contract"]},{"key":"ops_stack_diagnosis_contract","title":"Ops Stack Diagnosis Contract","status":"active","version":"v1","summary":"冻结海外单脑总检入口的统一诊断 contract,供页面、CLI、Codex、按钮共享同一份第一现场判断。","primary_endpoint":"/api/v1/ops/stack-diagnosis","schema_doc_path":"docs/schemas/ops_stack_diagnosis_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_stack_diagnosis_contract","discovery_endpoints":["/api/v1/ops/go-live-summary","/api/v1/ops/stack-diagnosis","/api/v1/ops/contracts","/api/v1/ops/link-snapshot","/api/v1/ops/overview","/api/v1/ops/nodes","/api/v1/ops/releases/launchpad","/api/v1/ops/playbook-runs","/api/v1/ops/activity-stream"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","release_hub_contract","ops_driver_contract","ops_playbook_contract","ops_observability_contract"]}]}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
|
||||
CYCLES="2"
|
||||
GO_LIVE_STATUS="attention"
|
||||
PUBLISH_READY="false"
|
||||
LOG_SYNC_STATE="full_capture"
|
||||
LOG_SYNC_MISSING_NODE_CODES=""
|
||||
STACK_STATUS="attention"
|
||||
ISSUE_TOTAL="1"
|
||||
BLOCKING_ISSUE_TOTAL="0"
|
||||
ISSUE_CODES="playbook_runs_need_attention"
|
||||
LAUNCHPAD_STATUS="blocked"
|
||||
LAUNCHPAD_RECOMMENDED_ACTION="run_acceptance"
|
||||
PROBLEM_RUNS_TOTAL="0"
|
||||
PROBLEM_RUN_CODE=""
|
||||
SCENE_STATUS="full_capture"
|
||||
SCENE_LINE_COUNT="1"
|
||||
GENERATED_AT="2026-04-19 02:29:55"
|
||||
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"base_url":"http://127.0.0.1:8100","generated_at":"2026-04-19 03:30:12","go_live_status":"attention","publish_ready":false,"publish_status":"attention","publish_status_label":"可发布但建议先复核","publish_summary":"当前没有硬阻断,但仍有上线前关注项,建议先完成复核再正式发版。","stack_status":"attention","contracts_ready":true,"contracts_total":11,"launchpad_status":"attention","launchpad_status_label":"待补执行面","launchpad_recommended_action_code":"fix_managed_nodes","launchpad_recommended_target_node_code":"","launchpad_recommended_recovery_label":"","launchpad_recommended_recovery_summary":"来自 overview.recommendation.primary_action_code","launchpad_onboarding_bootstrap_pending_nodes":0,"launchpad_onboarding_acceptance_ready_nodes":0,"route_surface_complete":true,"route_surface_missing_keys":[],"route_surface_declares_bootstrap_plan":true,"runtime_schema_stale":false,"repository_capabilities":{"supports_install_command_block":true,"supports_multi_layout_bootstrap":true},"managed_enabled":3,"remote_access_ready":3,"queue_dead_letter_nodes":0,"activity_start_delivery_issue_total":0,"participating_nodes_total":3,"log_sync_enabled":true,"log_sync_state":"partial_coverage","log_sync_mode":"full","log_sync_covered_nodes":2,"log_sync_missing_node_codes":["overseas-control-01"],"next_step_action_code":"focus_playbook_run","next_step_reason":"来自 overview.recommendation.primary_action_code","operator_lane":"ops_jobs","operator_title":"按总检默认下一步继续处理","operator_primary_command_key":"focus_playbook_run","publish_blocking_reasons":[],"publish_warnings":["stack_diagnosis=attention","release_launchpad=attention","log_sync_partial=2/3"],"blocking_reasons":[],"warnings":["stack_diagnosis=attention","release_launchpad=attention","log_sync_partial=2/3"],"recommended_commands":{"stack_summary":"bash domain-api/deploy/multi-region/check_ops_center_stack.sh http://127.0.0.1:8100 summary","contracts":"bash domain-api/deploy/multi-region/check_ops_contracts.sh http://127.0.0.1:8100","ops_plane":"bash domain-api/deploy/multi-region/check_ops_plane.sh http://127.0.0.1:8100","release_hub":"bash domain-api/deploy/multi-region/check_release_hub.sh http://127.0.0.1:8100","inspection":"bash domain-api/deploy/multi-region/check_ops_inspection.sh http://127.0.0.1:8100","overview":"bash domain-api/deploy/multi-region/drive_ops_center.sh overview http://127.0.0.1:8100","go_live_recover":"bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover http://127.0.0.1:8100","doctor_export":"bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-export /tmp/domaincheck-go-live http://127.0.0.1:8100","next_step":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 focus_playbook_run","log_sync_logs":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 open_worker_logs_participating","log_sync_inspection":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 run_inspection_participating"},"source_refs":{"stack_diagnosis_contract_key":"ops_stack_diagnosis_contract","contracts_registry_version":"2026-04-18","runtime_build_commit_sha":"246838ae4c07","release_focus_ref":{"kind":"release_hub","release_id":2,"release_version":"domaincheck_release_20260418_013833","channel":"stable","rollout_id":0,"rollout_code":"","section":"release_launchpad"}}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"node_code":"overseas-control-01","available":true,"status":"missing_sample","status_label":"缺少样本","status_type":"warning","summary":"当前还没有收到该参与节点的远端日志样本。","log_sync_enabled":true,"mode":"full","mode_label":"全量回传","records_total":0,"records_visible":0,"records_truncated":false,"records":[],"latest_record":{},"source_summary":{"node_code":"overseas-control-01","line_count":0,"key_line_count":0,"full_line_count":0,"last_at":"","last_line":""},"missing_reason_code":"no_sample","missing_reason":"当前还没有收到该参与节点的远端日志样本。","node":{"node_code":"overseas-control-01","region":"overseas","role":"control","status":"busy","current_load":25,"last_heartbeat_at":"2026-04-19 03:30:19"},"participation":{"detect_participating":true,"participation_state":"running","participation_label":"执行中","participation_reason":"当前正在执行 4 项检测任务。","participation_bucket":"dispatch_active","participation_bucket_label":"执行/已领","is_dispatch_active":true},"contract_navigation":{"detail_endpoint_pattern":"/api/v1/ops/contracts/{contract_key}","primary_contract_key":"ops_observability_contract","contract_keys":["ops_observability_contract","ops_stack_diagnosis_contract"],"contracts":[{"key":"ops_observability_contract","title":"Ops Observability Contract","status":"active","version":"v1","summary":"冻结 execution scene / inspection overview / activity stream / delivery queue 的正式观察面 contract。","primary_endpoint":"/api/v1/ops/overview","schema_doc_path":"docs/schemas/ops_observability_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_observability_contract","discovery_endpoints":["/api/v1/ops/overview","/api/v1/ops/inspection-overview","/api/v1/ops/activity-stream","/api/v1/ops/nodes/{node_code}/scene-log","/api/v1/ops/nodes/{node_code}/delivery-queue","/api/v1/ops/nodes/{node_code}/delivery-queue/records","/api/v1/ops/nodes/{node_code}/delivery-queue/flush","/api/v1/ops/nodes/{node_code}/delivery-queue/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/discard"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","ops_driver_contract","ops_playbook_contract","ops_stack_diagnosis_contract"]},{"key":"ops_stack_diagnosis_contract","title":"Ops Stack Diagnosis Contract","status":"active","version":"v1","summary":"冻结海外单脑总检入口的统一诊断 contract,供页面、CLI、Codex、按钮共享同一份第一现场判断。","primary_endpoint":"/api/v1/ops/stack-diagnosis","schema_doc_path":"docs/schemas/ops_stack_diagnosis_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_stack_diagnosis_contract","discovery_endpoints":["/api/v1/ops/go-live-summary","/api/v1/ops/stack-diagnosis","/api/v1/ops/contracts","/api/v1/ops/link-snapshot","/api/v1/ops/overview","/api/v1/ops/nodes","/api/v1/ops/releases/launchpad","/api/v1/ops/playbook-runs","/api/v1/ops/activity-stream"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","release_hub_contract","ops_driver_contract","ops_playbook_contract","ops_observability_contract"]}]}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
|
||||
CYCLES="3"
|
||||
GO_LIVE_STATUS="attention"
|
||||
PUBLISH_READY="false"
|
||||
LOG_SYNC_STATE="partial_coverage"
|
||||
LOG_SYNC_MISSING_NODE_CODES="overseas-control-01"
|
||||
STACK_STATUS="attention"
|
||||
ISSUE_TOTAL="2"
|
||||
BLOCKING_ISSUE_TOTAL="0"
|
||||
ISSUE_CODES="remote_log_sync_waiting_sample,playbook_runs_need_attention"
|
||||
LAUNCHPAD_STATUS="blocked"
|
||||
LAUNCHPAD_RECOMMENDED_ACTION="run_acceptance"
|
||||
PROBLEM_RUNS_TOTAL="0"
|
||||
PROBLEM_RUN_CODE=""
|
||||
SCENE_STATUS="missing_sample"
|
||||
SCENE_LINE_COUNT="0"
|
||||
GENERATED_AT="2026-04-19 03:30:12"
|
||||
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"base_url":"http://127.0.0.1:8100","generated_at":"2026-04-19 03:31:26","go_live_status":"attention","publish_ready":false,"publish_status":"attention","publish_status_label":"可发布但建议先复核","publish_summary":"当前没有硬阻断,但仍有上线前关注项,建议先完成复核再正式发版。","stack_status":"attention","contracts_ready":true,"contracts_total":11,"launchpad_status":"attention","launchpad_status_label":"待补执行面","launchpad_recommended_action_code":"fix_managed_nodes","launchpad_recommended_target_node_code":"","launchpad_recommended_recovery_label":"","launchpad_recommended_recovery_summary":"来自 overview.recommendation.primary_action_code","launchpad_onboarding_bootstrap_pending_nodes":0,"launchpad_onboarding_acceptance_ready_nodes":0,"route_surface_complete":true,"route_surface_missing_keys":[],"route_surface_declares_bootstrap_plan":true,"runtime_schema_stale":false,"repository_capabilities":{"supports_install_command_block":true,"supports_multi_layout_bootstrap":true},"managed_enabled":3,"remote_access_ready":3,"queue_dead_letter_nodes":0,"activity_start_delivery_issue_total":0,"participating_nodes_total":3,"log_sync_enabled":true,"log_sync_state":"full_capture","log_sync_mode":"full","log_sync_covered_nodes":3,"log_sync_missing_node_codes":[],"next_step_action_code":"focus_playbook_run","next_step_reason":"来自 overview.recommendation.primary_action_code","operator_lane":"ops_jobs","operator_title":"按总检默认下一步继续处理","operator_primary_command_key":"focus_playbook_run","publish_blocking_reasons":[],"publish_warnings":["stack_diagnosis=attention","release_launchpad=attention"],"blocking_reasons":[],"warnings":["stack_diagnosis=attention","release_launchpad=attention"],"recommended_commands":{"stack_summary":"bash domain-api/deploy/multi-region/check_ops_center_stack.sh http://127.0.0.1:8100 summary","contracts":"bash domain-api/deploy/multi-region/check_ops_contracts.sh http://127.0.0.1:8100","ops_plane":"bash domain-api/deploy/multi-region/check_ops_plane.sh http://127.0.0.1:8100","release_hub":"bash domain-api/deploy/multi-region/check_release_hub.sh http://127.0.0.1:8100","inspection":"bash domain-api/deploy/multi-region/check_ops_inspection.sh http://127.0.0.1:8100","overview":"bash domain-api/deploy/multi-region/drive_ops_center.sh overview http://127.0.0.1:8100","go_live_recover":"bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover http://127.0.0.1:8100","doctor_export":"bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-export /tmp/domaincheck-go-live http://127.0.0.1:8100","next_step":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 focus_playbook_run","log_sync_logs":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 open_worker_logs_participating","log_sync_inspection":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 run_inspection_participating"},"source_refs":{"stack_diagnosis_contract_key":"ops_stack_diagnosis_contract","contracts_registry_version":"2026-04-18","runtime_build_commit_sha":"246838ae4c07","release_focus_ref":{"kind":"release_hub","release_id":2,"release_version":"domaincheck_release_20260418_013833","channel":"stable","rollout_id":0,"rollout_code":"","section":"release_launchpad"}}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"node_code":"overseas-control-01","available":true,"status":"full_capture","status_label":"全量观察","status_type":"success","summary":"节点当前正在参与检测,已保留 3 条现场日志样本。","log_sync_enabled":true,"mode":"full","mode_label":"全量回传","records_total":0,"records_visible":0,"records_truncated":false,"records":[],"latest_record":{},"source_summary":{"node_code":"overseas-control-01","line_count":3,"key_line_count":0,"full_line_count":3,"last_at":"2026-04-19 03:30:30","last_line":"[2026-04-19 03:30:30] [overseas-control-01] 2026-04-19 01:59:40.686 | WARNING | __main__:start_detection_async:1073 - 收到启动检测指令,但检测任务已在运行,忽略重复启动"},"missing_reason_code":"","missing_reason":"","node":{"node_code":"overseas-control-01","region":"overseas","role":"control","status":"busy","current_load":25,"last_heartbeat_at":"2026-04-19 03:31:33"},"participation":{"detect_participating":true,"participation_state":"running","participation_label":"执行中","participation_reason":"当前正在执行 4 项检测任务。","participation_bucket":"dispatch_active","participation_bucket_label":"执行/已领","is_dispatch_active":true},"contract_navigation":{"detail_endpoint_pattern":"/api/v1/ops/contracts/{contract_key}","primary_contract_key":"ops_observability_contract","contract_keys":["ops_observability_contract","ops_stack_diagnosis_contract"],"contracts":[{"key":"ops_observability_contract","title":"Ops Observability Contract","status":"active","version":"v1","summary":"冻结 execution scene / inspection overview / activity stream / delivery queue 的正式观察面 contract。","primary_endpoint":"/api/v1/ops/overview","schema_doc_path":"docs/schemas/ops_observability_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_observability_contract","discovery_endpoints":["/api/v1/ops/overview","/api/v1/ops/inspection-overview","/api/v1/ops/activity-stream","/api/v1/ops/nodes/{node_code}/scene-log","/api/v1/ops/nodes/{node_code}/delivery-queue","/api/v1/ops/nodes/{node_code}/delivery-queue/records","/api/v1/ops/nodes/{node_code}/delivery-queue/flush","/api/v1/ops/nodes/{node_code}/delivery-queue/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/discard"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","ops_driver_contract","ops_playbook_contract","ops_stack_diagnosis_contract"]},{"key":"ops_stack_diagnosis_contract","title":"Ops Stack Diagnosis Contract","status":"active","version":"v1","summary":"冻结海外单脑总检入口的统一诊断 contract,供页面、CLI、Codex、按钮共享同一份第一现场判断。","primary_endpoint":"/api/v1/ops/stack-diagnosis","schema_doc_path":"docs/schemas/ops_stack_diagnosis_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_stack_diagnosis_contract","discovery_endpoints":["/api/v1/ops/go-live-summary","/api/v1/ops/stack-diagnosis","/api/v1/ops/contracts","/api/v1/ops/link-snapshot","/api/v1/ops/overview","/api/v1/ops/nodes","/api/v1/ops/releases/launchpad","/api/v1/ops/playbook-runs","/api/v1/ops/activity-stream"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","release_hub_contract","ops_driver_contract","ops_playbook_contract","ops_observability_contract"]}]}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
|
||||
CYCLES="4"
|
||||
GO_LIVE_STATUS="attention"
|
||||
PUBLISH_READY="false"
|
||||
LOG_SYNC_STATE="full_capture"
|
||||
LOG_SYNC_MISSING_NODE_CODES=""
|
||||
STACK_STATUS="attention"
|
||||
ISSUE_TOTAL="1"
|
||||
BLOCKING_ISSUE_TOTAL="0"
|
||||
ISSUE_CODES="playbook_runs_need_attention"
|
||||
LAUNCHPAD_STATUS="blocked"
|
||||
LAUNCHPAD_RECOMMENDED_ACTION="run_acceptance"
|
||||
PROBLEM_RUNS_TOTAL="0"
|
||||
PROBLEM_RUN_CODE=""
|
||||
SCENE_STATUS="full_capture"
|
||||
SCENE_LINE_COUNT="3"
|
||||
GENERATED_AT="2026-04-19 03:31:26"
|
||||
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"base_url":"http://127.0.0.1:8100","generated_at":"2026-04-19 04:31:45","go_live_status":"attention","publish_ready":false,"publish_status":"attention","publish_status_label":"可发布但建议先复核","publish_summary":"当前没有硬阻断,但仍有上线前关注项,建议先完成复核再正式发版。","stack_status":"attention","contracts_ready":true,"contracts_total":11,"launchpad_status":"attention","launchpad_status_label":"待补执行面","launchpad_recommended_action_code":"fix_managed_nodes","launchpad_recommended_target_node_code":"","launchpad_recommended_recovery_label":"","launchpad_recommended_recovery_summary":"来自 overview.recommendation.primary_action_code","launchpad_onboarding_bootstrap_pending_nodes":0,"launchpad_onboarding_acceptance_ready_nodes":0,"route_surface_complete":true,"route_surface_missing_keys":[],"route_surface_declares_bootstrap_plan":true,"runtime_schema_stale":false,"repository_capabilities":{"supports_install_command_block":true,"supports_multi_layout_bootstrap":true},"managed_enabled":3,"remote_access_ready":3,"queue_dead_letter_nodes":0,"activity_start_delivery_issue_total":0,"participating_nodes_total":3,"log_sync_enabled":true,"log_sync_state":"partial_coverage","log_sync_mode":"full","log_sync_covered_nodes":2,"log_sync_missing_node_codes":["overseas-control-01"],"next_step_action_code":"focus_playbook_run","next_step_reason":"来自 overview.recommendation.primary_action_code","operator_lane":"ops_jobs","operator_title":"按总检默认下一步继续处理","operator_primary_command_key":"focus_playbook_run","publish_blocking_reasons":[],"publish_warnings":["stack_diagnosis=attention","release_launchpad=attention","log_sync_partial=2/3"],"blocking_reasons":[],"warnings":["stack_diagnosis=attention","release_launchpad=attention","log_sync_partial=2/3"],"recommended_commands":{"stack_summary":"bash domain-api/deploy/multi-region/check_ops_center_stack.sh http://127.0.0.1:8100 summary","contracts":"bash domain-api/deploy/multi-region/check_ops_contracts.sh http://127.0.0.1:8100","ops_plane":"bash domain-api/deploy/multi-region/check_ops_plane.sh http://127.0.0.1:8100","release_hub":"bash domain-api/deploy/multi-region/check_release_hub.sh http://127.0.0.1:8100","inspection":"bash domain-api/deploy/multi-region/check_ops_inspection.sh http://127.0.0.1:8100","overview":"bash domain-api/deploy/multi-region/drive_ops_center.sh overview http://127.0.0.1:8100","go_live_recover":"bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover http://127.0.0.1:8100","doctor_export":"bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-export /tmp/domaincheck-go-live http://127.0.0.1:8100","next_step":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 focus_playbook_run","log_sync_logs":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 open_worker_logs_participating","log_sync_inspection":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 run_inspection_participating"},"source_refs":{"stack_diagnosis_contract_key":"ops_stack_diagnosis_contract","contracts_registry_version":"2026-04-18","runtime_build_commit_sha":"246838ae4c07","release_focus_ref":{"kind":"release_hub","release_id":2,"release_version":"domaincheck_release_20260418_013833","channel":"stable","rollout_id":0,"rollout_code":"","section":"release_launchpad"}}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"node_code":"overseas-control-01","available":true,"status":"missing_sample","status_label":"缺少样本","status_type":"warning","summary":"当前还没有收到该参与节点的远端日志样本。","log_sync_enabled":true,"mode":"full","mode_label":"全量回传","records_total":0,"records_visible":0,"records_truncated":false,"records":[],"latest_record":{},"source_summary":{"node_code":"overseas-control-01","line_count":0,"key_line_count":0,"full_line_count":0,"last_at":"","last_line":""},"missing_reason_code":"no_sample","missing_reason":"当前还没有收到该参与节点的远端日志样本。","node":{"node_code":"overseas-control-01","region":"overseas","role":"control","status":"busy","current_load":25,"last_heartbeat_at":"2026-04-19 04:31:52"},"participation":{"detect_participating":true,"participation_state":"running","participation_label":"执行中","participation_reason":"当前正在执行 4 项检测任务。","participation_bucket":"dispatch_active","participation_bucket_label":"执行/已领","is_dispatch_active":true},"contract_navigation":{"detail_endpoint_pattern":"/api/v1/ops/contracts/{contract_key}","primary_contract_key":"ops_observability_contract","contract_keys":["ops_observability_contract","ops_stack_diagnosis_contract"],"contracts":[{"key":"ops_observability_contract","title":"Ops Observability Contract","status":"active","version":"v1","summary":"冻结 execution scene / inspection overview / activity stream / delivery queue 的正式观察面 contract。","primary_endpoint":"/api/v1/ops/overview","schema_doc_path":"docs/schemas/ops_observability_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_observability_contract","discovery_endpoints":["/api/v1/ops/overview","/api/v1/ops/inspection-overview","/api/v1/ops/activity-stream","/api/v1/ops/nodes/{node_code}/scene-log","/api/v1/ops/nodes/{node_code}/delivery-queue","/api/v1/ops/nodes/{node_code}/delivery-queue/records","/api/v1/ops/nodes/{node_code}/delivery-queue/flush","/api/v1/ops/nodes/{node_code}/delivery-queue/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/replay","/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/discard"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","ops_driver_contract","ops_playbook_contract","ops_stack_diagnosis_contract"]},{"key":"ops_stack_diagnosis_contract","title":"Ops Stack Diagnosis Contract","status":"active","version":"v1","summary":"冻结海外单脑总检入口的统一诊断 contract,供页面、CLI、Codex、按钮共享同一份第一现场判断。","primary_endpoint":"/api/v1/ops/stack-diagnosis","schema_doc_path":"docs/schemas/ops_stack_diagnosis_contract.md","detail_endpoint":"/api/v1/ops/contracts/ops_stack_diagnosis_contract","discovery_endpoints":["/api/v1/ops/go-live-summary","/api/v1/ops/stack-diagnosis","/api/v1/ops/contracts","/api/v1/ops/link-snapshot","/api/v1/ops/overview","/api/v1/ops/nodes","/api/v1/ops/releases/launchpad","/api/v1/ops/playbook-runs","/api/v1/ops/activity-stream"],"related_contract_keys":["ops_job_contract","ops_agent_protocol","release_hub_contract","ops_driver_contract","ops_playbook_contract","ops_observability_contract"]}]}},"detail_code":null}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
|
||||
CYCLES="5"
|
||||
GO_LIVE_STATUS="attention"
|
||||
PUBLISH_READY="false"
|
||||
LOG_SYNC_STATE="partial_coverage"
|
||||
LOG_SYNC_MISSING_NODE_CODES="overseas-control-01"
|
||||
STACK_STATUS="attention"
|
||||
ISSUE_TOTAL="2"
|
||||
BLOCKING_ISSUE_TOTAL="0"
|
||||
ISSUE_CODES="remote_log_sync_waiting_sample,playbook_runs_need_attention"
|
||||
LAUNCHPAD_STATUS="blocked"
|
||||
LAUNCHPAD_RECOMMENDED_ACTION="run_acceptance"
|
||||
PROBLEM_RUNS_TOTAL="0"
|
||||
PROBLEM_RUN_CODE=""
|
||||
SCENE_STATUS="missing_sample"
|
||||
SCENE_LINE_COUNT="0"
|
||||
GENERATED_AT="2026-04-19 04:31:45"
|
||||
@@ -0,0 +1,16 @@
|
||||
CYCLES="6"
|
||||
GO_LIVE_STATUS=""
|
||||
PUBLISH_READY="false"
|
||||
LOG_SYNC_STATE=""
|
||||
LOG_SYNC_MISSING_NODE_CODES=""
|
||||
STACK_STATUS=""
|
||||
ISSUE_TOTAL="0"
|
||||
BLOCKING_ISSUE_TOTAL="0"
|
||||
ISSUE_CODES=""
|
||||
LAUNCHPAD_STATUS=""
|
||||
LAUNCHPAD_RECOMMENDED_ACTION=""
|
||||
PROBLEM_RUNS_TOTAL="0"
|
||||
PROBLEM_RUN_CODE=""
|
||||
SCENE_STATUS=""
|
||||
SCENE_LINE_COUNT="0"
|
||||
GENERATED_AT=""
|
||||
@@ -0,0 +1,16 @@
|
||||
CYCLES="7"
|
||||
GO_LIVE_STATUS=""
|
||||
PUBLISH_READY="false"
|
||||
LOG_SYNC_STATE=""
|
||||
LOG_SYNC_MISSING_NODE_CODES=""
|
||||
STACK_STATUS=""
|
||||
ISSUE_TOTAL="0"
|
||||
BLOCKING_ISSUE_TOTAL="0"
|
||||
ISSUE_CODES=""
|
||||
LAUNCHPAD_STATUS=""
|
||||
LAUNCHPAD_RECOMMENDED_ACTION=""
|
||||
PROBLEM_RUNS_TOTAL="0"
|
||||
PROBLEM_RUN_CODE=""
|
||||
SCENE_STATUS=""
|
||||
SCENE_LINE_COUNT="0"
|
||||
GENERATED_AT=""
|
||||
@@ -0,0 +1 @@
|
||||
{"code":0,"message":"ok","data":{"base_url":"http://127.0.0.1:8100","generated_at":"2026-04-19 04:34:28","go_live_status":"attention","publish_ready":false,"publish_status":"attention","publish_status_label":"可发布但建议先复核","publish_summary":"当前没有硬阻断,但仍有上线前关注项,建议先完成复核再正式发版。","stack_status":"attention","contracts_ready":true,"contracts_total":11,"launchpad_status":"attention","launchpad_status_label":"待补执行面","launchpad_recommended_action_code":"fix_managed_nodes","launchpad_recommended_target_node_code":"","launchpad_recommended_recovery_label":"","launchpad_recommended_recovery_summary":"来自 overview.recommendation.primary_action_code","launchpad_onboarding_bootstrap_pending_nodes":0,"launchpad_onboarding_acceptance_ready_nodes":0,"route_surface_complete":true,"route_surface_missing_keys":[],"route_surface_declares_bootstrap_plan":true,"runtime_schema_stale":false,"repository_capabilities":{"supports_install_command_block":true,"supports_multi_layout_bootstrap":true},"managed_enabled":3,"remote_access_ready":3,"queue_dead_letter_nodes":0,"activity_start_delivery_issue_total":0,"participating_nodes_total":1,"log_sync_enabled":true,"log_sync_state":"full_capture","log_sync_mode":"full","log_sync_covered_nodes":1,"log_sync_missing_node_codes":[],"next_step_action_code":"focus_playbook_run","next_step_reason":"来自 overview.recommendation.primary_action_code","operator_lane":"ops_jobs","operator_title":"按总检默认下一步继续处理","operator_primary_command_key":"focus_playbook_run","publish_blocking_reasons":[],"publish_warnings":["stack_diagnosis=attention","release_launchpad=attention"],"blocking_reasons":[],"warnings":["stack_diagnosis=attention","release_launchpad=attention"],"recommended_commands":{"stack_summary":"bash domain-api/deploy/multi-region/check_ops_center_stack.sh http://127.0.0.1:8100 summary","contracts":"bash domain-api/deploy/multi-region/check_ops_contracts.sh http://127.0.0.1:8100","ops_plane":"bash domain-api/deploy/multi-region/check_ops_plane.sh http://127.0.0.1:8100","release_hub":"bash domain-api/deploy/multi-region/check_release_hub.sh http://127.0.0.1:8100","inspection":"bash domain-api/deploy/multi-region/check_ops_inspection.sh http://127.0.0.1:8100","overview":"bash domain-api/deploy/multi-region/drive_ops_center.sh overview http://127.0.0.1:8100","go_live_recover":"bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover http://127.0.0.1:8100","doctor_export":"bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-export /tmp/domaincheck-go-live http://127.0.0.1:8100","next_step":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 focus_playbook_run","log_sync_logs":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 open_worker_logs_participating","log_sync_inspection":"bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 run_inspection_participating"},"source_refs":{"stack_diagnosis_contract_key":"ops_stack_diagnosis_contract","contracts_registry_version":"2026-04-18","runtime_build_commit_sha":"246838ae4c07","release_focus_ref":{"kind":"release_hub","release_id":2,"release_version":"domaincheck_release_20260418_013833","channel":"stable","rollout_id":0,"rollout_code":"","section":"release_launchpad"}}},"detail_code":null}
|
||||
@@ -0,0 +1,16 @@
|
||||
CYCLES="8"
|
||||
GO_LIVE_STATUS="attention"
|
||||
PUBLISH_READY="false"
|
||||
LOG_SYNC_STATE="full_capture"
|
||||
LOG_SYNC_MISSING_NODE_CODES=""
|
||||
STACK_STATUS=""
|
||||
ISSUE_TOTAL="0"
|
||||
BLOCKING_ISSUE_TOTAL="0"
|
||||
ISSUE_CODES=""
|
||||
LAUNCHPAD_STATUS=""
|
||||
LAUNCHPAD_RECOMMENDED_ACTION=""
|
||||
PROBLEM_RUNS_TOTAL="0"
|
||||
PROBLEM_RUN_CODE=""
|
||||
SCENE_STATUS=""
|
||||
SCENE_LINE_COUNT="0"
|
||||
GENERATED_AT="2026-04-19 04:34:28"
|
||||
@@ -0,0 +1,59 @@
|
||||
# night_run_20260419_012929 初步分析
|
||||
|
||||
## 结论
|
||||
|
||||
- 夜跑不是完全空跑,`cycle_1` 到 `cycle_8` 期间持续执行了巡检、收口和日志回传恢复动作。
|
||||
- 真正的中断点出现在 `2026-04-19 04:32:49` 到 `04:33:35`,本机 API `127.0.0.1:8100` 短时不可达,导致两轮自动动作直接失败。
|
||||
- 最终停止原因是 `signoff_ready_candidate`,这是“候选可签收”型收口,不等同于“整轮全绿、无异常结束”。
|
||||
|
||||
## 关键时间点
|
||||
|
||||
- `2026-04-19 01:29:29 +0800`
|
||||
- 夜跑启动。
|
||||
- `cycle_1` 到 `cycle_5`
|
||||
- 持续产出 `go_live.json`、`launchpad.json`、`playbook_runs.json`、`stack.json`、`scene_overseas_control_01.json`、`summary.env`。
|
||||
- `2026-04-19 04:32:04 +0800`
|
||||
- `run_inspection_participating` 成功创建 playbook,回执 `pbr-6d77b32f40`。
|
||||
- `2026-04-19 04:32:49 +0800`
|
||||
- `cycle=6`
|
||||
- `log-sync-recover` 调用失败。
|
||||
- `driver-run run_inspection_participating` 调用失败。
|
||||
- 错误为 `curl: (7) Failed to connect to 127.0.0.1 port 8100: Connection refused`。
|
||||
- `2026-04-19 04:33:34 +0800`
|
||||
- `cycle=7`
|
||||
- 同类动作再次失败,错误相同。
|
||||
- `2026-04-19 04:34:28 +0800`
|
||||
- `cycle=8`
|
||||
- `go_live=attention`
|
||||
- `log_sync=full_capture`
|
||||
- 夜跑停止,`reason=signoff_ready_candidate`。
|
||||
|
||||
## 已确认的问题
|
||||
|
||||
- 夜跑期间存在控制面 API 短时离线或重启窗口。
|
||||
- 自动恢复逻辑在 API 不可达时会直接失败,但日志里没有看到进一步的退避、跳过本轮、等待 API 恢复后的再确认闭环。
|
||||
- 当时的“可签收候选”判断,掺杂了 API 短时不可达窗口,所以不能把这次夜跑结论直接当成正式签收证据。
|
||||
|
||||
## 这轮修复后的关联状态
|
||||
|
||||
- 当前中央控制面已经恢复正常。
|
||||
- `runtime/cluster` 已恢复为 3 台有效执行节点。
|
||||
- `detect/status` 已恢复远端日志回传。
|
||||
- `mainland-controller-01` 当前已恢复 `100/100`。
|
||||
- `mainland-worker-01` 当前已进入活跃参与,中央已看到 `2/50`。
|
||||
|
||||
## 明天继续看时,优先检查
|
||||
|
||||
- `docs/ops_center_runtime/night_runs/night_run_20260419_012929.log`
|
||||
- 重点看 `04:32:49` 到 `04:34:28` 这段 API 拒绝连接窗口。
|
||||
- `docs/ops_center_runtime/night_runs/night_run_20260419_012929/cycle_8/go_live.json`
|
||||
- 确认 `go_live=attention` 的具体触发项。
|
||||
- `docs/ops_center_runtime/night_runs/night_run_20260419_012929_report.md`
|
||||
- 对照夜跑最终报告和原始日志,确认是否把“候选可签收”误当成“正式通过”。
|
||||
|
||||
## 下一步建议
|
||||
|
||||
- 补一条夜跑期间的 API 可用性守护:
|
||||
- 发现 `127.0.0.1:8100` 不可达时,不立刻继续推进收口动作,先等待 API 恢复后重试。
|
||||
- 把“候选可签收”和“正式可签收”拆开:
|
||||
- 避免在 API 短时重启窗口里出现假阳性收口。
|
||||
@@ -0,0 +1,44 @@
|
||||
# NIGHT RUN REPORT night_run_20260419_012929
|
||||
|
||||
- Base URL: `http://127.0.0.1:8100`
|
||||
- Deadline: `2026-04-20 12:00:00 +0800`
|
||||
- Stop Reason: `signoff_ready_candidate`
|
||||
- Cycles: `8`
|
||||
- Log Sync Recover Runs: `4`
|
||||
- Inspection Runs: `4`
|
||||
- Inspection Churn Runs: `0`
|
||||
- Quick Rechecks: `4`
|
||||
|
||||
## Final Snapshot
|
||||
|
||||
- `go_live_status = attention`
|
||||
- `publish_ready = false`
|
||||
- `log_sync_state = full_capture`
|
||||
- `issue_total = 0`
|
||||
- `problem_runs_total = 0`
|
||||
- `launchpad_status = `
|
||||
- `launchpad_recommended_action = `
|
||||
- `problem_run_code = `
|
||||
|
||||
## Summary JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"cycles": 8,
|
||||
"go_live_status": "attention",
|
||||
"publish_ready": false,
|
||||
"log_sync_state": "full_capture",
|
||||
"log_sync_missing_node_codes": [],
|
||||
"stack_status": "",
|
||||
"issue_total": 0,
|
||||
"blocking_issue_total": 0,
|
||||
"issue_codes": [],
|
||||
"launchpad_status": "",
|
||||
"launchpad_recommended_action": "",
|
||||
"problem_runs_total": 0,
|
||||
"problem_run_code": "",
|
||||
"scene_status": "",
|
||||
"scene_line_count": 0,
|
||||
"generated_at": "2026-04-19 04:34:28"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"cycles": 8,
|
||||
"go_live_status": "attention",
|
||||
"publish_ready": false,
|
||||
"log_sync_state": "full_capture",
|
||||
"log_sync_missing_node_codes": [],
|
||||
"stack_status": "",
|
||||
"issue_total": 0,
|
||||
"blocking_issue_total": 0,
|
||||
"issue_codes": [],
|
||||
"launchpad_status": "",
|
||||
"launchpad_recommended_action": "",
|
||||
"problem_runs_total": 0,
|
||||
"problem_run_code": "",
|
||||
"scene_status": "",
|
||||
"scene_line_count": 0,
|
||||
"generated_at": "2026-04-19 04:34:28"
|
||||
}
|
||||
816
docs/schemas/ops_agent_protocol.md
Normal file
816
docs/schemas/ops_agent_protocol.md
Normal file
@@ -0,0 +1,816 @@
|
||||
# domainCheck Ops Agent Protocol
|
||||
|
||||
## 1. 目标
|
||||
|
||||
这份文档用于冻结 `Node Agent <-> Overseas Control Plane` 的正式 contract。
|
||||
|
||||
适用范围:
|
||||
|
||||
- `POST /api/v1/ops/agent/tokens`
|
||||
- `POST /api/v1/ops/agent/bootstrap-plan`
|
||||
- `GET /api/v1/ops/nodes/{node_code}/handover`
|
||||
- `POST /api/v1/ops/nodes/{node_code}/handover/bootstrap-plan`
|
||||
- `POST /api/v1/ops/agent/register`
|
||||
- `POST /api/v1/ops/agent/heartbeat`
|
||||
- `POST /api/v1/ops/agent/pull`
|
||||
- `POST /api/v1/ops/agent/jobs/{job_id}/start`
|
||||
- `POST /api/v1/ops/agent/jobs/{job_id}/complete`
|
||||
- `POST /api/v1/ops/agent/jobs/{job_id}/events`
|
||||
|
||||
设计原则:
|
||||
|
||||
- Agent 只执行声明过的结构化动作
|
||||
- 控制面负责调度、门禁、编排和审计
|
||||
- 所有回执都必须可重放、可去重、可死信化
|
||||
|
||||
---
|
||||
|
||||
## 2. 公共响应包裹
|
||||
|
||||
所有接口统一返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"detail_code": "",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- `code=0` 表示成功
|
||||
- `code=1` 表示业务失败
|
||||
- `detail_code` 用于结构化错误语义
|
||||
- `message` 只承担可读说明,不承担机器判断主逻辑
|
||||
|
||||
常见 `detail_code`:
|
||||
|
||||
- `agent_token_invalid`
|
||||
- `agent_token_expired`
|
||||
- `agent_token_node_mismatch`
|
||||
- `ops_job_not_owned_by_agent`
|
||||
- `ops_job_invalid_status_transition`
|
||||
- `release_checksum_mismatch`
|
||||
- `release_health_check_failed`
|
||||
|
||||
---
|
||||
|
||||
## 3. 认证与请求头
|
||||
|
||||
Agent 相关接口统一使用:
|
||||
|
||||
- `Content-Type: application/json`
|
||||
- `X-Domaincheck-Agent-Token: <token>`
|
||||
|
||||
其中:
|
||||
|
||||
- `tokens`
|
||||
- `bootstrap-plan`
|
||||
|
||||
不要求 Agent Token。
|
||||
|
||||
其余接口都要求 Token。
|
||||
|
||||
---
|
||||
|
||||
## 4. 公共节点载荷
|
||||
|
||||
`register` 与 `heartbeat` 当前共享 `_base_payload()`。
|
||||
|
||||
最小字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02",
|
||||
"region": "mainland",
|
||||
"role": "worker",
|
||||
"title": "mainland-worker-02",
|
||||
"hostname": "host-a",
|
||||
"ip": "10.0.0.12",
|
||||
"agent_version": "0.1.0",
|
||||
"capabilities": [
|
||||
"service.start",
|
||||
"service.stop",
|
||||
"service.restart",
|
||||
"service.status",
|
||||
"health.snapshot",
|
||||
"logs.collect",
|
||||
"diagnostics.collect",
|
||||
"deploy.release"
|
||||
],
|
||||
"labels": {},
|
||||
"metadata": {
|
||||
"service_names": {
|
||||
"api": "domaincheck-api",
|
||||
"worker": "domaincheck-worker",
|
||||
"sync_agent": "domaincheck-sync-agent",
|
||||
"node_agent": "domaincheck-node-agent"
|
||||
},
|
||||
"delivery_queue": {
|
||||
"state": "healthy",
|
||||
"label": "正常",
|
||||
"reason": "当前没有待重试回执,也没有死信记录。",
|
||||
"pending_count": 0,
|
||||
"dead_letter_count": 0,
|
||||
"last_flush_at": "",
|
||||
"oldest_pending_at": "",
|
||||
"oldest_pending_request_id": "",
|
||||
"oldest_pending_kind": "",
|
||||
"oldest_dead_letter_at": "",
|
||||
"oldest_dead_letter_request_id": "",
|
||||
"oldest_dead_letter_kind": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `service_names` 是控制面识别节点服务拓扑的最小入口
|
||||
- `delivery_queue` 是控制面识别 Agent 回执现场的最小入口
|
||||
|
||||
---
|
||||
|
||||
## 5. Bootstrap Contract
|
||||
|
||||
### 5.1 Issue Token
|
||||
|
||||
`POST /api/v1/ops/agent/tokens`
|
||||
|
||||
请求体最小字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02",
|
||||
"issued_by": "web-ui",
|
||||
"expires_in_hours": 72,
|
||||
"metadata": {
|
||||
"source": "ops-center"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
返回体关键字段:
|
||||
|
||||
- `token`
|
||||
- `token_preview`
|
||||
- `record_id`
|
||||
- `node_code`
|
||||
- `expires_at`
|
||||
- `created_at`
|
||||
|
||||
### 5.2 Bootstrap Plan
|
||||
|
||||
`POST /api/v1/ops/agent/bootstrap-plan`
|
||||
|
||||
请求体最小字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02",
|
||||
"node_region": "mainland",
|
||||
"node_role": "worker",
|
||||
"issued_by": "web-ui",
|
||||
"expires_in_hours": 72,
|
||||
"control_plane_base_url": "https://ops.example.com",
|
||||
"root_dir": "/opt/domaincheck",
|
||||
"metadata": {
|
||||
"source": "ops-center"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
返回体关键字段:
|
||||
|
||||
- Token 相关字段
|
||||
- `control_plane_base_url`
|
||||
- `bootstrap_plan.node_code`
|
||||
- `bootstrap_plan.node_region`
|
||||
- `bootstrap_plan.node_role`
|
||||
- `bootstrap_plan.root_dir`
|
||||
- `bootstrap_plan.env_file`
|
||||
- `bootstrap_plan.service_name`
|
||||
- `bootstrap_plan.service_file`
|
||||
- `bootstrap_plan.install_script_path`
|
||||
- `bootstrap_plan.env_content`
|
||||
- `bootstrap_plan.command_lines`
|
||||
- `bootstrap_plan.command_block`
|
||||
- `bootstrap_plan.health_checks`
|
||||
- `bootstrap_plan.health_check_block`
|
||||
- `bootstrap_plan.bootstrap_script_name`
|
||||
- `bootstrap_plan.bootstrap_script_path`
|
||||
- `bootstrap_plan.bootstrap_script_content`
|
||||
- `bootstrap_plan.bootstrap_run_script_block`
|
||||
|
||||
约束:
|
||||
|
||||
- `bootstrap_plan` 是标准接入方案对象
|
||||
- 页面、Codex、CLI 必须复用这一个对象
|
||||
- 不允许各端再次手写 env 或 shell 逻辑
|
||||
|
||||
---
|
||||
|
||||
## 6. Runtime Contract
|
||||
|
||||
### 6.1 Register
|
||||
|
||||
`POST /api/v1/ops/agent/register`
|
||||
|
||||
语义:
|
||||
|
||||
- 校验 Token 与 `node_code`
|
||||
- Upsert Agent 运行态
|
||||
- 将节点推入托管目录候选态
|
||||
|
||||
最小成功返回字段:
|
||||
|
||||
- `node_code`
|
||||
- `expires_at`
|
||||
- `capabilities`
|
||||
|
||||
### 6.2 Heartbeat
|
||||
|
||||
`POST /api/v1/ops/agent/heartbeat`
|
||||
|
||||
语义:
|
||||
|
||||
- 刷新 `last_seen_at`
|
||||
- 刷新节点身份、服务名和队列快照
|
||||
- 维持控制面中的 Agent 在线态
|
||||
|
||||
最小成功返回字段:
|
||||
|
||||
- `node_code`
|
||||
- `server_time`
|
||||
- `expires_at`
|
||||
|
||||
### 6.3 Pull
|
||||
|
||||
`POST /api/v1/ops/agent/pull?limit=1`
|
||||
|
||||
请求体最小字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02"
|
||||
}
|
||||
```
|
||||
|
||||
返回体关键字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"id": 123,
|
||||
"job_code": "ops-xxx",
|
||||
"action": "health.snapshot",
|
||||
"target_node_code": "mainland-worker-02",
|
||||
"status": "dispatching",
|
||||
"execution_mode": "remote-agent",
|
||||
"payload": {},
|
||||
"metadata": {},
|
||||
"policy": {},
|
||||
"steps": []
|
||||
}
|
||||
],
|
||||
"count": 1
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- Agent 只能拿到属于自己的任务
|
||||
- Agent 不负责选择任务
|
||||
- 调度权始终在控制面
|
||||
|
||||
### 6.3.1 Agent Job Envelope
|
||||
|
||||
为了避免 Agent 再从自然语言动作名里“猜执行上下文”,`pull.data.jobs[]` 当前已经按统一任务包裹返回。
|
||||
|
||||
当前 `pull.data` 顶层也会额外带:
|
||||
|
||||
- `protocol_version`
|
||||
- `envelope_type`
|
||||
- `node_code`
|
||||
- `limit`
|
||||
- `count`
|
||||
|
||||
推荐最小结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol_version": "ops-agent/v1",
|
||||
"envelope_type": "agent_job",
|
||||
"id": 123,
|
||||
"job_id": 123,
|
||||
"job_code": "ops-20260418-001",
|
||||
"job_type": "ops_action",
|
||||
"action": "logs.collect",
|
||||
"target_node_code": "mainland-worker-02",
|
||||
"status": "dispatching",
|
||||
"execution_mode": "remote-agent",
|
||||
"step_key": "worker_logs",
|
||||
"step_title": "收集 Worker 日志",
|
||||
"job_ref": {
|
||||
"job_id": 123,
|
||||
"job_code": "ops-20260418-001",
|
||||
"action": "logs.collect",
|
||||
"target_node_code": "mainland-worker-02"
|
||||
},
|
||||
"step_ref": {
|
||||
"step_id": 456,
|
||||
"step_key": "worker_logs",
|
||||
"step_title": "收集 Worker 日志"
|
||||
},
|
||||
"payload": {
|
||||
"service_name": "domaincheck-worker",
|
||||
"lines": 120,
|
||||
"include_agent_logs": false
|
||||
},
|
||||
"policy": {
|
||||
"timeout_seconds": 120,
|
||||
"stop_on_failure": true,
|
||||
"auto_approve": true
|
||||
},
|
||||
"metadata": {
|
||||
"requested_by": "playbook:inspection.standard",
|
||||
"source": "ops-center"
|
||||
},
|
||||
"release_context": {
|
||||
"release_id": 0,
|
||||
"release_version": "",
|
||||
"rollout_id": 0,
|
||||
"rollout_code": ""
|
||||
},
|
||||
"focus_ref": {
|
||||
"kind": "ops_job",
|
||||
"job_id": 123,
|
||||
"job_code": "ops-20260418-001",
|
||||
"action": "logs.collect",
|
||||
"target_node_code": "mainland-worker-02"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
正式要求:
|
||||
|
||||
- Agent 必须优先消费:
|
||||
- `action`
|
||||
- `payload`
|
||||
- `policy`
|
||||
- Agent 不应通过:
|
||||
- `step_title`
|
||||
- `summary`
|
||||
- `notes`
|
||||
去反推真实执行参数
|
||||
- 与发布相关的任务应通过:
|
||||
- `release_context`
|
||||
传递 release / rollout 关联,而不是让 Agent 自己查询“当前版本”
|
||||
|
||||
这层的意义是:
|
||||
|
||||
- `ops job`
|
||||
- 仍是正式执行颗粒度
|
||||
- `Agent Job Envelope`
|
||||
- 是 Node Agent 拿到的稳定执行视图
|
||||
|
||||
这样同一套 Agent 才能同时承接:
|
||||
|
||||
- 标准巡检
|
||||
- 日志收集
|
||||
- 诊断采样
|
||||
- Release 部署
|
||||
- Rollout 回滚
|
||||
|
||||
### 6.4 Start
|
||||
|
||||
`POST /api/v1/ops/agent/jobs/{job_id}/start`
|
||||
|
||||
请求体最小字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02"
|
||||
}
|
||||
```
|
||||
|
||||
语义:
|
||||
|
||||
- `dispatching` 表示已派发
|
||||
- `running` 表示节点已真实开工
|
||||
|
||||
### 6.5 Complete
|
||||
|
||||
`POST /api/v1/ops/agent/jobs/{job_id}/complete`
|
||||
|
||||
请求体最小字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02",
|
||||
"client_request_id": "complete-ops-123-1",
|
||||
"status": "success",
|
||||
"stdout": "",
|
||||
"stderr": "",
|
||||
"result": {
|
||||
"summary": "ok"
|
||||
},
|
||||
"error_message": ""
|
||||
}
|
||||
```
|
||||
|
||||
允许状态:
|
||||
|
||||
- `success`
|
||||
- `failed`
|
||||
- `partially_succeeded`
|
||||
|
||||
幂等约束:
|
||||
|
||||
- 使用 `client_request_id`
|
||||
- 控制面写入 `ops_jobs.last_agent_complete_request_id`
|
||||
- 同一完成回执可安全重放,不应再次制造副作用
|
||||
|
||||
推荐补充字段:
|
||||
|
||||
- `duration_ms`
|
||||
- `result.summary_text`
|
||||
- `result.focus_ref`
|
||||
|
||||
当前成功返回里也会额外带:
|
||||
|
||||
- `completion_summary.job_id`
|
||||
- `completion_summary.job_code`
|
||||
- `completion_summary.status`
|
||||
- `completion_summary.status_label`
|
||||
- `completion_summary.result_summary_text`
|
||||
- `completion_summary.focus_ref`
|
||||
- `completion_summary.deduplicated`
|
||||
|
||||
这样控制面在不展开 stdout/stderr 的情况下,也能直接把:
|
||||
|
||||
- 任务收口摘要
|
||||
- 后续跳转落点
|
||||
|
||||
并入 activity / inspection / rollout 观察面。
|
||||
|
||||
### 6.6 Events
|
||||
|
||||
`POST /api/v1/ops/agent/jobs/{job_id}/events`
|
||||
|
||||
请求体最小字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02",
|
||||
"client_event_id": "event-ops-123-checksum-1",
|
||||
"step_id": 0,
|
||||
"event_type": "deploy_checksum_verified",
|
||||
"level": "info",
|
||||
"message": "checksum ok",
|
||||
"payload": {
|
||||
"checksum": "sha256:..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
去重约束:
|
||||
|
||||
- 使用 `client_event_id`
|
||||
- 控制面通过唯一索引去重
|
||||
- 同一事件可安全重放,不应重复落库
|
||||
|
||||
推荐补充字段:
|
||||
|
||||
- `occurred_at`
|
||||
- `summary_text`
|
||||
- `focus_ref`
|
||||
|
||||
当前成功返回里也会额外带:
|
||||
|
||||
- `event`
|
||||
- 即标准化后的事件对象
|
||||
- 内含 `event_key / summary_text / occurred_at / focus_ref`
|
||||
|
||||
这样事件流就不再只是“原始日志点”,而能直接成为:
|
||||
|
||||
- playbook run events
|
||||
- rollout events
|
||||
- activity-stream
|
||||
|
||||
共同消费的现场片段。
|
||||
|
||||
---
|
||||
|
||||
## 7. Agent 本地补发队列
|
||||
|
||||
当前主链路已经正式具备:
|
||||
|
||||
- `pending` 队列
|
||||
- `dead-letter` 队列
|
||||
- 定时 `_flush_delivery_queue()`
|
||||
- 永久性错误转死信
|
||||
|
||||
当前重点覆盖:
|
||||
|
||||
- `jobs/{id}/complete`
|
||||
- `jobs/{id}/events`
|
||||
|
||||
队列状态:
|
||||
|
||||
- `healthy`
|
||||
- `retrying`
|
||||
- `dead_letter`
|
||||
|
||||
语义:
|
||||
|
||||
- `healthy`:无积压,无死信
|
||||
- `retrying`:存在待补发回执,Agent 会继续自动重放
|
||||
- `dead_letter`:存在永久失败记录,需人工介入
|
||||
|
||||
控制面消费方式:
|
||||
|
||||
- 节点维度:
|
||||
- `delivery_queue_state`
|
||||
- `delivery_queue_label`
|
||||
- `delivery_queue_reason`
|
||||
- `delivery_queue_pending_count`
|
||||
- `delivery_queue_dead_letter_count`
|
||||
- 汇总维度:
|
||||
- `queue_retrying_nodes`
|
||||
- `queue_dead_letter_nodes`
|
||||
- `queue_pending_records`
|
||||
- `queue_dead_letter_records`
|
||||
|
||||
### 7.1 当前控制面已可见的最小现场
|
||||
|
||||
当前至少已经可以通过:
|
||||
|
||||
- `GET /api/v1/ops/nodes`
|
||||
|
||||
看到每台托管节点的队列现场:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02",
|
||||
"delivery_queue_state": "dead_letter",
|
||||
"delivery_queue_label": "死信 2",
|
||||
"delivery_queue_reason": "当前存在 2 条死信记录,建议优先查看节点日志或诊断编排。",
|
||||
"delivery_queue_pending_count": 0,
|
||||
"delivery_queue_dead_letter_count": 2,
|
||||
"delivery_queue_last_flush_at": "2026-04-18 06:10:00",
|
||||
"delivery_queue_oldest_pending_at": "",
|
||||
"delivery_queue_oldest_pending_request_id": "",
|
||||
"delivery_queue_oldest_pending_kind": "",
|
||||
"delivery_queue_oldest_dead_letter_at": "2026-04-18 05:59:00",
|
||||
"delivery_queue_oldest_dead_letter_request_id": "complete-ops-123-1",
|
||||
"delivery_queue_oldest_dead_letter_kind": "job_complete"
|
||||
}
|
||||
```
|
||||
|
||||
这已经足够让:
|
||||
|
||||
- 页面显示“节点存在死信”
|
||||
- `overview / driver-feed / codex-brief` 产出驾驶建议
|
||||
- CLI 快速判断现场是不是要先走日志或诊断
|
||||
|
||||
但这还不够支撑正式运维,因为它只能“看见死信”,还不能“处理死信”。
|
||||
|
||||
### 7.2 Delivery Queue Record 正式对象
|
||||
|
||||
后续控制面不应再把死信理解成一个纯计数器,而要把每条待补发 / 死信记录升级成正式对象。
|
||||
|
||||
推荐最小结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"record_id": "dq-mainland-worker-02-20260418-001",
|
||||
"node_code": "mainland-worker-02",
|
||||
"state": "dead_letter",
|
||||
"request_kind": "job_complete",
|
||||
"client_request_id": "complete-ops-123-1",
|
||||
"job_id": 123,
|
||||
"job_code": "ops-20260418-001",
|
||||
"target_api": "/api/v1/ops/agent/jobs/123/complete",
|
||||
"detail_code": "ops_job_invalid_status_transition",
|
||||
"error_message": "当前任务状态不允许 complete",
|
||||
"attempt_count": 6,
|
||||
"first_queued_at": "2026-04-18 05:58:00",
|
||||
"last_attempt_at": "2026-04-18 05:59:00",
|
||||
"next_retry_at": "",
|
||||
"payload_preview": {
|
||||
"status": "success"
|
||||
},
|
||||
"response_preview": {
|
||||
"code": 1,
|
||||
"detail_code": "ops_job_invalid_status_transition"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
正式约束:
|
||||
|
||||
- `record_id`
|
||||
- 是控制面侧唯一主键
|
||||
- `client_request_id`
|
||||
- 是 Agent 幂等键
|
||||
- `detail_code`
|
||||
- 是死信聚类主键,不能只靠 `message`
|
||||
- `payload_preview / response_preview`
|
||||
- 用于页面和 Codex 快速判断,不必默认展开完整原始报文
|
||||
|
||||
推荐状态:
|
||||
|
||||
- `pending`
|
||||
- `retrying`
|
||||
- `dead_letter`
|
||||
- `replayed`
|
||||
- `discarded`
|
||||
|
||||
### 7.3 死信操作面正式入口
|
||||
|
||||
为了让“看见死信”之后不用回节点本地处理,推荐把操作面固定成下面这组接口。
|
||||
|
||||
当前已落地的第一阶段能力:
|
||||
|
||||
- `GET /api/v1/ops/nodes/{node_code}/delivery-queue`
|
||||
- `GET /api/v1/ops/nodes/{node_code}/delivery-queue/records`
|
||||
|
||||
当前控制面返回的记录可见性为:
|
||||
|
||||
- `record_visibility=head_only`
|
||||
|
||||
也就是:
|
||||
|
||||
- 当前已经能稳定查看节点级队列总览
|
||||
- 也能看到 `pending / dead_letter` 的头部记录摘要
|
||||
- 但还没有把节点本地全量 `pending/*.json / dead-letter/*.json` 正式同步到控制面
|
||||
|
||||
所以这两条 GET 入口现在属于“正式只读观察面”,而不是完整操作面。
|
||||
|
||||
#### a. 单节点队列总览
|
||||
|
||||
- `GET /api/v1/ops/nodes/{node_code}/delivery-queue`
|
||||
|
||||
最小返回体:
|
||||
|
||||
```json
|
||||
{
|
||||
"node_code": "mainland-worker-02",
|
||||
"summary": {
|
||||
"state": "dead_letter",
|
||||
"pending_count": 0,
|
||||
"dead_letter_count": 2,
|
||||
"last_flush_at": "2026-04-18 06:10:00"
|
||||
},
|
||||
"oldest_pending_record": {},
|
||||
"oldest_dead_letter_record": {}
|
||||
}
|
||||
```
|
||||
|
||||
#### b. 队列记录列表
|
||||
|
||||
- `GET /api/v1/ops/nodes/{node_code}/delivery-queue/records`
|
||||
|
||||
推荐筛选参数:
|
||||
|
||||
- `state=pending|retrying|dead_letter|replayed|discarded`
|
||||
- `request_kind=job_complete|job_event`
|
||||
- `detail_code=...`
|
||||
- `group_by=detail_code|request_kind|target_api`
|
||||
- `limit=50`
|
||||
|
||||
当带 `group_by` 时,返回值应优先给出聚类摘要,而不是只返回平铺明细。
|
||||
|
||||
#### c. 单条死信重放
|
||||
|
||||
- `POST /api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/replay`
|
||||
|
||||
当前已落地,但要明确当前阶段约束:
|
||||
|
||||
- 控制面仍然是 `record_visibility=head_only`
|
||||
- 所以单条动作目前只允许针对“当前可见头部记录”
|
||||
- 真正的执行不是控制面直接改远端文件,而是创建正式 `ops job`
|
||||
- 由目标节点 `Node Agent` 执行 `delivery.queue.replay`
|
||||
|
||||
最小请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"requested_by": "web-ui",
|
||||
"reason": "确认任务状态已修复,重放这条 complete 回执"
|
||||
}
|
||||
```
|
||||
|
||||
#### d. 批量重放
|
||||
|
||||
- `POST /api/v1/ops/nodes/{node_code}/delivery-queue/replay`
|
||||
|
||||
当前已落地为正式操作面。
|
||||
|
||||
推荐请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"requested_by": "codex",
|
||||
"selector": {
|
||||
"state": "dead_letter",
|
||||
"detail_code": "ops_job_invalid_status_transition"
|
||||
},
|
||||
"limit": 20
|
||||
}
|
||||
```
|
||||
|
||||
#### e. 丢弃死信
|
||||
|
||||
- `POST /api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/discard`
|
||||
|
||||
当前已落地,但与单条重放一样,仍然只允许针对当前可见头部死信记录发起单条动作。
|
||||
|
||||
最小请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"discarded_by": "web-ui",
|
||||
"reason": "确认这条回执不再需要补发"
|
||||
}
|
||||
```
|
||||
|
||||
#### f. 主动冲刷队列
|
||||
|
||||
- `POST /api/v1/ops/nodes/{node_code}/delivery-queue/flush`
|
||||
|
||||
当前已落地为正式操作面,执行方式同样是:
|
||||
|
||||
- 控制面创建 `ops job`
|
||||
- 目标节点 `Node Agent` 执行 `delivery.queue.flush`
|
||||
|
||||
语义:
|
||||
|
||||
- 不是“强行成功”
|
||||
- 而是立即触发一次 Agent 补发冲刷
|
||||
- 结果仍然回到 `pending / retrying / dead_letter / replayed`
|
||||
|
||||
### 7.4 为什么必须做成正式操作面
|
||||
|
||||
这层不是为了让页面多一个按钮,而是为了保证:
|
||||
|
||||
- 页面可以处理死信
|
||||
- CLI 可以处理死信
|
||||
- 海外 Codex 驾驶员可以处理死信
|
||||
|
||||
三者都不需要绕回:
|
||||
|
||||
- 手工 SSH 登录节点
|
||||
- 手工删本地文件
|
||||
- 手工重放某条 HTTP 请求
|
||||
|
||||
正式规则应该固定成:
|
||||
|
||||
- “死信查看” 走控制面对象
|
||||
- “死信重放 / 丢弃 / 冲刷” 走控制面对象
|
||||
- Agent 只负责执行,不负责决定如何处理死信
|
||||
|
||||
---
|
||||
|
||||
## 8. Job Status Enum
|
||||
|
||||
当前 Agent 主链路约束:
|
||||
|
||||
- `queued`
|
||||
- `dispatching`
|
||||
- `running`
|
||||
- `success`
|
||||
- `failed`
|
||||
- `partially_succeeded`
|
||||
|
||||
语义:
|
||||
|
||||
- `queued`:任务已创建,尚未派发
|
||||
- `dispatching`:控制面已派发,但节点尚未确认开工
|
||||
- `running`:节点已真实执行
|
||||
- `success`:成功完成
|
||||
- `failed`:失败完成
|
||||
- `partially_succeeded`:部分成功,需关注
|
||||
|
||||
---
|
||||
|
||||
## 9. 实现边界
|
||||
|
||||
Agent 只执行已声明动作:
|
||||
|
||||
- `service.start`
|
||||
- `service.stop`
|
||||
- `service.restart`
|
||||
- `service.status`
|
||||
- `health.snapshot`
|
||||
- `logs.collect`
|
||||
- `diagnostics.collect`
|
||||
- `deploy.release`
|
||||
|
||||
不允许控制面长期依赖任意 shell 下发。
|
||||
|
||||
`shell executor` 只能作为受限兜底能力存在,并必须挂审批与审计。
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user