feat: stabilize multi-region runtime sync and worker orchestration
This commit is contained in:
84
docs/shenhe.md
Normal file
84
docs/shenhe.md
Normal file
@@ -0,0 +1,84 @@
|
||||
可以,按“尽量省额度但不丢高风险”的思路,我建议你把全项目审核拆成 3 轮,目标控制在 `800万 ~ 1200万 tokens`。
|
||||
|
||||
**先排除**
|
||||
第一轮先不要审这些,不然额度会被白白吃掉:
|
||||
|
||||
- `release/`
|
||||
- `.venv/`
|
||||
- `node_modules/`
|
||||
- `domain-web/package-lock.json`
|
||||
- `domainCheck/app/sdk_leg.js`
|
||||
- `domainCheck/detect/sdk_leg.js`
|
||||
- 运行时产物、日志、快照、历史 night runs
|
||||
- 大 JSON 词库这类静态数据,除非代码直接依赖逻辑可疑
|
||||
|
||||
**三轮顺序**
|
||||
1. 控制面与数据正确性
|
||||
预算:`300万 ~ 450万`
|
||||
- `domain-api/app/services/detect_job_service.py`
|
||||
- `domain-api/app/services/detect_service.py`
|
||||
- `domain-api/app/services/runtime_status_service.py`
|
||||
- `domain-api/app/services/dashboard.py`
|
||||
- `domain-api/app/services/sync_record_service.py`
|
||||
- `domain-api/app/services/sync_push_service.py`
|
||||
- `domain-api/app/services/worker_control_service.py`
|
||||
- `domain-api/app/services/settings_service.py`
|
||||
- `domain-api/app/services/cluster_runtime_service.py`
|
||||
- 对应 `routes/` 和关键测试
|
||||
|
||||
这一轮最值钱,因为它直接查:
|
||||
- 页面显示为什么和现场不一致
|
||||
- sync 为什么会把旧状态盖新状态
|
||||
- runtime projection / queue health / active job 是否互相打架
|
||||
- 配置下发和节点实际执行是否一致
|
||||
|
||||
2. Worker 并发与执行链
|
||||
预算:`300万 ~ 400万`
|
||||
- `domainCheck/detect_worker.py`
|
||||
- `domainCheck/app/utils/database.py`
|
||||
- `domainCheck/app/detectors/`
|
||||
- `domainCheck/detect/`
|
||||
- `domainCheck/tests/` 里和并发、连接池、超时、代理有关的测试
|
||||
|
||||
这一轮重点查:
|
||||
- 多进程 / 多线程是否真能提升吞吐
|
||||
- DB 连接池、代理池、任务领取链有没有硬瓶颈
|
||||
- 内存为什么高、进程为什么空转
|
||||
- 超时、重试、降级逻辑是否会拖垮吞吐
|
||||
|
||||
3. 发布、运维、前端展示
|
||||
预算:`200万 ~ 300万`
|
||||
- `domain-api/deploy/`
|
||||
- `domain-api/app/node_agent.py`
|
||||
- `domain-api/app/services/ops_*`
|
||||
- `domain-web/src/views/detect/`
|
||||
- `domain-web/src/views/runtime/`
|
||||
- `domain-web/src/views/settings/`
|
||||
- systemd 模板、迁移/发布脚本
|
||||
|
||||
这一轮重点查:
|
||||
- 发布链和实际运行是否一致
|
||||
- 多实例 worker 的部署是否完整
|
||||
- 前端是否误导运维判断
|
||||
- 迁移、接管、rollout 有没有高风险坑
|
||||
|
||||
**模型建议**
|
||||
- 第 1 轮:`gpt-5.4 + xhigh`
|
||||
- 第 2 轮:`gpt-5.4 + xhigh`
|
||||
- 第 3 轮:`gpt-5.4 + high`
|
||||
|
||||
这样通常能把额度压在你要的区间里。
|
||||
|
||||
**输出方式**
|
||||
每轮都只要这 3 类结果,最省额度:
|
||||
|
||||
- `P0/P1` 真实问题
|
||||
- 影响面
|
||||
- 修复建议
|
||||
|
||||
不要第一轮就让模型写大篇架构说明,不然额度会烧很快。
|
||||
|
||||
一句话版:
|
||||
先审 `domain-api` 的状态/同步链,再审 `domainCheck` 的并发执行链,最后审 `deploy + ops + 前端展示`;按这个顺序,`800万~1200万 tokens` 是有机会压住的。
|
||||
|
||||
如果你要,我下一步可以直接给你生成一份“第一轮审核清单”,精确到文件名单。
|
||||
58
docs/test.md
58
docs/test.md
@@ -62,7 +62,65 @@ controller syncer 批量同步海外主库
|
||||
↓
|
||||
controller finalizer 标记本次流程完成
|
||||
|
||||
发现问题
|
||||
主体功能
|
||||
1.去后台点击 聚名获取删除域名入库
|
||||
2.按后台勾选 的检测选项,按顺序逐个去跑
|
||||
3.正常逻辑是按顺序 一步一步前面的处理完了,再往下一个处理,最大进程跑起来,直到所有任务跑完
|
||||
|
||||
现在遇到的问题是:
|
||||
1.后台展示文案的歧义非常大;运营很难理解
|
||||
比喻托管节点:这个应该就是 服务器管理,现在你把进程也算是一个节点,全部放到这个列表,我看起来都蒙,如果需要你可以加多一个进程管理不就好了,不要混一起
|
||||
现在后台应该有 机器/进程/线程,节点到底是啥?现在已经乱了,
|
||||
|
||||
运行配置这块也是 节点独立线程覆盖 你把所有进程都列出来配置 线程数量,这个不需要的,所有进程的线程数量全部走默认的,进程那么大不会人工管理的,设计很不合理,
|
||||
|
||||
检测管理页面:日志输出窗口 这块也是
|
||||
参与节点:3 这个应该改成 参与 服务器
|
||||
参与进程:62 参与 进程
|
||||
参与 线程
|
||||
运行中:127
|
||||
线程:127 / 74000(参与节点汇总)
|
||||
要让人一眼看明白
|
||||
|
||||
2.最重要一点,后台页面的数据展示很多都是不符合实际的,很多一点,为啥黑名单一直是0,这块不肯定的,这个正常清空最少命中80%;
|
||||
进程和线程一直跑不起来,这个最致命,优化了好几日了,知道目前还是没跑通完整流程
|
||||
|
||||
|
||||
3.概览
|
||||
步骤队列
|
||||
看每一步堆积、吞吐和失败,快速判断到底卡在注册、百度、360、爱站还是站长之家。 这块应该按后台勾选设置的顺序拍下来,正常任务完成也是,一个跑完才会往下推,才会往下一个跑
|
||||
|
||||
|
||||
4.检测的进程和线程 机器 不稳定,不会自动检测 自动跑起来,就是最大性能没有跑起来
|
||||
|
||||
5.如果大陆controller 的DB链接数量是瓶颈,那可以每个大陆 机器都开启db+redis 反正每个机器的配置都很高的,只要有效率能提速
|
||||
|
||||
6.还有一个但海外机器绝对不参与worker 检测
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
一句话结论:
|
||||
|
||||
线上 hotfix 收口基本完成
|
||||
下一步最该继续的是代理供给优化,不是回到代码审核
|
||||
我下一步建议就直接转到代理链路,继续收:
|
||||
|
||||
为什么多实例同时刷新时会被代理源限流
|
||||
是否要继续压低单实例补货批量/频率
|
||||
是否要做更强的跨进程代理补货协调
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
大陆处理好的跑完流程域名是否返回海外机器勾选状态
|
||||
|
||||
|
||||
域名检测流程设计
|
||||
|
||||
229
docs/后台运行观察口径.md
Normal file
229
docs/后台运行观察口径.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# 后台运行观察口径
|
||||
|
||||
> 说明:这份文档主要解释页面怎么看。当前线上执行口径与判断顺序,统一以 [当前线上最终Runbook.md](/www/wwwroot/getDomain/docs/当前线上最终Runbook.md) 为准。
|
||||
|
||||
更新时间:`2026-04-24 14:24`
|
||||
|
||||
## 先说结论
|
||||
|
||||
以后不要先盯散乱日志。
|
||||
|
||||
日志只是辅助定位。
|
||||
|
||||
现在优先看后台 `运行中心` 第一屏。
|
||||
|
||||
那里已经会直接告诉你:
|
||||
|
||||
- 全库总盘子有多少
|
||||
- 当前活跃批次到底有多少
|
||||
- 近 15 分钟真实推进了多少
|
||||
- 当前到底算不算真跑起来了
|
||||
- 还有多少待处理
|
||||
- 真正有多少进程和线程在干活
|
||||
- 最近 15 分钟处理了多少
|
||||
- 失败多不多
|
||||
- 黑名单有没有推进
|
||||
- 当前最忙的是哪些进程
|
||||
- 主要积压卡在哪几个步骤
|
||||
|
||||
只有在后台页面临时不可用,或者你想在终端里持续盯时,才再用下面这条命令:
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/getDomain
|
||||
./.venv/bin/python tools/runtime_observer.py
|
||||
```
|
||||
|
||||
如果想持续盯着看,就用:
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/getDomain
|
||||
./.venv/bin/python tools/runtime_observer.py --watch 5
|
||||
```
|
||||
|
||||
它会把和后台首屏同一套核心数字收成一屏,不用再自己去拼:
|
||||
|
||||
- 当前任务是谁
|
||||
- 还有多少待处理
|
||||
- 真正有多少进程和线程在干活
|
||||
- 最近 15 分钟到底处理了多少
|
||||
- 失败多不多
|
||||
- 黑名单有没有推进
|
||||
- 哪几个节点真的在跑
|
||||
- 每一步卡在哪
|
||||
|
||||
## 先看哪 4 组数
|
||||
|
||||
脚本里最重要的是这 4 行:
|
||||
|
||||
### 1. 任务积压
|
||||
|
||||
看:
|
||||
|
||||
- `pending`
|
||||
- `claimed`
|
||||
- `running`
|
||||
|
||||
这组数回答的是:
|
||||
|
||||
- 还有多少活没做
|
||||
- 有没有任务已经被领走
|
||||
- 当前有多少任务处于运行中
|
||||
|
||||
### 2. 结果产出
|
||||
|
||||
看:
|
||||
|
||||
- `completed`
|
||||
- `failed`
|
||||
- `blacklisted`
|
||||
|
||||
这组数回答的是:
|
||||
|
||||
- 成功推进了多少
|
||||
- 失败了多少
|
||||
- 黑名单命中了多少
|
||||
|
||||
### 3. 执行面
|
||||
|
||||
看:
|
||||
|
||||
- `active_processes`
|
||||
- `active_threads`
|
||||
- `max_threads`
|
||||
|
||||
这组数回答的是:
|
||||
|
||||
- 现在到底有多少执行实例真的在动
|
||||
- 当前用了多少线程
|
||||
- 当前理论上限是多少
|
||||
|
||||
### 4. 最近吞吐
|
||||
|
||||
看:
|
||||
|
||||
- `processed_recent`
|
||||
- `per_minute`
|
||||
- `failed_recent`
|
||||
- `blacklisted_recent`
|
||||
|
||||
这组数回答的是:
|
||||
|
||||
- 最近 15 分钟有没有真实推进
|
||||
- 大概每分钟能跑多少
|
||||
- 最近失败是不是很多
|
||||
- 最近有没有新的黑名单命中
|
||||
|
||||
## 怎么判断“真跑起来了”
|
||||
|
||||
满足下面这 3 条,才算真跑:
|
||||
|
||||
1. `pending` 还有积压
|
||||
2. `active_threads` 不是 0
|
||||
3. `processed_recent` 持续增长
|
||||
|
||||
如果只是页面上显示 `running`,但:
|
||||
|
||||
- `active_threads` 接近 0
|
||||
- `processed_recent` 也接近 0
|
||||
|
||||
那更像是:
|
||||
|
||||
- 旧状态残影
|
||||
- 口径没收准
|
||||
- 或者任务挂着但没真正消化
|
||||
|
||||
## 怎么快速判断卡在哪
|
||||
|
||||
### 情况 1:`pending` 很高,`active_threads` 很低
|
||||
|
||||
说明更像:
|
||||
|
||||
- 没真正拉起执行面
|
||||
- worker 没开始干活
|
||||
- 或者任务没正确分发进去
|
||||
|
||||
### 情况 2:`active_threads` 不低,但 `failed_recent` 很高
|
||||
|
||||
说明更像:
|
||||
|
||||
- 不是没跑
|
||||
- 而是外部步骤在大量失败
|
||||
- 常见就是代理、RDAP、爱站、时光机这类链路超时
|
||||
|
||||
### 情况 3:`completed_recent` 很低,`blacklisted_recent` 也很低
|
||||
|
||||
说明更像:
|
||||
|
||||
- 线程虽然在跑
|
||||
- 但结果大多没形成有效推进
|
||||
- 更像在外部失败里空转
|
||||
|
||||
### 情况 4:节点列表里只有一台在有动作
|
||||
|
||||
说明更像:
|
||||
|
||||
- 当前真正承担执行的就一台
|
||||
- 其他节点可能只是在线
|
||||
- 或者只是历史残影,不是真正参与执行
|
||||
|
||||
## 为什么不要先盯日志
|
||||
|
||||
因为日志只能回答:
|
||||
|
||||
- 某一步报了什么错
|
||||
- 某个实例刚才做了什么
|
||||
|
||||
但它回答不了:
|
||||
|
||||
- 现在到底有多少进程真在跑
|
||||
- 一共跑成功了多少
|
||||
- 黑名单推进了多少
|
||||
- 当前整体吞吐是上升还是下降
|
||||
|
||||
所以顺序应该固定成:
|
||||
|
||||
1. 先看后台 `运行中心` 第一屏
|
||||
2. 再看节点列表和步骤分布
|
||||
3. 只有需要深挖时,再看 `runtime_observer.py` 或具体日志
|
||||
|
||||
## 一句话记法
|
||||
|
||||
先看:
|
||||
|
||||
- 有没有积压
|
||||
- 有没有执行面
|
||||
- 最近有没有吞吐
|
||||
|
||||
这 3 个一起动,才算真的在跑。
|
||||
|
||||
## 现在先看哪 3 块
|
||||
|
||||
后台第一屏已经拆成这 3 个核心口径:
|
||||
|
||||
### 1. 总盘子(全库)
|
||||
|
||||
回答的是:
|
||||
|
||||
- 海外主库现在一共有多少域名
|
||||
- 全库还有多少待检测
|
||||
- 全库已经通过、失败、黑名单各多少
|
||||
|
||||
### 2. 当前活跃批次
|
||||
|
||||
回答的是:
|
||||
|
||||
- 当前正在跑的是哪一批
|
||||
- 这一批的展示口径有多少
|
||||
- 这一批的原始口径有多少
|
||||
|
||||
这一块非常重要。
|
||||
|
||||
它不是全库总量。
|
||||
|
||||
### 3. 近窗吞吐
|
||||
|
||||
回答的是:
|
||||
|
||||
- 最近 15 分钟到底推进了多少
|
||||
- 每分钟大概多少
|
||||
- 最近完成、失败、黑名单各多少
|
||||
103
docs/审核顺序.md
Normal file
103
docs/审核顺序.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# 第一轮审核清单
|
||||
|
||||
第一轮目标:先查控制面、运行态聚合、同步链、节点控制和配置分发。
|
||||
|
||||
建议模型与强度:
|
||||
- `gpt-5.4`
|
||||
- `xhigh`
|
||||
|
||||
建议额度:
|
||||
- `300万 ~ 450万 tokens`
|
||||
|
||||
本轮不看:
|
||||
- `release/`
|
||||
- `.venv/`
|
||||
- `node_modules/`
|
||||
- 运行时日志、快照、night runs
|
||||
- 大型静态资源和锁文件
|
||||
|
||||
## 审核顺序
|
||||
|
||||
### P0:运行态与页面口径
|
||||
1. [domain-api/app/services/detect_job_service.py](/www/wwwroot/getDomain/domain-api/app/services/detect_job_service.py)
|
||||
重点看:`active_job`、`runtime_snapshot`、`runtime_ingest`、`distributed_node_stats`、`display_*` 字段是否会互相覆盖。
|
||||
2. [domain-api/app/services/detect_service.py](/www/wwwroot/getDomain/domain-api/app/services/detect_service.py)
|
||||
重点看:检测控制页口径、聚合线程数、参与节点/参与进程统计、零值回退逻辑。
|
||||
3. [domain-api/app/services/runtime_status_service.py](/www/wwwroot/getDomain/domain-api/app/services/runtime_status_service.py)
|
||||
重点看:运行中心聚合、`queue_health` 与 backlog 对齐、活跃任务判定。
|
||||
4. [domain-api/app/services/dashboard.py](/www/wwwroot/getDomain/domain-api/app/services/dashboard.py)
|
||||
重点看:首页总览是否复用旧快照、`queue_display_*` 和 `active_job` 是否一致。
|
||||
5. [domain-api/app/api/routes/detect.py](/www/wwwroot/getDomain/domain-api/app/api/routes/detect.py)
|
||||
重点看:检测控制接口有没有直接透传脏口径。
|
||||
6. [domain-api/app/api/routes/runtime.py](/www/wwwroot/getDomain/domain-api/app/api/routes/runtime.py)
|
||||
重点看:运行中心接口是否二次加工错误。
|
||||
7. [domain-api/app/api/routes/dashboard.py](/www/wwwroot/getDomain/domain-api/app/api/routes/dashboard.py)
|
||||
重点看:首页口径是否和服务层一致。
|
||||
|
||||
### P0:同步链与投影链
|
||||
8. [domain-api/app/services/sync_record_service.py](/www/wwwroot/getDomain/domain-api/app/services/sync_record_service.py)
|
||||
重点看:`runtime_projection`、`runtime_ingest`、未来时间记录、重复投影、自愈逻辑。
|
||||
9. [domain-api/app/services/sync_push_service.py](/www/wwwroot/getDomain/domain-api/app/services/sync_push_service.py)
|
||||
重点看:同步触发、推送条件、失败重试、是否会把旧状态推成新状态。
|
||||
10. [domain-api/app/services/cluster_runtime_service.py](/www/wwwroot/getDomain/domain-api/app/services/cluster_runtime_service.py)
|
||||
重点看:集群节点汇总、心跳、stale/offline 判定。
|
||||
11. [domain-api/app/services/debug_event_service.py](/www/wwwroot/getDomain/domain-api/app/services/debug_event_service.py)
|
||||
重点看:调试事件是否参与运行态推断,是否会误导当前任务。
|
||||
|
||||
### P0:节点控制与配置分发
|
||||
12. [domain-api/app/services/worker_control_service.py](/www/wwwroot/getDomain/domain-api/app/services/worker_control_service.py)
|
||||
重点看:worker 进程探测、当前状态读取、systemd 口径和实际进程口径是否一致。
|
||||
13. [domain-api/app/services/settings_service.py](/www/wwwroot/getDomain/domain-api/app/services/settings_service.py)
|
||||
重点看:`process_count`、`thread_count`、节点级覆盖、多实例父子节点映射。
|
||||
14. [domain-api/app/services/runtime_settings_service.py](/www/wwwroot/getDomain/domain-api/app/services/runtime_settings_service.py)
|
||||
重点看:运行态配置来源、热配置优先级、页面修改后是否真生效。
|
||||
15. [domain-api/app/services/runtime_control_service.py](/www/wwwroot/getDomain/domain-api/app/services/runtime_control_service.py)
|
||||
重点看:启动/停止/恢复对多实例 worker 是否安全。
|
||||
|
||||
### P1:检测任务主链
|
||||
16. [domain-api/app/services/detect_run_service.py](/www/wwwroot/getDomain/domain-api/app/services/detect_run_service.py)
|
||||
重点看:运行记录、cycle 事件、页面日志来源。
|
||||
17. [domain-api/app/services/domains_service.py](/www/wwwroot/getDomain/domain-api/app/services/domains_service.py)
|
||||
重点看:域名主数据是否和检测任务状态有交叉写入风险。
|
||||
18. [domain-api/app/services/import_task_service.py](/www/wwwroot/getDomain/domain-api/app/services/import_task_service.py)
|
||||
重点看:导入任务是否影响 backlog、是否能造成页面统计失真。
|
||||
|
||||
## 必看测试
|
||||
|
||||
### 直接对应运行态/聚合
|
||||
1. [domain-api/tests/test_detect_job_service.py](/www/wwwroot/getDomain/domain-api/tests/test_detect_job_service.py)
|
||||
2. [domain-api/tests/test_detect_service_status_fallback.py](/www/wwwroot/getDomain/domain-api/tests/test_detect_service_status_fallback.py)
|
||||
3. [domain-api/tests/test_runtime_status_service.py](/www/wwwroot/getDomain/domain-api/tests/test_runtime_status_service.py)
|
||||
4. [domain-api/tests/test_dashboard_service.py](/www/wwwroot/getDomain/domain-api/tests/test_dashboard_service.py)
|
||||
|
||||
### 直接对应同步链
|
||||
5. [domain-api/tests/test_sync_record_service.py](/www/wwwroot/getDomain/domain-api/tests/test_sync_record_service.py)
|
||||
6. [domain-api/tests/test_sync_push_service.py](/www/wwwroot/getDomain/domain-api/tests/test_sync_push_service.py)
|
||||
7. [domain-api/tests/test_cluster_runtime_service.py](/www/wwwroot/getDomain/domain-api/tests/test_cluster_runtime_service.py)
|
||||
|
||||
### 直接对应节点控制与配置
|
||||
8. [domain-api/tests/test_worker_control_service.py](/www/wwwroot/getDomain/domain-api/tests/test_worker_control_service.py)
|
||||
9. [domain-api/tests/test_settings_service.py](/www/wwwroot/getDomain/domain-api/tests/test_settings_service.py)
|
||||
10. [domain-api/tests/test_detect_api_routes.py](/www/wwwroot/getDomain/domain-api/tests/test_detect_api_routes.py)
|
||||
11. [domain-api/tests/test_ops_api_routes.py](/www/wwwroot/getDomain/domain-api/tests/test_ops_api_routes.py)
|
||||
|
||||
## 本轮输出要求
|
||||
|
||||
只输出这 3 类内容,避免烧额度:
|
||||
- `P0 / P1` 真实问题,带文件和行号
|
||||
- 影响范围
|
||||
- 修复建议
|
||||
|
||||
不要在第一轮做这些:
|
||||
- 大篇架构说明
|
||||
- 文件逐段复述
|
||||
- UI 细节优化建议
|
||||
- 发布脚本和迁移功能深挖
|
||||
|
||||
## 第一轮完成标准
|
||||
|
||||
满足以下条件就可以结束第一轮,转第二轮:
|
||||
- 能回答“为什么页面显示会和现场不一致”
|
||||
- 能回答“为什么 sync 会把旧运行态覆盖成新页面口径”
|
||||
- 能回答“进程/线程配置、页面显示、节点实际执行三者有没有断层”
|
||||
- 能列出前 `10` 个最值得先修的 `P0/P1` 问题
|
||||
180
docs/当前已验证有效的线上参数与改动清单.md
Normal file
180
docs/当前已验证有效的线上参数与改动清单.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# 当前已验证有效的线上参数与改动清单
|
||||
|
||||
> 说明:这份文档保留作阶段留档。后续执行和观察,统一以 [当前线上最终Runbook.md](/www/wwwroot/getDomain/docs/当前线上最终Runbook.md) 为准。
|
||||
|
||||
最后更新:2026-04-25 17:30 左右
|
||||
适用节点:`mainland-controller-01`
|
||||
目标:给后续观察和继续优化留一个“当前已经验证有效”的固定基线,不再靠聊天记录回忆。
|
||||
|
||||
## 1. 当前线上基底
|
||||
|
||||
- 当前 `current` 指向:
|
||||
`/opt/domaincheck/releases/domaincheck_release_20260424_220158`
|
||||
- 当前核心服务状态:
|
||||
- `domaincheck-worker.service = active`
|
||||
- `domaincheck-sync-agent.service = active`
|
||||
- `domaincheck-api.service = active`
|
||||
|
||||
说明:
|
||||
- 这台机器现在不是只跑旧 release 原样代码,而是“`220158` 基底 + 多轮热补”。
|
||||
- 后续如果要正式固化,应该把当前热补内容重新打一版正式 release。
|
||||
|
||||
## 2. 当前已确认生效的远端环境参数
|
||||
|
||||
以下参数已经在运行中的 `detect_worker.py` 进程环境里确认过,不是只改了文件没重启:
|
||||
|
||||
### 单机性能/爱站相关
|
||||
|
||||
- `DOMAINCHECK_REGISTER_SINGLE_MACHINE_MODE=1`
|
||||
- `DOMAINCHECK_SINGLE_MACHINE_AIZHAN_DIRECT_FIRST=1`
|
||||
- `DOMAINCHECK_AIZHAN_REMOTE_DISCONNECT_DEGRADE=1`
|
||||
- `DOMAINCHECK_AIZHAN_EXTERNAL_FAST_DEGRADE=1`
|
||||
- `DOMAINCHECK_PROXY_STEP_MAX_ATTEMPTS_AIZHAN=2`
|
||||
- `DOMAINCHECK_PROXY_STEP_MAX_SECONDS_AIZHAN=10`
|
||||
- `DOMAINCHECK_AIZHAN_TIMEOUT_PROXY=1.8`
|
||||
- `DOMAINCHECK_AIZHAN_TIMEOUT_DIRECT=2.4`
|
||||
|
||||
### Wayback 相关
|
||||
|
||||
- `DOMAINCHECK_PROXY_STEP_MAX_ATTEMPTS_WAYBACK=2`
|
||||
- `DOMAINCHECK_PROXY_STEP_MAX_SECONDS_WAYBACK=8`
|
||||
- `WAYBACK_CDX_TIMEOUT=3`
|
||||
- `WAYBACK_SNAPSHOT_TIMEOUT=2`
|
||||
- `WAYBACK_RETRY_COUNT=1`
|
||||
- `WAYBACK_DOMAIN_CONCURRENCY=1`
|
||||
- `WAYBACK_MAX_RECORDS=2`
|
||||
- `WAYBACK_TRANSIENT_BACKOFF_SECONDS=0.5`
|
||||
|
||||
## 3. 当前已确认上线的代码改动方向
|
||||
|
||||
这些不是“计划中”,而是已经热补到 `mainland-controller-01` 并跑起来的:
|
||||
|
||||
### 调度/分发侧
|
||||
|
||||
- 预补货提前触发,不再等批次快空了才补。
|
||||
- 预补货时不让拿到锁的那个 worker 先独吞下一批任务。
|
||||
- `pipeline` 推进和主动 `pull_tasks` 做了共享锁,减少 60 个 worker 同时拆批次。
|
||||
- `session_replaced -> queued_before_start` 这条重复唤起链已经加护栏压住。
|
||||
- `claim / finalize / release` 这些本地 DB 重链做过多轮减重,分钟级长尾已经明显掉下来。
|
||||
|
||||
### 注册/站点检测侧
|
||||
|
||||
- 注册检测保留单机性能模式。
|
||||
- 百度、360、爱站都已经不再停留在过于激进的超时口径。
|
||||
- `爱站` 已经补到:
|
||||
- 单机模式下首轮可直连优先
|
||||
- `RemoteDisconnected` 可直接降级
|
||||
- 现在又进一步支持“外部依赖异常快速降级”,不再把整轮预算白白耗完
|
||||
|
||||
### Wayback 侧
|
||||
|
||||
- `wayback` 已经从“自己 backoff 把自己打死”收住。
|
||||
- 当前远端新版逻辑里:
|
||||
- `latest_cdx` transient 时,不再硬打额外的 `records_cdx`
|
||||
- backoff 已收短到 `0.5s`
|
||||
- 当前剩下主要是 `web.archive.org` 本身慢/拒绝连接
|
||||
|
||||
## 4. 这轮真正验证出来的效果
|
||||
|
||||
下面这些是已经实测到的,不是预估:
|
||||
|
||||
### 4.1 机器确实吃起来了
|
||||
|
||||
较早一轮稳定快照里,`mainland-controller-01` 已经出现:
|
||||
|
||||
- `60` 个节点全在线
|
||||
- `53` 个子 worker 的 `active_threads > 0`
|
||||
- `active_thread_count = 13531`
|
||||
|
||||
后续观察里,最近 2 分钟也长期能看到:
|
||||
|
||||
- `59` 个 fresh worker
|
||||
- 大约 `51 ~ 56` 个 worker 有真实线程数大于 `0`
|
||||
- 真实线程总和大约在 `3.8 万 ~ 4.2 万`
|
||||
|
||||
这说明当前不是“进程活着但没吃活”,而是确实在跑。
|
||||
|
||||
### 4.2 内存高位问题先被压下来了
|
||||
|
||||
滚动重启并替换旧 RSS 后,现场有过一轮明显回落:
|
||||
|
||||
- `Mem used ≈ 31Gi`
|
||||
- `available ≈ 93Gi`
|
||||
- `60` 个 worker 总 RSS 约 `23.9Gi`
|
||||
|
||||
说明“旧 RSS 不退”这层已经不是最早那种危险状态。
|
||||
|
||||
### 4.3 爱站与 Wayback 的尾部外部链,已经从“卡住不产出”变成“持续产出”
|
||||
|
||||
观察窗:`2026-04-25 17:17:18` 到 `17:29:23`
|
||||
|
||||
- `completed_total: 50786 -> 51298`,净增 `512`
|
||||
- `aizhan_completed: 7718 -> 7936`,净增 `218`
|
||||
- `wayback_completed: 3068 -> 3362`,净增 `294`
|
||||
- 这段窗口里:
|
||||
- `aizhan_failed = 0`
|
||||
- `wayback_failed = 0`
|
||||
|
||||
这个结论很重要:
|
||||
|
||||
- 现在已经不是“压住 failed,但 completed 不动”
|
||||
- 而是“failed 压住了,同时 completed 也在持续增长”
|
||||
|
||||
### 4.4 爱站快速降级这刀确实有作用
|
||||
|
||||
更早一段观察里,`爱站 failed` 还是会堆。
|
||||
在把 `DOMAINCHECK_AIZHAN_EXTERNAL_FAST_DEGRADE=1` 灰到远端后,后面的观察窗里:
|
||||
|
||||
- `aizhan_failed` 被压到 `0`
|
||||
- `aizhan_completed` 持续增长
|
||||
|
||||
这说明当前主链里,对爱站这类外部依赖异常,“快速降级继续”是有效的。
|
||||
|
||||
## 5. 当前怎么理解这些数字
|
||||
|
||||
当前最应该盯的不是:
|
||||
|
||||
- 单次 `claimed`
|
||||
- 单次 `pending`
|
||||
- 某一个瞬间的 `running`
|
||||
|
||||
因为这是 `domain_pipeline`,前一步跑完会继续生成下一步,数字天然会波动。
|
||||
|
||||
当前更应该盯的是:
|
||||
|
||||
1. `completed_total` 是否持续增长
|
||||
2. `aizhan_completed / wayback_completed` 是否持续增长
|
||||
3. `aizhan_failed / wayback_failed` 是否继续维持低位
|
||||
|
||||
如果这三组数继续保持当前趋势,就说明这套配置是对的。
|
||||
|
||||
## 6. 当前不要再乱动的东西
|
||||
|
||||
在下一轮更长观察结束前,建议先不要再继续频繁改:
|
||||
|
||||
- worker 进程数
|
||||
- 每进程线程上限
|
||||
- claim / backlog 批量参数
|
||||
- wayback / 爱站超时参数
|
||||
|
||||
原因很简单:
|
||||
现在已经进入“参数开始生效、completed 在涨”的阶段,再频繁动,会把已验证有效的窗口打碎。
|
||||
|
||||
## 7. 下一步建议
|
||||
|
||||
当前建议先停手观察,不再继续大改参数。
|
||||
|
||||
优先做两件事:
|
||||
|
||||
1. 继续观察更长窗口
|
||||
建议至少再看 `30 ~ 60` 分钟,确认:
|
||||
- `completed_total` 继续增长
|
||||
- `aizhan_completed / wayback_completed` 继续增长
|
||||
- `aizhan_failed / wayback_failed` 不重新抬头
|
||||
|
||||
2. 之后再做正式固化
|
||||
把当前这些热补过的代码和远端有效参数,整理进正式 release,避免后续机器重启或重新发版时丢失。
|
||||
|
||||
## 8. 当前一句话结论
|
||||
|
||||
**这轮已经验证到:当前 `mainland-controller-01` 上这套“单机性能模式 + 外部依赖快速降级继续”的组合是有效的,主链已经从“线程忙但不出结果”切到“线程忙,同时持续产出 completed”。**
|
||||
273
docs/当前线上最终Runbook.md
Normal file
273
docs/当前线上最终Runbook.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# 当前线上最终 Runbook
|
||||
|
||||
最后更新:2026-04-26 18:12 左右
|
||||
适用节点:`mainland-controller-01`
|
||||
|
||||
这份文档的目标很简单:
|
||||
后面不再靠聊天记录回忆,也不在多份文档里来回翻。
|
||||
只看这一份,就知道:
|
||||
|
||||
1. 当前线上到底跑在什么基线上
|
||||
2. 现在先看什么数
|
||||
3. 什么情况继续观察
|
||||
4. 什么情况才值得继续动刀
|
||||
|
||||
## 1. 当前结论
|
||||
|
||||
当前这套线上方案,已经从:
|
||||
|
||||
- 线程忙但不出结果
|
||||
|
||||
推进到了:
|
||||
|
||||
- 线程忙,同时持续产出 `completed`
|
||||
|
||||
所以现在的正确策略不是继续乱改参数,而是:
|
||||
|
||||
**先稳住,先观察,确认这套已经验证有效的配置能不能持续出结果。**
|
||||
|
||||
## 2. 当前线上基线
|
||||
|
||||
### 当前基底版本
|
||||
|
||||
- `current` 指向:
|
||||
`/opt/domaincheck/releases/domaincheck_release_20260424_220158`
|
||||
|
||||
说明:
|
||||
|
||||
- 当前不是纯旧 release 原样运行
|
||||
- 真实线上状态是:
|
||||
`220158 基底 + 多轮已热补代码 + 已生效 env`
|
||||
|
||||
### 当前服务状态
|
||||
|
||||
- `domaincheck-worker.service = active`
|
||||
- `domaincheck-sync-agent.service = active`
|
||||
- `domaincheck-api.service = active`
|
||||
|
||||
## 3. 当前已确认生效的关键参数
|
||||
|
||||
这些参数是**已经在运行进程环境里确认过**的,不是只改了文件。
|
||||
|
||||
### 单机性能与爱站相关
|
||||
|
||||
- `DOMAINCHECK_REGISTER_SINGLE_MACHINE_MODE=1`
|
||||
- `DOMAINCHECK_SINGLE_MACHINE_AIZHAN_DIRECT_FIRST=1`
|
||||
- `DOMAINCHECK_AIZHAN_REMOTE_DISCONNECT_DEGRADE=1`
|
||||
- `DOMAINCHECK_AIZHAN_EXTERNAL_FAST_DEGRADE=1`
|
||||
- `DOMAINCHECK_PROXY_STEP_MAX_ATTEMPTS_AIZHAN=2`
|
||||
- `DOMAINCHECK_PROXY_STEP_MAX_SECONDS_AIZHAN=10`
|
||||
- `DOMAINCHECK_AIZHAN_TIMEOUT_PROXY=1.8`
|
||||
- `DOMAINCHECK_AIZHAN_TIMEOUT_DIRECT=2.4`
|
||||
|
||||
### Wayback 相关
|
||||
|
||||
- `DOMAINCHECK_PROXY_STEP_MAX_ATTEMPTS_WAYBACK=2`
|
||||
- `DOMAINCHECK_PROXY_STEP_MAX_SECONDS_WAYBACK=8`
|
||||
- `WAYBACK_CDX_TIMEOUT=3`
|
||||
- `WAYBACK_SNAPSHOT_TIMEOUT=2`
|
||||
- `WAYBACK_RETRY_COUNT=1`
|
||||
- `WAYBACK_DOMAIN_CONCURRENCY=1`
|
||||
- `WAYBACK_MAX_RECORDS=2`
|
||||
- `WAYBACK_TRANSIENT_BACKOFF_SECONDS=0.5`
|
||||
|
||||
## 4. 当前已确认上线的代码方向
|
||||
|
||||
### 调度 / 分发侧
|
||||
|
||||
- 预补货提前触发
|
||||
- 预补货时不再让补货 worker 先独吞下一批
|
||||
- `pipeline` 推进和主动 `pull_tasks` 做了共享锁
|
||||
- `session_replaced -> queued_before_start` 这条重复唤起链已压住
|
||||
- `claim / finalize / release` 这些本地 DB 重链已经做过减重
|
||||
|
||||
### 外部步骤侧
|
||||
|
||||
- 注册检测保留单机性能模式
|
||||
- 百度、360、爱站都不再是早期那套过于激进的超时口径
|
||||
- `爱站` 当前已经具备:
|
||||
- 首轮可直连优先
|
||||
- `RemoteDisconnected` 可直接降级
|
||||
- 外部依赖异常可快速降级继续
|
||||
- `wayback` 当前已经具备:
|
||||
- `latest_cdx` transient 时不再硬打额外 `records_cdx`
|
||||
- backoff 已收短
|
||||
- 主要剩下 `web.archive.org` 本身慢/拒绝连接
|
||||
|
||||
## 5. 当前已经验证出来的效果
|
||||
|
||||
### 5.1 机器已经真正吃起来
|
||||
|
||||
已观察到:
|
||||
|
||||
- `60` 个节点全在线
|
||||
- 多次快照里 `51 ~ 56` 个 worker 有真实线程
|
||||
- 真实线程和长期在 `3.8 万 ~ 4.2 万`
|
||||
|
||||
所以当前不是“进程活着但没干活”,而是确实在跑。
|
||||
|
||||
### 5.2 内存高位问题先被压下来
|
||||
|
||||
滚动重启释放旧 RSS 后,现场出现过一轮明显回落:
|
||||
|
||||
- `Mem used ≈ 31Gi`
|
||||
- `available ≈ 93Gi`
|
||||
- `60` 个 worker 总 RSS ≈ `23.9Gi`
|
||||
|
||||
说明“旧 RSS 不退”这层已经先被压住。
|
||||
|
||||
### 5.3 当前真正最重要的验证结果
|
||||
|
||||
观察窗:`2026-04-25 17:17:18` 到 `17:29:23`
|
||||
|
||||
- `completed_total: 50786 -> 51298`,净增 `512`
|
||||
- `aizhan_completed: 7718 -> 7936`,净增 `218`
|
||||
- `wayback_completed: 3068 -> 3362`,净增 `294`
|
||||
- 这段窗口里:
|
||||
- `aizhan_failed = 0`
|
||||
- `wayback_failed = 0`
|
||||
|
||||
这说明:
|
||||
|
||||
- 现在已经不是“压住 failed,但 completed 不动”
|
||||
- 而是“failed 被压住,同时 completed 持续增长”
|
||||
|
||||
## 6. 当前最该看的数
|
||||
|
||||
后面观察时,优先级固定按这个顺序:
|
||||
|
||||
1. `completed_total`
|
||||
2. `aizhan_completed`
|
||||
3. `wayback_completed`
|
||||
4. `aizhan_failed`
|
||||
5. `wayback_failed`
|
||||
6. `running / claimed / pending`
|
||||
|
||||
顺序不要反过来。
|
||||
|
||||
原因:
|
||||
|
||||
- `claimed / pending` 在 `domain_pipeline` 下天然会波动
|
||||
- `completed` 才是最真实的产出
|
||||
|
||||
## 7. 当前正确的判断方法
|
||||
|
||||
### 7.1 什么叫“继续观察就行”
|
||||
|
||||
只要看到下面这种趋势,就先不要再改:
|
||||
|
||||
- `completed_total` 持续增长
|
||||
- `aizhan_completed` 持续增长
|
||||
- `wayback_completed` 持续增长
|
||||
- `aizhan_failed / wayback_failed` 维持低位或归零
|
||||
|
||||
这说明:
|
||||
|
||||
- 当前主链是通的
|
||||
- 当前配置方向是对的
|
||||
- 现在最应该做的是稳住,不是继续乱调
|
||||
|
||||
### 7.2 什么叫“又卡住了”
|
||||
|
||||
只有出现下面这些情况,才值得继续下刀:
|
||||
|
||||
#### 情况一
|
||||
|
||||
`completed_total` 在 `30 ~ 60` 分钟窗口里基本不动
|
||||
|
||||
说明:
|
||||
|
||||
- 虽然线程在跑
|
||||
- 但结果没有真正落地
|
||||
|
||||
#### 情况二
|
||||
|
||||
`aizhan_failed` 或 `wayback_failed` 又明显抬头
|
||||
|
||||
说明:
|
||||
|
||||
- 当前“快速降级继续”的策略还不够稳
|
||||
|
||||
#### 情况三
|
||||
|
||||
`running` 长时间很高,但 `aizhan_completed / wayback_completed` 不再增长
|
||||
|
||||
说明:
|
||||
|
||||
- 新的主瓶颈又出现了
|
||||
|
||||
## 8. 当前建议观察窗口
|
||||
|
||||
建议至少继续看 `30 ~ 60` 分钟。
|
||||
|
||||
正确做法:
|
||||
|
||||
1. 记录一组起始值
|
||||
2. 每隔 `10 ~ 15` 分钟看一次
|
||||
3. 至少看 `3 ~ 4` 个点
|
||||
|
||||
不要只看一两个瞬间。
|
||||
|
||||
## 9. 当前先不要再碰的东西
|
||||
|
||||
在这轮观察结束前,先不要继续改:
|
||||
|
||||
- worker 进程数
|
||||
- 每进程线程数
|
||||
- claim 批量
|
||||
- backlog 批量
|
||||
- 爱站超时
|
||||
- wayback 超时
|
||||
- 其他步骤的重试窗口
|
||||
|
||||
原因很简单:
|
||||
|
||||
- 现在已经进入“开始稳定产出”的阶段
|
||||
- 再频繁改参数,只会把已经验证有效的窗口打碎
|
||||
|
||||
## 10. 当前一句话执行原则
|
||||
|
||||
**先稳住,先看 `completed` 能不能持续增长;只要结果还在持续出来,就先不要再乱改。**
|
||||
|
||||
## 11. `job 876` 尾项释放的当前判断
|
||||
|
||||
观察时间:`2026-04-26 18:12` 左右
|
||||
|
||||
当前不是“又卡死了”,而是:
|
||||
|
||||
- `idx_detect_job_items_release_node_job` 还没转成 `valid=1`
|
||||
- 但它已经稳定进入 `index validation: scanning table`
|
||||
- 最新验证进度已经到 `229991 / 6197384`
|
||||
|
||||
`codex-job876-tail-watch.service` 这条后台链当前是活的,而且在连续记进度:
|
||||
|
||||
- `18:09:51 -> 126725`
|
||||
- `18:10:52 -> 169564`
|
||||
- `18:11:52 -> 210067`
|
||||
- `18:12:22 -> 227856`
|
||||
|
||||
同时现场另外两组状态也正常:
|
||||
|
||||
- `job 876 = running`
|
||||
- worker 已恢复到:
|
||||
- `base=active`
|
||||
- `templated=199`
|
||||
- `node_agent=active`
|
||||
|
||||
这次现场更准确的判断应该是:
|
||||
|
||||
- 已经从“卡住”切成“后台验证扫描中”
|
||||
- 当前最合理的动作不是再人工乱动
|
||||
- 应该继续让索引自己扫完
|
||||
|
||||
一旦 `idx_detect_job_items_release_node_job` 转成 `valid=1`,`codex-job876-tail-watch.service` 就会自动继续释放 `876` 的尾项。
|
||||
|
||||
## 12. 如果后面还要继续优化,下一刀顺序
|
||||
|
||||
只有在更长观察窗口里确认又卡住时,才按这个顺序继续:
|
||||
|
||||
1. 先看 `completed_total` 为什么不涨
|
||||
2. 再看 `aizhan_completed / wayback_completed` 哪个先停
|
||||
3. 再决定是继续打外部链,还是回头查回写 / 聚合语义
|
||||
|
||||
不要一上来就回去改线程、claim、并发。
|
||||
149
docs/当前线上运维执行清单.md
Normal file
149
docs/当前线上运维执行清单.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# 当前线上运维执行清单
|
||||
|
||||
> 说明:这份文档保留作阶段执行稿。后续执行和观察,统一以 [当前线上最终Runbook.md](/www/wwwroot/getDomain/docs/当前线上最终Runbook.md) 为准。
|
||||
|
||||
最后更新:2026-04-25 17:30 左右
|
||||
适用节点:`mainland-controller-01`
|
||||
|
||||
## 1. 当前目标
|
||||
|
||||
当前先不要继续乱调参数。
|
||||
先确认这一套已经生效的配置,能不能稳定把结果持续跑出来。
|
||||
|
||||
现在最重要的不是:
|
||||
|
||||
- 再加线程
|
||||
- 再改 claim
|
||||
- 再改批量
|
||||
- 再改超时
|
||||
|
||||
现在最重要的是:
|
||||
|
||||
1. `completed_total` 能不能持续增长
|
||||
2. `aizhan_completed / wayback_completed` 能不能继续增长
|
||||
3. `aizhan_failed / wayback_failed` 会不会重新抬头
|
||||
|
||||
## 2. 当前已经验证有效的方向
|
||||
|
||||
这一轮已经确认有效的不是单点,而是整套思路:
|
||||
|
||||
- 单机性能模式保留
|
||||
- 任务已经能铺到更多 worker 上
|
||||
- `爱站` 支持更快降级继续
|
||||
- `wayback` 已经减少了额外的 `records_cdx` 压力
|
||||
- 当前主链已经从“线程忙但不出结果”变成“线程忙,同时持续产出 completed”
|
||||
|
||||
## 3. 当前观察时先看什么
|
||||
|
||||
优先看这 6 组数:
|
||||
|
||||
1. `completed_total`
|
||||
2. `aizhan_completed`
|
||||
3. `wayback_completed`
|
||||
4. `aizhan_failed`
|
||||
5. `wayback_failed`
|
||||
6. `running / claimed / pending`
|
||||
|
||||
判断顺序不要乱:
|
||||
|
||||
1. 先看 `completed_total` 有没有涨
|
||||
2. 再看 `aizhan_completed / wayback_completed` 有没有涨
|
||||
3. 最后才看 `failed` 和 `pending`
|
||||
|
||||
原因:
|
||||
|
||||
- `claimed / pending` 在 `domain_pipeline` 下会波动,不能单独看
|
||||
- `completed` 才是最真实的产出
|
||||
|
||||
## 4. 当前正确的判断口径
|
||||
|
||||
### 说明一
|
||||
|
||||
如果看到:
|
||||
|
||||
- `running` 很高
|
||||
- `claimed / pending` 在波动
|
||||
- 但 `completed_total` 也在持续涨
|
||||
|
||||
这不是问题。
|
||||
这说明当前机器正在持续消化任务。
|
||||
|
||||
### 说明二
|
||||
|
||||
如果看到:
|
||||
|
||||
- `aizhan_failed = 0`
|
||||
- `wayback_failed = 0`
|
||||
- `aizhan_completed / wayback_completed` 继续涨
|
||||
|
||||
这说明现在这套“外部依赖快速降级继续”是对的。
|
||||
|
||||
### 说明三
|
||||
|
||||
如果看到:
|
||||
|
||||
- `running` 很高
|
||||
- 但 `completed_total` 长时间完全不涨
|
||||
|
||||
这才说明主链又卡住了,需要继续排。
|
||||
|
||||
## 5. 当前建议观察窗口
|
||||
|
||||
建议至少看 `30 ~ 60` 分钟,不要只看一两个瞬间。
|
||||
|
||||
推荐做法:
|
||||
|
||||
1. 先记一组起始值
|
||||
2. 每隔 `10 ~ 15` 分钟看一次
|
||||
3. 连看至少 `3 ~ 4` 个点
|
||||
|
||||
只看单点,很容易误判。
|
||||
|
||||
## 6. 什么情况说明继续观察就行
|
||||
|
||||
只要出现下面这种趋势,就先不要动参数:
|
||||
|
||||
- `completed_total` 持续增长
|
||||
- `aizhan_completed` 持续增长
|
||||
- `wayback_completed` 持续增长
|
||||
- `aizhan_failed / wayback_failed` 维持低位或归零
|
||||
|
||||
这说明当前主链是通的,应该先稳住。
|
||||
|
||||
## 7. 什么情况才需要继续下刀
|
||||
|
||||
只有出现下面这些情况,才值得继续改:
|
||||
|
||||
### 情况一
|
||||
|
||||
`completed_total` 在 `30 ~ 60` 分钟窗口里基本不动
|
||||
说明虽然线程在跑,但结果没有真正落地。
|
||||
|
||||
### 情况二
|
||||
|
||||
`aizhan_failed` 或 `wayback_failed` 又明显抬头
|
||||
说明当前“快速降级继续”还不够稳。
|
||||
|
||||
### 情况三
|
||||
|
||||
`running` 长时间很高,但 `aizhan_completed / wayback_completed` 不再增长
|
||||
说明新的主瓶颈又出现了。
|
||||
|
||||
## 8. 当前不要再碰的东西
|
||||
|
||||
在这轮观察结束前,先不要继续改:
|
||||
|
||||
- worker 进程数
|
||||
- 每进程线程数
|
||||
- claim 批量
|
||||
- backlog 批量
|
||||
- wayback 参数
|
||||
- 爱站参数
|
||||
|
||||
原因很简单:
|
||||
|
||||
现在已经进到“开始稳定产出”的阶段,频繁动参数,只会把已验证有效的窗口打碎。
|
||||
|
||||
## 9. 当前一句话执行原则
|
||||
|
||||
**先稳住,先观察 completed 是否持续增长;只要结果还在持续出来,就先不要再乱改。**
|
||||
162
docs/新机器接手交接_20260427.md
Normal file
162
docs/新机器接手交接_20260427.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# 新机器接手交接
|
||||
|
||||
## 1. 目标
|
||||
|
||||
这次不是继续在当前机器上排障,而是:
|
||||
|
||||
- 把当前代码整理后提交到 Git
|
||||
- 在新服务器上重新部署验证
|
||||
- 让新的 Codex 接手继续推进
|
||||
|
||||
当前最重要的未完成主线只有一条:
|
||||
|
||||
- `domain-api/app/services/sync_push_service.py` 中 `_load_pushable_projections()` 的修复,需要在远端稳定部署后验证:
|
||||
- `detect_result_projection` push 是否恢复
|
||||
- `detect_result_ingest` 是否出现
|
||||
|
||||
## 2. 当前代码结论
|
||||
|
||||
已经确认并完成的代码侧修复:
|
||||
|
||||
- `domain-api/app/services/sync_push_service.py`
|
||||
- 修复 `_load_pushable_projections()` 选择逻辑
|
||||
- 旧问题:最新 `detect_result_projection` 明明存在且没有 push attempt,但候选集为空
|
||||
- 现修复:候选改为优先按最新 projection 选择
|
||||
- `domain-api/tests/test_sync_push_service.py`
|
||||
- 已补回归测试
|
||||
|
||||
本地验证已完成:
|
||||
|
||||
- `py_compile` 通过
|
||||
- `python -m unittest tests.test_sync_push_service` 通过
|
||||
|
||||
## 3. 当前卡点
|
||||
|
||||
不是代码不清楚,而是当前远端 SSH 不稳定:
|
||||
|
||||
- `121.204.244.188:22` TCP 可连接
|
||||
- 但 SSH banner 经常超时
|
||||
- Paramiko 常见报错:
|
||||
- `SSHException('No existing session')`
|
||||
- `Error reading SSH protocol banner`
|
||||
|
||||
因此当前没有拿到“远端已发布并生效”的硬结果。
|
||||
|
||||
## 4. 新机器接手后的首要动作
|
||||
|
||||
新机器接手后,先不要扩散排查面,只做这一个最小动作:
|
||||
|
||||
1. 发布 `domain-api/app/services/sync_push_service.py`
|
||||
2. 重启 `domaincheck-sync-agent.service`
|
||||
3. 只验证两项:
|
||||
- `detect_result_projection` push 是否恢复
|
||||
- `detect_result_ingest` 是否出现
|
||||
|
||||
## 5. 关键背景
|
||||
|
||||
项目根目录:
|
||||
|
||||
- `/www/wwwroot/getDomain`
|
||||
|
||||
主要子目录:
|
||||
|
||||
- `domain-api/`
|
||||
- `domain-web/`
|
||||
- `domainCheck/`
|
||||
- `docs/`
|
||||
|
||||
当前远端主机:
|
||||
|
||||
- `mainland-controller-01`
|
||||
- `121.204.244.188`
|
||||
|
||||
已确认的远端运行时 region 配置:
|
||||
|
||||
- `NODE_REGION=mainland`
|
||||
- `SYNC_SOURCE_REGION=mainland`
|
||||
- `SYNC_TARGET_REGION=overseas`
|
||||
|
||||
已确认的数据事实:
|
||||
|
||||
- mainland 本地已经生成了 `detect_result_projection`
|
||||
- surrogate job 例如:
|
||||
- `job_id=909`
|
||||
- `job_code=sync-overseas-28618`
|
||||
- worker 事件已写入 mainland 本地库
|
||||
- 真正未打通的是 `detect_result_projection` 的 push 选择阶段
|
||||
|
||||
## 6. 建议提交范围
|
||||
|
||||
建议优先提交真正的代码改动,不要把运行产物一起带上。
|
||||
|
||||
建议提交:
|
||||
|
||||
- `domain-api/`
|
||||
- `domain-web/`
|
||||
- `domainCheck/`
|
||||
- `tools/`
|
||||
- 需要保留的文档 `.md`
|
||||
|
||||
建议重点确认本次必须包含:
|
||||
|
||||
- `domain-api/app/services/sync_push_service.py`
|
||||
- `domain-api/tests/test_sync_push_service.py`
|
||||
|
||||
## 7. 明确不要提交的内容
|
||||
|
||||
以下属于运行产物、临时文件或本地探针,不建议提交:
|
||||
|
||||
- `docs/ops_center_runtime/night_runs/step_mix_*/`
|
||||
- `docs/ops_center_runtime/chinaz_gray_runs/`
|
||||
- `docs/_tmp_regression/`
|
||||
- `.codex-release-probe.txt`
|
||||
- `*.bak_*`
|
||||
- `*.log`
|
||||
- `*.pid`
|
||||
|
||||
当前工作区里特别要排除的项目:
|
||||
|
||||
- `domainCheck/app/utils/database.py.bak_20260426_220818_active_job_cache_tune`
|
||||
- `domainCheck/detect_worker.py.bak_20260426_220818_active_job_cache_tune`
|
||||
- `docs/ops_center_runtime/night_runs/step_mix_20260426_051718_smoke_p200/`
|
||||
- `docs/ops_center_runtime/night_runs/step_mix_20260426_051754_smoke_p200/`
|
||||
- `docs/ops_center_runtime/night_runs/step_mix_20260426_052641_debug_stepmix/`
|
||||
- `docs/ops_center_runtime/night_runs/step_mix_20260426_053252_mainland_step_mix_p200_t800/`
|
||||
- `docs/ops_center_runtime/chinaz_gray_runs/`
|
||||
- `.codex-release-probe.txt`
|
||||
|
||||
## 8. 已跟踪但不建议把这次删除提交进去的文件
|
||||
|
||||
这些文件目前显示为已删除,但更像本地运行态/配置文件,不建议在这次“迁移到新服务器”的提交里带上删除:
|
||||
|
||||
- `domainCheck/app/thread_count.json`
|
||||
- `domainCheck/node_thread_counts.json`
|
||||
- `domainCheck/runtime/runtime_settings.json`
|
||||
- `domainCheck/runtime/sensitive_words.json`
|
||||
- `domainCheck/runtime_settings.json`
|
||||
- `domainCheck/thread_count.json`
|
||||
|
||||
处理建议:
|
||||
|
||||
- 如果这些删除不是你明确想做的配置收口,请在提交前恢复
|
||||
- 不要把“本地运行时删掉了某个 JSON”误当作产品代码改动提交
|
||||
|
||||
## 9. 提交前建议
|
||||
|
||||
提交前建议至少做这几步:
|
||||
|
||||
1. `git status --short`
|
||||
2. 把运行产物和备份文件排除掉
|
||||
3. 只保留代码、测试、必要文档
|
||||
4. 单独复查:
|
||||
- `sync_push_service.py`
|
||||
- `test_sync_push_service.py`
|
||||
- `.gitignore`
|
||||
- 本交接文档
|
||||
|
||||
## 10. 给新机器上的 Codex 的一句话
|
||||
|
||||
接手后不要重新发散排查 worker、projection 生成、事件落库链;这些已经基本收敛。优先完成 `sync_push_service.py` 的远端生效验证,只盯:
|
||||
|
||||
- `detect_result_projection` push
|
||||
- `detect_result_ingest`
|
||||
417
docs/测试优化分析.md
Normal file
417
docs/测试优化分析.md
Normal file
@@ -0,0 +1,417 @@
|
||||
# 测试优化分析
|
||||
|
||||
> 说明:这份文档保留作历史分析记录。当前线上执行基线与观察方法,统一以 [当前线上最终Runbook.md](/www/wwwroot/getDomain/docs/当前线上最终Runbook.md) 为准。
|
||||
|
||||
更新时间:`2026-04-24 14:00`
|
||||
|
||||
## 这份文档是干什么的
|
||||
|
||||
这份文档不是讲理想情况,而是把这次已经做过的单机压测结果,和当前现场“根本没真正跑起来”的现状,放在一起说清楚。
|
||||
|
||||
目的很直接:
|
||||
|
||||
- 先把已经验证过的参数结论留档
|
||||
- 再把现在为什么看起来线程上限很高、实际只跑了很少线程说清楚
|
||||
- 给后面继续优化的人一个明确顺序,别再一边主链没跑通,一边继续盲目加并发
|
||||
|
||||
## 一句话结论
|
||||
|
||||
早上那轮“只测一台大陆机器”的压测,已经得出过一个单机最优值:
|
||||
|
||||
- `mainland-controller-01` 单机跑时,当前最优参数是 `35 进程 / 900 线程`
|
||||
|
||||
但这不等于项目现在已经能按这个参数稳定跑。
|
||||
|
||||
按 `2026-04-24 13:22` 左右控制面看到的实时状态,这套链路目前更像是:
|
||||
|
||||
- 任务还挂着
|
||||
- 页面也还能显示“运行中”
|
||||
- 但真正参与执行的只有很少几个桶
|
||||
- 总体上属于“没有真正跑起来”
|
||||
|
||||
所以现在的主矛盾不是“继续把线程调大”,而是“先让主流程真的跑起来”。
|
||||
|
||||
## 这次单机压测是怎么测的
|
||||
|
||||
这轮压测不是全链路压测,而是一个故意收缩后的测试环境。
|
||||
|
||||
当时做了这几件事:
|
||||
|
||||
- 先停掉 `121.204.244.248`,也就是 `mainland-worker-01`
|
||||
- 只保留 `mainland-controller-01` 单机承担检测
|
||||
- 停掉 controller 上的 `domaincheck-sync-agent.service`
|
||||
- 不再继续额外增加新的 Redis 限制动作
|
||||
- 直接在 controller 本地数据库里看 60 秒窗口真实完成量和更新量
|
||||
|
||||
这么做的目的,不是模拟线上真实规模,而是先排除多机互相干扰,看单机能跑到什么水平。
|
||||
|
||||
## 单机压测结果
|
||||
|
||||
压测时间段大致是 `2026-04-24 05:14 - 05:28`。
|
||||
|
||||
当时 controller 本地 60 秒窗口结果如下:
|
||||
|
||||
| 参数 | 60 秒完成量 | 60 秒更新量 | Redis 连接数 | 内存已用 | 可用内存 | 实际活跃 worker |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| `35/900` | `4092` | `22267` | `751` | `73.6G` | `54.3G` | `35` |
|
||||
| `40/1000` | `1885` | `1544` | `793` | `75.1G` | `52.9G` | `40` |
|
||||
| `45/1100` | `388` | `11347` | `818` | `75.7G` | `52.3G` | `45` |
|
||||
| `50/1200` | `0` | `12118` | `823` | `75.9G` | `52.1G` | `45` |
|
||||
|
||||
## 压测结论
|
||||
|
||||
从这轮结果里,可以直接得出 4 个结论:
|
||||
|
||||
### 1. 单机最优值不是越大越好
|
||||
|
||||
当前这套链路下,`35/900` 明显优于后面的更大参数。
|
||||
|
||||
也就是说,继续加进程、加线程,并没有带来更高完成量,反而更差。
|
||||
|
||||
### 2. 当前单机稳定上限大约在 `45/1100`
|
||||
|
||||
`45/1100` 还能勉强活住。
|
||||
|
||||
但它已经不是“跑得更快”,只是“还能挂着不死”。
|
||||
|
||||
### 3. `50/1200` 已经没有意义
|
||||
|
||||
虽然当时把参数抬到了 `50/1200`,但最终实际只活成了 `45` 个 worker,而且完成量已经掉到 `0`。
|
||||
|
||||
这说明不是配置没写进去,而是链路已经先撞到别的瓶颈了。
|
||||
|
||||
### 4. 当时真正的瓶颈已经不是 Redis
|
||||
|
||||
从这轮压测看,Redis 连接数有上升,但没有先爆。
|
||||
|
||||
更像是外部检测链路本身先撑不住了,尤其是:
|
||||
|
||||
- 注册检测
|
||||
- 代理池质量
|
||||
- 会话切换抖动
|
||||
|
||||
## 为什么当时测出来 `35/900`,现在页面却只剩 `52` 线程
|
||||
|
||||
这就是最容易误判的地方。
|
||||
|
||||
早上压测结论成立的前提是:
|
||||
|
||||
- 只测 controller 单机
|
||||
- `mainland-worker-01` 被停掉
|
||||
- `sync-agent` 被停掉
|
||||
- 现场是专门为压测收缩过的
|
||||
|
||||
而现在你看到的实时状态,已经不是那个压测场景了。
|
||||
|
||||
按 `2026-04-24 13:22` 左右接口返回的状态,现在的现场是:
|
||||
|
||||
- `detect/job/active` 里的活动任务还是 `job_id=1`
|
||||
- 这条任务从 `2026-04-21 23:30:42` 就已经是 `running`
|
||||
- `raw_items_pending=9478`
|
||||
- `raw_items_running=1`
|
||||
- `raw_items_completed=4996`
|
||||
- `raw_items_failed=486`
|
||||
|
||||
同时,`runtime/status` 给出的聚合状态是:
|
||||
|
||||
- `参与服务器:4`
|
||||
- `参与进程:4`
|
||||
- `参与线程:52`
|
||||
- `运行中:52`
|
||||
- `线程上限:52 / 2701`
|
||||
|
||||
这几组数字合起来说明的不是“系统已经高效跑起来”,而是:
|
||||
|
||||
- 页面还能看到一些参与桶
|
||||
- 但真正持续工作的执行面很薄
|
||||
- 大量任务还躺在队列里,没有被健康地持续消化
|
||||
|
||||
## 当前为什么可以直接判断“根本跑不起来”
|
||||
|
||||
不是因为页面数字小,而是因为几条关键事实同时出现了:
|
||||
|
||||
### 1. 活动任务太老
|
||||
|
||||
当前活动任务还是 `2026-04-21` 开出来的老任务。
|
||||
|
||||
如果主链真的健康,它不应该拖这么久还挂在 `running`。
|
||||
|
||||
### 2. 待处理量还很大
|
||||
|
||||
当前还剩:
|
||||
|
||||
- `9478` 条原始 pending
|
||||
- `3779` 条 claimed
|
||||
- `1028` 条 running backlog
|
||||
|
||||
但真正展示出来的活跃线程只有 `52`。
|
||||
|
||||
这个比例说明队列不是空了,而是消化不动。
|
||||
|
||||
### 3. 当前节点自己根本不跑本机 worker
|
||||
|
||||
当前 `overseas-control-01` 的 `runtime/status` 里明确写着:
|
||||
|
||||
- `worker_online=false`
|
||||
- `worker_process_count=0`
|
||||
- `worker_runtime_message=inactive/dead`
|
||||
|
||||
也就是说,现在这个页面看到的“运行中”,本来就不是本机在跑,而是靠远端汇总。
|
||||
|
||||
### 4. 远端参与桶很少,而且口径不稳
|
||||
|
||||
现在控制面聚合出的参与节点只有:
|
||||
|
||||
- `mainland-worker-01`
|
||||
- `mainland-controller-01-k`
|
||||
- `mainland-controller-01-a`
|
||||
- `mainland-controller-01-s`
|
||||
|
||||
这和早上单机压测时的 `35` 个 worker,根本不是一个级别。
|
||||
|
||||
所以你现在看到“线程上限 2701”,不要被这个数字迷惑。
|
||||
|
||||
它只是汇总上限,不代表这些线程真的都在跑。
|
||||
|
||||
## 现在最像什么问题
|
||||
|
||||
如果用人话说,现在最像下面这种情况:
|
||||
|
||||
- 任务队列里还有很多活
|
||||
- 但是执行面只剩很薄一层还在动
|
||||
- 页面还能看到“运行中”,所以看起来像没完全死
|
||||
- 可真正吞吐已经低到接近“没跑起来”
|
||||
|
||||
所以这不是单纯的参数问题,而是主流程状态已经歪了。
|
||||
|
||||
## 当前最该先做的事
|
||||
|
||||
下一步优化顺序建议固定成这样:
|
||||
|
||||
### 第 1 步:先恢复“能持续跑”
|
||||
|
||||
先不要继续加进程、加线程。
|
||||
|
||||
先确认 4 件事:
|
||||
|
||||
- 当前到底是哪几个节点真的在跑
|
||||
- `mainland-worker-01` 是不是还应该继续停着
|
||||
- controller 上当前实际活着多少 worker
|
||||
- 老任务里这些 `claimed/running` 有没有大量卡死项
|
||||
|
||||
### 第 2 步:把老任务和会话问题理顺
|
||||
|
||||
现在这条 `2026-04-21` 的老任务已经拖太久了。
|
||||
|
||||
要优先确认:
|
||||
|
||||
- 是不是有很多旧 `session_replaced`
|
||||
- 是不是有大量任务项一直卡在 `claimed/running`
|
||||
- 是不是页面显示还在跑,但实际 worker 已经不工作了
|
||||
|
||||
### 第 3 步:确认代理链是不是主瓶颈
|
||||
|
||||
早上单机压测已经说明,Redis 不是先撞墙的那个点。
|
||||
|
||||
下一步更值得盯的是:
|
||||
|
||||
- `detect_register` 的真实完成率
|
||||
- 代理池是否经常空
|
||||
- RDAP 访问是否大量超时
|
||||
|
||||
### 第 4 步:只有主链恢复后,才重新做性能优化
|
||||
|
||||
## 13:48 补充结论
|
||||
|
||||
这轮又确认了一件非常关键的事:
|
||||
|
||||
- `mainland-worker-01` 不是“已经彻底消失”,而是“被标记为停用,但之前还在继续上报运行态”
|
||||
|
||||
后来实际做了两步处理:
|
||||
|
||||
- 先通过远端 `ops job` 让 `mainland-worker-01` 本机执行 `systemctl stop domaincheck-worker`
|
||||
- 再把控制面的状态汇总改成:只要节点在 `ops_managed_nodes` 里是 `is_enabled=false`,就不再算进在线 Worker、参与节点和活跃线程
|
||||
|
||||
处理完成后,控制面实时口径已经从“2 台参与节点 / 2 个检测进程 / 2 线程”收到了:
|
||||
|
||||
- `参与节点:1`
|
||||
- `参与进程:1`
|
||||
- `运行中:1`
|
||||
- 只剩 `mainland-controller-01`
|
||||
|
||||
这说明前面那种“明明已经准备单机测了,页面还一直把停用节点算进去”的问题,确实是状态口径 bug,不是现场真的还有两台健康执行机一起在跑。
|
||||
|
||||
所以从现在开始再看单机测试结果时,要以这条新口径为准:
|
||||
|
||||
- `mainland-worker-01` 已停用,不再参与单机压测统计
|
||||
- 当前有效执行面只剩 `mainland-controller-01`
|
||||
|
||||
等主流程恢复成“真的能持续吃队列”之后,再拿 `35/900` 作为第一版基线。
|
||||
|
||||
到那时可以按下面顺序再调:
|
||||
|
||||
1. 先验证 `35/900` 在恢复后的现场还能不能稳定
|
||||
2. 如果稳定,再测 `40/1000`
|
||||
3. 只有吞吐确实提高了,才继续往上加
|
||||
|
||||
## 这份文档的最终结论
|
||||
|
||||
可以把这次结果浓缩成两句话:
|
||||
|
||||
第一句:
|
||||
|
||||
- 单机压测已经证明,当前代码和链路下,`mainland-controller-01` 的最佳参数是 `35 进程 / 900 线程`
|
||||
|
||||
第二句:
|
||||
|
||||
- 但当前线上真正的问题不是“参数不够大”,而是“主流程根本没有持续跑起来”,所以现在继续加线程没有意义
|
||||
|
||||
后面再优化时,应该先解决“为什么只剩 52 线程在动”,再谈如何把吞吐重新抬高。
|
||||
|
||||
## 2026-04-24 13:35 补充结论
|
||||
|
||||
这份文档写完以后,又继续往下排了一轮,现场有两个非常关键的新结论。
|
||||
|
||||
### 1. `52` 线程里有明显口径错配
|
||||
|
||||
后来继续核对后发现,页面里那组:
|
||||
|
||||
- `参与服务器:4`
|
||||
- `参与进程:4`
|
||||
- `参与线程:52`
|
||||
|
||||
并不是来自 `detect_job_items` 真表本身。
|
||||
|
||||
真实数据库里,`job_id=1` 其实只剩:
|
||||
|
||||
- `1` 条 `running`
|
||||
|
||||
而且这条记录最后更新时间还停在 `2026-04-22 15:00:56`,本质上已经是老僵死项。
|
||||
|
||||
真正把页面抬到 `52` 的,是一条口径 bug:
|
||||
|
||||
- 当前 active job 还是老任务 `detect-20260421232649-acfa3d`
|
||||
- 但控制面又拿到了别的 sync job 的 runtime overlay
|
||||
- 两套数据被硬合到了一起
|
||||
|
||||
简单说就是:
|
||||
|
||||
- 任务表是老 job
|
||||
- 线程数却借用了别的 job 的运行态
|
||||
|
||||
### 2. 这条口径 bug 已经修掉了
|
||||
|
||||
现在代码已经补成:
|
||||
|
||||
- 只有 runtime overlay 的 `job_code / job_id` 和当前 active job 对得上时,才允许覆盖 `queue_health`
|
||||
- 对不上时,宁可退回真实任务表,也不再把别的 job 的运行态硬套到当前页面上
|
||||
|
||||
修完并重启海外控制面 API 之后,实时口径已经从之前的 `52` 收回到了:
|
||||
|
||||
- `参与节点:2`
|
||||
- `参与进程:2`
|
||||
- `参与线程:2`
|
||||
|
||||
当前这 `2` 个真实信号分别来自:
|
||||
|
||||
- `mainland-controller-01` 那条老 `running`
|
||||
- `mainland-worker-01` 当前 heartbeat 上报的 `1` 条活跃线程
|
||||
|
||||
这说明一件事:
|
||||
|
||||
- 之前那组 `52` 的确主要是错口径,不是实际吞吐
|
||||
|
||||
## 目前还剩的真实问题
|
||||
|
||||
虽然 `52 -> 2` 这一步已经收准了,但项目还是没有真正恢复健康。
|
||||
|
||||
当前还剩 2 个真实问题:
|
||||
|
||||
### 1. `mainland-worker-01` 明明已停用,却还在持续推运行态
|
||||
|
||||
当前控制面日志里还能持续看到:
|
||||
|
||||
- `121.204.244.248` 往海外控制面打 `runtime/debug-ingest`
|
||||
- 同时也还在打 `ops/agent/pull`
|
||||
|
||||
这说明这台机器不是“旧残影”,而是还真的在线、还真的在报活。
|
||||
|
||||
所以“已停用”这件事,目前只是在托管配置层停了,但没有真正把它从 Agent / runtime 上报链里摘干净。
|
||||
|
||||
### 2. `job_id=1` 这条老任务本身也还没收口
|
||||
|
||||
当前老任务依然挂着:
|
||||
|
||||
- `job_id=1`
|
||||
- `job_code=detect-20260421232649-acfa3d`
|
||||
- `started_at=2026-04-21 23:30:42`
|
||||
|
||||
而真实任务表里,它现在已经不是“很多线程在跑”,而是:
|
||||
|
||||
- 大部分还在 `pending`
|
||||
- 只剩 1 条老 `running`
|
||||
|
||||
这说明这条老任务本身也需要后续专门处理,不能继续长期挂在 `running`。
|
||||
|
||||
## 现在更准确的下一步
|
||||
|
||||
到这里为止,下一步就更明确了:
|
||||
|
||||
1. 先把 `mainland-worker-01` 真的摘掉。
|
||||
2. 再处理 `job_id=1` 这条老任务的遗留 `running` 项。
|
||||
3. 等这两件事收完,再重新看当前真实执行面到底还有没有持续吞吐。
|
||||
|
||||
也就是说,现在已经不是“继续猜线程参数”的阶段,而是“先把错误执行面和老任务残留清掉”的阶段。
|
||||
|
||||
## 新增一版“单机性能模式”给注册检测
|
||||
|
||||
这次为了后面继续压单机吞吐,我已经在代码里补了一版只影响“注册状态检测”的性能模式。
|
||||
|
||||
它的目标不是改全局架构,而是先把当前最像瓶颈的那一段链缩短:
|
||||
|
||||
- 只改 `detect_register`
|
||||
- 不碰百度、360、站长、爱站、时光机这些步骤
|
||||
- 保留当前版的连接复用和失败闭环
|
||||
- 只把注册检测改得更像老版本那种“先尽快打出去,再说”
|
||||
|
||||
### 这版模式做了什么
|
||||
|
||||
打开后,注册检测会变成下面这个思路:
|
||||
|
||||
- 即使全局 `allow_direct=false`,注册检测这一步也允许直连
|
||||
- 默认先连续直连 `2` 次
|
||||
- 这两次之间不再等代理补货
|
||||
- 只有前面的直连没打通,后面才继续走代理兜底
|
||||
|
||||
简单说就是:
|
||||
|
||||
- 当前默认模式:代理优先,直连兜底
|
||||
- 单机性能模式:注册检测直连优先,代理兜底
|
||||
|
||||
### 怎么开
|
||||
|
||||
这版先做成环境变量开关:
|
||||
|
||||
- `DOMAINCHECK_REGISTER_SINGLE_MACHINE_MODE=1`
|
||||
- `DOMAINCHECK_REGISTER_DIRECT_STREAK_ATTEMPTS=2`
|
||||
|
||||
当前默认建议先用这组:
|
||||
|
||||
- `进程:35`
|
||||
- `线程:900`
|
||||
- `DOMAINCHECK_REGISTER_SINGLE_MACHINE_MODE=1`
|
||||
- `DOMAINCHECK_REGISTER_DIRECT_STREAK_ATTEMPTS=2`
|
||||
|
||||
如果后面继续试更激进一点,再考虑把直连连打次数从 `2` 提到 `3`,但不建议一上来就抬。
|
||||
|
||||
### 为什么不是直接回退老版本
|
||||
|
||||
老版本真正有参考价值的是“链短、切得快”,不是它的实现本身更先进。
|
||||
|
||||
所以这次没有回退这几样东西:
|
||||
|
||||
- 没回退到 `20s * 3` 的长超时
|
||||
- 没回退到“注册失败也继续往后跑”
|
||||
- 没丢掉当前的 `Session` 复用
|
||||
|
||||
换句话说,这次是“借老策略”,不是“退老实现”。
|
||||
405
docs/项目当前运行流程说明.md
Normal file
405
docs/项目当前运行流程说明.md
Normal file
@@ -0,0 +1,405 @@
|
||||
# 项目当前运行流程说明
|
||||
|
||||
> 说明:这份文档主要回答“项目现在怎么跑”。当前线上执行基线、观察顺序和是否继续调参,统一以 [当前线上最终Runbook.md](/www/wwwroot/getDomain/docs/当前线上最终Runbook.md) 为准。
|
||||
|
||||
更新时间:`2026-04-24`
|
||||
|
||||
## 这份文档是干什么的
|
||||
|
||||
这不是一份“理想设计稿”,而是按项目现在的真实跑法整理出来的说明。
|
||||
|
||||
目标只有一个:让人用人话看明白,这个项目现在到底怎么跑,任务从哪里来,谁在执行,结果又是怎么回来的。
|
||||
|
||||
## 先用一句话讲明白
|
||||
|
||||
这套系统现在不是“点一下开始,然后一台机器自己跑完”。
|
||||
|
||||
它现在的实际跑法是:
|
||||
|
||||
海外控制面先挑出要检测的域名,打成一批任务,然后把这批任务交给大陆节点;大陆节点把任务拉下来后,由 worker 一步一步去跑检测;跑出来的结果,再同步回海外控制面,最后由页面统一展示。
|
||||
|
||||
## 先认识 5 个角色
|
||||
|
||||
### 1. 海外控制面
|
||||
|
||||
可以把它理解成“总调度台”。
|
||||
|
||||
它主要负责:
|
||||
|
||||
- 创建检测任务
|
||||
- 给大陆节点派动作
|
||||
- 接收大陆回传的运行状态和检测结果
|
||||
- 在页面上展示当前进度
|
||||
|
||||
当前本机 `overseas-control-01` 就是这个角色。
|
||||
|
||||
它本机一般不直接跑检测。
|
||||
|
||||
### 2. 大陆控制节点
|
||||
|
||||
可以把它理解成“大陆现场调度员”。
|
||||
|
||||
它主要负责:
|
||||
|
||||
- 去海外把待检测批次拉下来
|
||||
- 启动大陆这边的 sync-agent、worker
|
||||
- 把大陆现场的运行情况回传出去
|
||||
|
||||
### 3. 大陆 worker 节点
|
||||
|
||||
这才是真正“干活”的机器。
|
||||
|
||||
它负责:
|
||||
|
||||
- 领取待执行任务
|
||||
- 开线程跑检测
|
||||
- 把每一步的结果写回本地
|
||||
|
||||
### 4. sync-agent
|
||||
|
||||
它就是“搬运工”。
|
||||
|
||||
负责在海外和大陆之间搬 3 类东西:
|
||||
|
||||
- 待检测任务批次
|
||||
- 当前运行状态
|
||||
- 检测结果
|
||||
|
||||
### 5. node-agent
|
||||
|
||||
它就是“远程执行员”。
|
||||
|
||||
它会在节点上定时来领控制命令,然后执行,比如:
|
||||
|
||||
- 启动 worker
|
||||
- 开始检测
|
||||
- 拉取任务
|
||||
- 重启服务
|
||||
|
||||
## 当前现场快照
|
||||
|
||||
下面这段,是按 `2026-04-24 01:44 - 01:45` 左右控制面看到的实时数据整理的。
|
||||
|
||||
- 当前控制面节点是 `overseas-control-01`
|
||||
- 角色是 `overseas / control`
|
||||
- 本机 API 在线
|
||||
- 本机 worker 不承担实际检测
|
||||
|
||||
当时控制面看到的活动任务是:
|
||||
|
||||
- `job_id = 208`
|
||||
- `job_code = sync-overseas-1430`
|
||||
- 状态是 `running`
|
||||
- 这一批一共 `5000` 个任务项
|
||||
- 其中 `4435` 个已经被领取
|
||||
- `575` 个正在执行
|
||||
|
||||
当时控制面汇总看到的执行规模大致是:
|
||||
|
||||
- 约 `28` 个参与节点
|
||||
- 约 `28` 个检测进程
|
||||
- 约 `575` 个活跃线程
|
||||
|
||||
当时积压里最大头还是“注册状态检测”:
|
||||
|
||||
- `detect_register` 待处理约 `8235`
|
||||
- 后续步骤待处理约 `1243`
|
||||
|
||||
同一时间段里,系统的 readiness 仍然提示:
|
||||
|
||||
- 大陆节点心跳并不稳定
|
||||
- 还有结果批次待推送
|
||||
|
||||
这说明了一件很关键的事:
|
||||
|
||||
不是完全没跑,而是“链路在跑,但跑得不稳”。所以现在的主矛盾,确实还是稳定性,不是单纯把线程数继续往上调。
|
||||
|
||||
## 整个项目现在是怎么跑的
|
||||
|
||||
下面按真实流程,一步一步讲。
|
||||
|
||||
### 第 1 步:海外控制面先挑出“需要再检测”的域名
|
||||
|
||||
简单理解就是:
|
||||
|
||||
- 还没检测过的
|
||||
- 之前检测失败过的
|
||||
- 或者状态需要重新确认的
|
||||
|
||||
这些域名会先被挑出来,形成一份“待处理名单”。
|
||||
|
||||
这时候只是“选名单”,还没有真正开始跑检测。
|
||||
|
||||
### 第 2 步:海外控制面创建一轮检测任务
|
||||
|
||||
系统会先创建一条“本轮任务”记录。
|
||||
|
||||
然后把这批域名拆成很多个“任务项”。
|
||||
|
||||
这里要特别注意:
|
||||
|
||||
它不是一次就给某个域名下发“整套检测”。
|
||||
|
||||
它做的是:
|
||||
|
||||
- 先判断这个域名下一步该做什么
|
||||
- 只给它安排“下一步”
|
||||
|
||||
所以这个系统现在跑的是“分步骤推进”,不是“单个域名一次性从头跑到尾”。
|
||||
|
||||
### 第 3 步:海外控制面自己不跑,而是把动作派到大陆
|
||||
|
||||
当你在页面上点“开始检测”后,海外控制面会去排队发送几类动作给大陆节点:
|
||||
|
||||
- 让大陆启动 sync-agent
|
||||
- 让大陆去拉取待检测批次
|
||||
- 让大陆启动 worker
|
||||
- 让大陆开始执行检测
|
||||
|
||||
这些动作不是直接 ssh 过去硬敲命令。
|
||||
|
||||
而是先进入远程动作队列,再由大陆节点上的 node-agent 定时来领。
|
||||
|
||||
所以你可以把它理解成:
|
||||
|
||||
海外控制面负责“发指令”,大陆节点负责“取指令并执行”。
|
||||
|
||||
### 第 4 步:大陆控制节点先把任务批次拉下来
|
||||
|
||||
大陆控制节点会去海外控制面拿一批待检测域名。
|
||||
|
||||
拿到以后,会做几件事:
|
||||
|
||||
- 把这批域名落到大陆本地库里
|
||||
- 在大陆本地创建一条对应的 job
|
||||
- 给每个域名生成“下一步要做什么”的任务项
|
||||
- 再回头告诉海外:这批任务我已经收到了
|
||||
|
||||
这个“确认收到”很重要。
|
||||
|
||||
因为如果不确认,海外会以为这批任务还没被接走,后面就可能重复下发。
|
||||
|
||||
另外,大陆控制节点不会无脑一直拉新任务。
|
||||
|
||||
如果它发现本地已经堆了很多待处理任务,它会先停一下,不再继续拉新批次,避免越堆越多。
|
||||
|
||||
### 第 5 步:worker 启动后,先做准备,不会立刻开跑
|
||||
|
||||
worker 真正开始检测前,会先做一轮准备动作。
|
||||
|
||||
大致包括:
|
||||
|
||||
- 重新读取最新配置
|
||||
- 重新读取线程数和进程数
|
||||
- 重新加载 cookies
|
||||
- 刷新代理池
|
||||
- 回收上次异常退出留下来的遗留任务
|
||||
|
||||
所以你看到“worker 已经启动”,并不等于“已经开始稳定出结果”。
|
||||
|
||||
它中间还有一个准备阶段。
|
||||
|
||||
### 第 6 步:worker 真正领的,是任务队列里的“下一步”
|
||||
|
||||
worker 现在不是直接扫整张域名表。
|
||||
|
||||
它主要是从任务队列里领取待执行任务。
|
||||
|
||||
领取后的状态大致可以这样理解:
|
||||
|
||||
- `pending`:还没被谁接手
|
||||
- `claimed`:已经被某个节点领走了
|
||||
- `running`:已经开始跑了
|
||||
- `completed / failed / blacklisted`:这一小步跑完了
|
||||
|
||||
也就是说,系统现在盯的不是“这个域名整体做完没”,而是“这个域名现在跑到哪一步了”。
|
||||
|
||||
### 第 7 步:一个域名不是一次跑完,而是一小步一小步推进
|
||||
|
||||
当前默认的主流程顺序,大致是:
|
||||
|
||||
1. 注册状态检测
|
||||
2. 百度 site 检测
|
||||
3. 360 site 检测
|
||||
4. 站长之家检测
|
||||
5. 爱站检测
|
||||
6. 时光机检测
|
||||
|
||||
有些来源的域名,会跳过注册状态这一步,直接从后面的步骤开始。
|
||||
|
||||
所以你不能把它理解成“所有域名一定都从第一步开始”。
|
||||
|
||||
更准确地说,是系统会先判断这个域名“现在最该补哪一步”。
|
||||
|
||||
### 第 8 步:流程顺序,和 worker 实际优先领什么,不完全一样
|
||||
|
||||
这个地方很容易误会,所以单独说一下。
|
||||
|
||||
流程顺序上,域名一般是先过前面的关,再去后面的关。
|
||||
|
||||
但 worker 实际领任务时,会优先照顾已经走到后面的域名。
|
||||
|
||||
为什么要这样做?
|
||||
|
||||
因为如果完全按最前面的步骤一直领,后面的域名会永远被堵住,怎么都跑不到尾部。
|
||||
|
||||
所以现在的真实策略更像是:
|
||||
|
||||
- 流程上按顺序推进
|
||||
- 调度上优先让已经走到后面的域名尽快跑完
|
||||
|
||||
这也是为什么你现在会看到“注册状态检测积压很大”,但后面的步骤也还在继续跑。
|
||||
|
||||
### 第 9 步:每一步跑完后,系统会决定下一步怎么走
|
||||
|
||||
某一步做完后,系统不会简单地只记一个“成功 / 失败”。
|
||||
|
||||
它还会决定后面怎么走。
|
||||
|
||||
大致有几种情况:
|
||||
|
||||
- 这一步通过了:给这个域名创建“下一步”的任务项
|
||||
- 这一步命中黑名单:后面的步骤就不再继续
|
||||
- 这一步属于外部站点异常、超时、代理问题:可能会重试,也可能降级,也可能转成人工复核
|
||||
- 这一步明确不通过:流程在这里终止
|
||||
|
||||
所以这个项目现在不是“跑完就完”,而是“每走完一步,再决定下一步”。
|
||||
|
||||
### 第 10 步:结果先写回大陆本地
|
||||
|
||||
worker 跑完某一步后,会先把结果写回大陆本地。
|
||||
|
||||
写回去的内容包括:
|
||||
|
||||
- 这一个任务项是什么结果
|
||||
- 这个域名当前是什么状态
|
||||
- 这一步的详细信息
|
||||
- 是否需要人工复核
|
||||
|
||||
所以大陆本地库,先是“第一落点”。
|
||||
|
||||
### 第 11 步:大陆再把结果和运行状态同步回海外
|
||||
|
||||
大陆这边不是只回传“最终结果”。
|
||||
|
||||
它还会把两类信息往海外送:
|
||||
|
||||
- 当前运行状态
|
||||
- 最近有哪些域名开始了、完成了、失败了、进黑名单了
|
||||
|
||||
然后海外控制面收到后,再去更新自己的展示和汇总。
|
||||
|
||||
这也是为什么页面上看到的数字,不是某一台机器的原始数字。
|
||||
|
||||
它其实是“控制面汇总后的结果”。
|
||||
|
||||
### 第 12 步:海外页面最后展示出来的,是一份汇总快照
|
||||
|
||||
所以现在页面上的数据,本质上是几部分拼起来的:
|
||||
|
||||
- 控制面自己知道的任务信息
|
||||
- 大陆回传的运行状态
|
||||
- 大陆回传的结果事件
|
||||
- 当前 job 的统计汇总
|
||||
|
||||
这就会带来一个现实情况:
|
||||
|
||||
如果大陆心跳断一下,或者结果同步晚一点,页面看起来就会突然不稳定,甚至和现场有一点时间差。
|
||||
|
||||
这不一定代表 worker 完全没跑。
|
||||
|
||||
很多时候,只是“页面依赖的回传链路断了一下”。
|
||||
|
||||
## 你可以把现在的项目理解成两条并行链
|
||||
|
||||
### 第一条:任务执行链
|
||||
|
||||
海外选域名 -> 建任务 -> 大陆拉批次 -> worker 领任务 -> 按步骤推进 -> 写结果
|
||||
|
||||
### 第二条:运行状态和结果同步链
|
||||
|
||||
大陆上报运行状态 -> 大陆回推结果事件 -> 海外接收并汇总 -> 页面刷新展示
|
||||
|
||||
这两条链只要有一条不稳,使用感受就会变差。
|
||||
|
||||
如果任务执行链慢,你会感觉“没速度”。
|
||||
|
||||
如果同步链不稳,你会感觉“页面不准、看不清到底跑没跑”。
|
||||
|
||||
## 为什么你会一直觉得“没有速度、没有效率”
|
||||
|
||||
因为现在影响体验的,不只是“worker 够不够快”。
|
||||
|
||||
这套系统至少要同时经过下面这些环节:
|
||||
|
||||
- 海外选任务
|
||||
- 海外派动作
|
||||
- 大陆领动作
|
||||
- 大陆拉批次
|
||||
- worker 领任务
|
||||
- 外部站点检测
|
||||
- 结果回传
|
||||
- 页面汇总展示
|
||||
|
||||
任何一段不稳,最后给人的感觉都会像是“整套系统没跑起来”。
|
||||
|
||||
所以从当前现场来看,先把主链路稳定跑顺,仍然比继续往上冲性能更重要。
|
||||
|
||||
## 如果你只想用最简单的方法判断现在卡在哪
|
||||
|
||||
可以按下面这个顺序看:
|
||||
|
||||
1. 先看有没有新的活动 job
|
||||
- 没有的话,说明卡在“任务还没真正建起来”
|
||||
|
||||
2. 再看大陆有没有把任务批次收下
|
||||
- 没收下的话,说明卡在“海外发过去了,但大陆没接住”
|
||||
|
||||
3. 再看 `claimed` 和 `running` 有没有开始增长
|
||||
- 不增长的话,说明 worker 没真正开始领任务
|
||||
|
||||
4. 再看 `completed / failed / blacklisted` 有没有开始变化
|
||||
- 长时间不变的话,说明任务虽然在跑,但结果没持续产出
|
||||
|
||||
5. 最后看海外页面有没有跟着更新
|
||||
- 大陆明明在跑,海外不更新,通常就是“结果同步链”有问题
|
||||
|
||||
## 最后只记住 4 句话就够了
|
||||
|
||||
1. 现在这套项目是“海外控制,大陆执行”,不是单机直跑。
|
||||
2. 一个域名不是一次跑完,而是按步骤一小步一小步推进。
|
||||
3. 页面看到的是汇总快照,不是某台机器的原始现场数字。
|
||||
4. 当前最大的矛盾仍然是链路稳定,不是单纯把性能参数继续调大。
|
||||
|
||||
继续看完了,当前是稳推进,不是又卡死。
|
||||
|
||||
现在现场是:
|
||||
- `idx_detect_job_items_release_node_job` 还没转 `valid=1`
|
||||
- 但已经稳定在 `index validation: scanning table`
|
||||
- 最新进度到:
|
||||
- `229991 / 6197384`
|
||||
- `watch` 这条后台链是活的,而且一直在连续记进度:
|
||||
- `18:09:51 -> 126725`
|
||||
- `18:10:52 -> 169564`
|
||||
- `18:11:52 -> 210067`
|
||||
- `18:12:22 -> 227856`
|
||||
|
||||
另外两点也正常:
|
||||
- `876` 现在还显示 `running`
|
||||
- worker 已经全恢复:
|
||||
- `base=active`
|
||||
- `templated=199`
|
||||
- `node_agent=active`
|
||||
|
||||
一句话说:
|
||||
**现在已经从“卡住”切成“后台验证扫描中”,而且进度在稳定往前走。**
|
||||
|
||||
下一步最合理的动作不是再人工乱动,而是继续让它扫;一旦索引转成 `valid=1`,`codex-job876-tail-watch.service` 就会自动接着去释放 `876` 的尾项。
|
||||
|
||||
|
||||
|
||||
发布 sync_push_service.py
|
||||
重启 domaincheck-sync-agent.service
|
||||
验证:
|
||||
detect_result_projection push 是否恢复
|
||||
detect_result_ingest 是否出现
|
||||
Reference in New Issue
Block a user