This commit is contained in:
Your Name
2026-04-16 21:35:47 +08:00
parent ff32aa50bf
commit ebf632e651
86 changed files with 14097 additions and 585 deletions

View File

@@ -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 发布所需的核心验收项,后续重点不再是功能开发,而是正式环境收口与上线后观察。

View File

@@ -55,13 +55,20 @@
- 上线前灰度发布
- 发布后观察期
补充说明:
- Linux 测试服基础联调已完成
- 正式 `systemd` 服务态已验证通过
- 当前进入的是“正式上线前最后检查与观察”阶段
## 五、建议下一步
1. 把最新交付包发送到目标 Linux 服务器
2.`docs/05``docs/07``docs/08` 的顺序执行部署与验收
3. 部署完成后再做一次真实环境 smoke test
4. 进入灰度上线
2.`docs/05``docs/13``docs/14` 的顺序执行部署、核对与收口
3. 部署完成后再做一次正式服务态 `smoke test`
4. 导出一份最终诊断包
5. 进入灰度上线
## 六、最终判断
当前这套项目,已经达到“工程交付完成,待真实环境上线联调”的状态。
当前这套项目,已经达到“工程交付完成,Linux 测试服联调闭环,待正式环境上线收口”的状态。

View File

@@ -20,6 +20,22 @@
- `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`
## 二、文档阅读顺序
### 1. 先看总体方案
@@ -33,6 +49,10 @@
- `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`
### 3. 如果要回溯历史需求与问题
@@ -63,6 +83,9 @@
- `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/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`

View File

@@ -23,17 +23,21 @@
- 交付包、验包、SHA256、最新交付指针已完成
- Linux 测试服数据库初始化问题已定位并修复
- Linux 测试服在“临时 API 进程 + 已初始化数据库”的模式下,`smoke test` 已通过
- Linux 测试服已经完成正式 `systemd` 服务化联调,`domaincheck-api``domaincheck-worker` 均已拉起
- 正式服务态下 `/health` 已确认 `worker_mode = linux-systemd`
- 正式服务态 `smoke test` 已通过
- 已补做一轮真实导入回归,确认“导入域名 -> 写入 `domains` -> 自动创建 `detect_tasks`”链路正常
### 2. 未完全完成
- Linux 测试服当前还不是最终正式部署形态
- 这次通过的是“临时启动 API 进程”的验证,不是正式 `systemd` 服务托管态
- `worker_mode` 当前仍表现为 `windows-local`
- `domaincheck-api` / `domaincheck-worker` 还没有按正式生产口径落成 Linux `systemd` 服务闭环
- Linux 测试服虽然已完成正式服务化联调,但仍属于“测试服验证通过”,不等于生产观察期已经完成
- Worker 当前通过 `QT_QPA_PLATFORM=offscreen` 运行,属于“无头 Qt 托管态”,后续仍建议继续观察稳定性
- 真实业务网络环境下的长时检测、代理池质量、Wayback 首次全量列表耗时,还需要继续压测和观察
- 当前数据库里仅导入了少量回归样本,不代表真实大批量数据已完成验收
一句话结论:
> 功能数据库问题已经打通;正式 Linux 上线态还差最后一段服务化收口
> 功能数据库和正式服务化都已经打通;后续工作转入真实业务回归、稳定性观察和上线前优化
## 三、这次 Linux 测试服已验证通过的内容
@@ -79,7 +83,7 @@ python init_database.py
- 库结构已正常
- 只是当前还没有正式业务数据导入
### 3. smoke test 已通过
### 3. 临时验证态 smoke test 已通过
新版 `smoke test` 结果:
@@ -96,7 +100,7 @@ python init_database.py
- Redis 连接可用
- 缺表问题已解除
### 4. 诊断包已导出
### 4. 临时验证态诊断包已导出
本次测试服诊断产物:
@@ -105,36 +109,95 @@ python init_database.py
可用于后续继续排障或归档。
## 四、当前测试服不是正式上线态的原因
## 四、正式服务态已补验证通过
虽然 `smoke test` 已通过,但当前仍不是正式上线态,原因如下:
在后续继续收口过程中,已经额外完成了正式 `systemd` 服务态验证,结果如下:
### 1. 当前通过的是临时 API 进程验证
### 1. 正式服务已落地
本次验证是通过“当前工作区里手动启动的 API 进程”完成的,不是通过正式服务方式完成的。
### 2. worker_mode 仍不是 Linux 正式模式
当前表现仍是:
- `worker_mode = windows-local`
这意味着:
- 运行中心、配置项、控制逻辑还没有真正切到 Linux 正式托管模式
- 当前仍属于“测试验证态”
### 3. systemd 服务还未正式落地闭环
还没有最终确认以下两项处于正式可用状态:
已安装并启用:
- `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`
- 正式测试服日志更适合持续观察和上线前留档
## 五、这次联调后已经明确固化的部署规则
@@ -169,6 +232,7 @@ python init_database.py
- `domain-web` 主要页面已完成
- `domain-api` 主要接口已完成
- 运行中心、系统设置、导入、导出、日志诊断、自检、自测均已具备
- 正式 `systemd` 服务态下 `/health``/runtime/preflight``/runtime/status``smoke test` 已全部通过
### 3. 交付层
@@ -185,56 +249,23 @@ python init_database.py
- Linux 联调输入清单已完成
- 导航索引文档已完成
### 5. 真实业务回归层
- 已通过 API 上传样本 TXT
- 已确认导入结果:
- 总数 `5`
- 有效 `3`
- 新增 `3`
- 无效 `2`
- 已确认 `domains_total = 3`
- 已确认 `detect_tasks_total = 3`
- 已确认导入后会自动创建 `detect_tasks`
## 七、当前未完成项清单
以下内容仍属于“后续要做”:
### 1. 正式 Linux 目录落地
需要确认正式部署目录结构为:
```text
/opt/domaincheck
├── domainCheck
├── domain-api
├── domain-web
```
如果测试服当前目录不是这一套,需要统一。
### 2. 正式 systemd 服务化
需要把以下服务真正落好并验证:
- `domaincheck-api`
- `domaincheck-worker`
至少要完成:
- 安装 service 文件
- `daemon-reload`
- `enable`
- `start`
- `status`
- `journalctl`
### 3. worker_mode 切换为 linux-systemd
需要确认:
- Web 系统设置中运行模式改为 `linux-systemd`
- API `/health` 或运行中心能正确反映:
- `worker_mode = linux-systemd`
### 4. 正式服务态再跑一次 smoke test
不是临时 API 进程跑通就结束,还要在正式服务态下再跑一次:
```bash
python smoke_test.py --base-url http://127.0.0.1:8100
```
### 5. Worker 真实联动验证
### 1. Worker 真实联动验证
还应继续确认:
@@ -243,17 +274,26 @@ python smoke_test.py --base-url http://127.0.0.1:8100
- 检测控制页读取是否正常
- `detect_worker.log` 是否正常写入
### 6. 导入真实数据后的业务复测
### 2. 导入更多真实数据后的业务复测
当前 `domains_count = 0`,说明库表正常,但业务数据还没开始导入
当前已经完成一轮小样本回归,不再是空库空表态
后续应至少补一次真实业务复测:
- 导入域名
- 查看 `domains` 增长
- 查看 `detect_tasks` 生成
- 导入更接近真实业务规模的域名样本
- 查看 `domains` 持续增长
- 查看 `detect_tasks` 持续生成
- 再验证筛选与导出
### 3. 长时间运行与代理池观察
仍建议继续验证:
- Worker 长时运行稳定性
- Redis 订阅超时后的重连是否持续稳定
- 国内网络环境下代理池真实可用率
- Wayback 首次全量快照列表的耗时表现
## 八、后续继续收口的推荐顺序
建议 Linux 上的下一位接手人严格按下面顺序执行。
@@ -291,6 +331,11 @@ order by tablename;
- `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
@@ -318,6 +363,16 @@ 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`

View File

@@ -0,0 +1,244 @@
# 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`
## 二、上线前必须确认的结论
上线前至少要确认下面这些结论同时成立:
- `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` 控制链路可用
- 导入、筛选、批量更新、导出四条核心业务链路至少各回归一次
- 诊断包可正常导出
## 三、正式上线前执行顺序
### 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 测试服联调、正式服务态验证和关键日志降噪;剩余工作主要是正式环境发布与上线后观察,不再是功能性大修。

View 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`

View 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不再重构核心架构。

View File

@@ -0,0 +1,647 @@
# 17 domainCheck 全流程部署实操手册
## 一、文档目标
这份文档不是设计说明,也不是零散检查单,而是给实际部署时直接照着做的“全流程操作手册”。
适用场景:
- 先在国外机器完成单机部署与联调
- 后续再扩到“国外控制面 + 大陆执行面”
- 当前暂时无法把代码真正部署到大陆机器时,先在国外机器模拟多节点联调
- 最后再把同样的部署方式复制到其他机器
一句话理解:
> 先把国外主控机部署好,再按同样套路扩第二台、第三台,不靠临场猜。
并发配置补充:
- 系统支持 `默认线程数 + 节点单独覆盖`
- 节点单独覆盖按机器自己的 `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
### 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` 管理和更新,不再手工散传目录。
第一次部署建议:
```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
```
### 2. 创建 Python 虚拟环境
```bash
cd /opt/domaincheck/domainCheck
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.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
```
### 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. 最后再做真实跨地域联调
一句话总结:
> 先把单机跑稳,再把多机脚本跑通,最后再扩机器;每一步都有现成脚本,不靠现场猜。

File diff suppressed because it is too large Load Diff