5.6 KiB
5.6 KiB
ProfileMax(CloakB + ipmart.io-US)并发常驻浏览器压测报告
- 日期:2026-10-09
- 服务器:OVH-FR
37.187.92.169(8 核 / 31GB 内存 / /dev/shm 16G / 同机还跑 mysql、clickhouse、plausible 等其它服务) - 链路:ProfileMax admin(127.0.0.1:5310)→ 节点 OVH-FR(node :3106,systemd 直跑,无 Docker)
- 测试身份:MCP 用户 phptits(id=2);Profile 全部归属该用户
- 方式:节点 API
POST /profiles/:id/lease(ttlMs=2h)→POST /profiles/:id/browser/start→ CDP/json/new+ WSPage.navigate开真实页面;每 20s 扫/proc按--user-data-dir聚合每 Profile 进程树 - 内存口径:PSS(smaps_rollup,去共享重复);RSS 会把共享页重复计数(报告注明)
配置
| 项 | 值 |
|---|---|
| 浏览器内核 | CloakB(cloak,146.0.7680.177.5) |
| 代理 | ipmart.io-US(socks5 gateway.ipmart.io:9999,用户名含 {sid} → 每指纹独立 US 住宅 sticky 出口) |
| 标签 | SERP |
| 模式 | 无头(用户中途指示全部改无头) |
| 保活 | BROWSER_IDLE_TIMEOUT=0(禁用 10 分钟空闲自动关闭)+ 每 Profile 2 小时 lease |
| Profile 池 | 10,002 个(sz-serp-*,CloakB + ipmart.io-US + SERP) |
结果总览
| 指标 | 测试1:3 标签(google/yahoo/x) | 测试2:1 标签(google) |
|---|---|---|
| 同时常驻浏览器上限 | 82 个 | 189 个 |
| 常驻时长 | ≥40 分钟(最老的) | ≥40 分钟(最老的) |
| 系统峰值 PSS | 25.0GB | 25.5GB |
| 内存最低可用(avail) | 542MB(耗尽) | 2793MB |
| swap 峰值 | 9.2GB 全满(耗尽) | 7.6GB(触发停止线) |
| load 峰值(8 核) | 118(kswapd 抢转,CPU 也耗尽) | 46 |
| 总进程/线程数峰值 | 1280 进程 | 1702 进程 |
| 每浏览器进程数(均值) | 15.1(重载页到 50+) | 9.0 |
| 每 Profile 内存(稳定期) | p50=125 / p90=906 / max=1560 MB;总量均值 ≈305MB | p50=152 / p90=158 / max=179 MB;总量均值 ≈129MB |
| 每 Profile swap | p50=20MB | p50=2MB |
| 每 Profile CPU(约 40 分钟常驻) | 均值 ≈164s | 均值 ≈46s |
| 每 Profile 磁盘(user-data) | p50=25MB / max=115MB | p50=10MB / max=115MB |
结论:当前服务器(31GB 内存,其余 3.7GB 被 mysql/clickhouse/系统占用)
- 3 标签(轻量页)可常驻 约 80 个 Profile;3 标签里出现 yahoo/x 重页时重载 Profile 会拖到 1.5GB/个,是方差的主因。
- 1 标签(google)可常驻 约 190 个 Profile(停止在 swap 7.2GB 保守线,真实极限约 200±10)。
- 内存是第一瓶颈,PSS 是衡量口径;3 标签场景 CPU(kswapd + 软渲染)会成为第二瓶颈。
每轮细节
测试1(3 标签)
- 发射阶段:并发 4,fd 修复后从 58 → 82 一路推进;
MemAvailable<1.5GB+ swap 满后页面加载/启动开始超时与抖动(load 118),停止发射。 - 残留 82 个全部驻留至数据采集完成(带 OOM 保护策略:浏览器主进程 oom_score_adj=200,其它服务进程=-600,整个压测期间 mysqld/clickhouse/PG 等零损伤)。
- 重载 Profile(x.com/yahoo 富页)实测会把进程树拉到 50+ 进程 / 1.5GB PSS。
测试2(1 标签)
- 清场回收后重跑同一 10002 池;发射 25 分钟到 189 个,唯一失败 1 次;swap 7458MB ≥ 7200MB 触发保守停止(avail 仍有 3.3GB,真实极限略高)。
- 单标签 google 的内存分布极稳(129MB 均值,极差 179)——google 轻页没有长尾。
过程中修复的 Docker/系统/产品问题
fs.file-max=65535系统级文件句柄上限——58 个浏览器即吃满(65216/65535),新 chrome 启动静默失败 → 启动超时。已放宽:fs.file-max=2097152(已写入 /etc/sysctl.conf)。- inotify 额度:max_user_instances 128→1024、max_user_watches 261756→524288(chrome 每 Profile 多个 watcher,128 实例上限也会卡死启动)。
- swap 仅 1GB:追加 8G swapfile
/testswap(priority 10),现共 9GB,保留作为长期优化(防 OOM 误伤同机其它服务)。 - 10 分钟空闲自动关闭(节点
BROWSER_IDLE_TIMEOUT默认 600s):测试期间置 0 禁用,已恢复默认。 - 有头模式(浏览器经 VNC/WebDesk 跑在每 Profile Xvfb 上,llvmpipe 软渲染)在批量场景会瞬间把 8 核打满(load 96),批量常驻必须用无头;webdesk 二进制与 x11vnc 测试期间暂移、已恢复。
- 产品坑(记录进记忆):节点有「UI 误关自动复活」(SIGKILL 杀浏览器会被复活,重启风暴);停浏览器必须走 API 显式 stop(closing 路径)。
browser/start返回的processId是包装进程(拉起 chrome 后退出),不能当存活判据;存活判据应按--user-data-dir进程树聚合。响应体统一{success,data}包装。 - admin
DELETE /api/profiles/:id只删库行、不清理节点侧 Profile 数据(节点清理只在转移链路触发)——压测清理需要另对节点调DELETE /profiles/:id?force=true(本次已处理)。
清理与恢复
- 测试 Profile:admin 侧 10,002 个全部删除;节点侧已启动过的 190 个数据目录全部强删(
force=true);节点现存 139 个目录均为合法 Profile(未动)。 - 配置:webdesk 二进制、x11vnc、
BROWSER_IDLE_TIMEOUT、全部恢复;fs.file-max/inotify/8G swapfile 保留(系统优化项)。 - 终态:节点在线(0 running)、admin 正常、内存回收(avail 29GB)、swap 余量 6.2GB。
复现物
- 服务器
/root/serpmax-stress/:create-profiles.ts / run-stress.ts / sampler.ts / stop-browsers.ts / report.ts / cleanup-profiles.ts / node-wipe-stress.ts - 数据:
data/test{1,2}-summary.json|md、data/test1-stats-final.jsonl(154 轮)、data/test2-stats.jsonl(117 轮)、各轮 run 日志 - 本地:
/home/bigcode/data/dev/bun/SerpMax/stress/REPORT.md(本文件)+ 同套脚本与 summary JSON