Files
getDomain/docs/测试优化分析.md

14 KiB
Raw Permalink Blame History

测试优化分析

说明:这份文档保留作历史分析记录。当前线上执行基线与观察方法,统一以 当前线上最终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-01runtime/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 jobmainland-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 其实只剩:

  • 1running

而且这条记录最后更新时间还停在 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 复用

换句话说,这次是“借老策略”,不是“退老实现”。