156 lines
16 KiB
Markdown
156 lines
16 KiB
Markdown
# xLightpanda 温池切换 + Storage Hook 部署手册(v0.47.0 / xlp 0.10.0)
|
||
|
||
> 日期:2026-11-03/04。交付:xLightpanda 接管 SERP 浏览器温池 + Storage Hook Phase 1(tmpfs 路由 + 共享 ShaderCache)。
|
||
> 代码:SerpMax node v0.47.0(zcode/serpmax-node 已推送);xLightpanda upstream 提交 `4f69ccd2`(0.10.0 显式指纹导入)。
|
||
> **部署路径勘误(2026-11-04)**:三节点 systemd 服务 WorkingDirectory=/app,实际运行代码在 `/app/src`(bundle 含 /app/node_modules,勿动);
|
||
> `/opt/{serpmax,profilemax}/src` 是滞留副本。部署 = rsync src → 节点 `/app/src` + package.json → `/app` + 更新日期戳 `/app/version` → restart。
|
||
|
||
## 1. 交付物
|
||
|
||
| 产物 | 位置 | 说明 |
|
||
|---|---|---|
|
||
| lightpanda 二进制(ReleaseFast,glibc 2.36 目标) | `/opt/{serpmax,profilemax}/bin/lightpanda` | 222MB;xlp 0.10.0;**必须用 `-Dtarget=x86_64-linux-gnu.2.36` 构建**(节点 Debian 12 glibc 2.36,宿主 2.39 构建会缺 `GLIBC_2.38/__isoc23_strtoull`) |
|
||
| SerpMax node 源码 v0.47.0 | `/opt/{serpmax,profilemax}/src` + package.json | xlightpanda kind / SERP_BROWSER_KIND / storage.hook / /storage/hook 端点 |
|
||
|
||
## 2. 温池引擎切换(每节点)
|
||
|
||
```bash
|
||
# 1) 二进制与代码
|
||
rsync -az upstream/zig-out/bin/lightpanda NODE:/opt/serpmax/bin/lightpanda
|
||
rsync -az --delete node/src/ NODE:/opt/serpmax/src/ # 源码内含 node_modules 除外
|
||
rsync -az node/package.json NODE:/opt/serpmax/
|
||
|
||
# 2) node.env 追加(二进制路径必配;SERP_BROWSER_KIND 分两步灰度)
|
||
grep -q XLIGHTPANDA_BINARY_PATH /opt/serpmax/node.env || \
|
||
echo 'XLIGHTPANDA_BINARY_PATH=/opt/serpmax/bin/lightpanda' >> /opt/serpmax/node.env
|
||
# 灰度第二阶段才加:
|
||
echo 'SERP_BROWSER_KIND=xlightpanda' >> /opt/serpmax/node.env
|
||
|
||
# 3) 重启并验证
|
||
systemctl restart serpmax-node
|
||
curl -s localhost:3100/version # 版本号 0.47.0
|
||
tail -f /opt/serpmax/data/logs/* # 观察 browser.started_xlightpanda / serp.pool_warm
|
||
```
|
||
|
||
- **回滚**:node.env 删掉 `SERP_BROWSER_KIND`(或置空)→ `systemctl restart serpmax-node`,温池立即回到 Profile kind(veil/cloak)。Profile 元数据不动。
|
||
- 温池入池门槛/搜索逻辑(serp-pool.ts)零改动;媒体拦截 `page.route` 与页内 fetch 在 xLightpanda 上已实测(CDP Fetch domain / Runtime.evaluate)。
|
||
- xLightpanda 仅无头运行(无渲染引擎);kind=xlightpanda 的 Profile 请求有头(VNC/WebDesk)会显式报错。
|
||
|
||
## 3. Storage Hook Phase 1(每节点,默认关闭)
|
||
|
||
配置:`DATA_DIR/node-settings.json` 合并(注意保留既有键;HZ-DE-245 已有 httpCacheDir/profileDir):
|
||
|
||
```json
|
||
{
|
||
"httpCacheDir": "…(保留)",
|
||
"profileDir": "…(保留)",
|
||
"storageHook": {
|
||
"enabled": true,
|
||
"tmpfsRoot": "/run/serpmax",
|
||
"perProfileCacheSizeMb": 256,
|
||
"sharedShaderCache": true,
|
||
"sharedShaderSizeMb": 256
|
||
}
|
||
}
|
||
```
|
||
|
||
- 生效后 veil/cloak 浏览器启动前:Cache/Code Cache/GPUCache/Dawn/Media Cache → 每 Profile 独立 tmpfs(256MB 上限);ShaderCache/GrShaderCache → bind 到 `/run/serpmax/shared/shader` 共享 tmpfs。停机/崩溃/hardReset 自动 lazy umount。
|
||
- **验证**:`curl -s localhost:3100/storage/hook`(activeProfiles/mounts/recentErrors);浏览器启动后 `mount | grep <profileDir>`;`du` 确认 Cache 目录不再占磁盘;Cookies/IndexedDB 重启保留(路由清单永不含存储类目录)。
|
||
- **回滚**:node-settings 置 `"enabled": false` → 重启。挂载失败(无 root/CAP_SYS_ADMIN)自动降级直写磁盘并记 `storage.hook_no_root` 告警,不影响业务。
|
||
- xLightpanda 温池实例无此问题(无渲染无 shader cache;HTTP cache 为单 sqlite 文件),storage.hook 只对 veil/cloak 分支挂载。
|
||
|
||
## 4. 已验证结论(2026-11-03/04,本机)
|
||
|
||
1. **种子一致性**:6 seed(10000/42/123456/999999/573891/248166)veil-chromium vs xLightpanda 全字段对比,均只剩同 7 处引擎基底差异(canvas/webgl 像素、rects 布局基底、audio DSP),身份字段逐字段一致(xLightpanda docs/SEED_PARITY.md)。
|
||
2. **温池可行性**:google 首页入池门槛(搜索框)、登录门槛 evaluate、页内 fetch+DOMParser、route 媒体拦截、导航回退全部通过;fetch 拿到 enablejs 空壳时 results=0 → serp-pool 原有回退逻辑按设计工作。
|
||
3. **Cookie 桥**:注入真实形 Google 会话 cookie(SID/HSID/SSID/SAPISID/NID)导航后全部存活。注意:Google 会对请求中出现的**陌生名字** cookie 主动下发删除 Set-Cookie(fake 名必被清,系 Google 侧行为,真实 Chrome 同样)。
|
||
4. **Storage Hook**:unshare 用户命名空间实测 18/18 挂载(含带空格目录)、共享 shader 互通、卸载干净、tmpfs 易失语义、disabled 零动作。
|
||
5. **导入连贯性守卫**:cloak UA(151)误配 derivation=veil(内核 153)时启动即失败 `InconsistentUserAgentVersion`——node 侧转换器已按 `origin==="veil" && uaMajor===153` 门控。
|
||
|
||
## 5. 温池灰度现状与遗留问题(2026-11-04)
|
||
|
||
**当前舰队状态:OVH-ETH-33 已开 xLightpanda 灰度(0.10.5,`SERP_BROWSER_KIND=xlightpanda`);HZ-DE-245 / OVH-DEDI-KS5B 暂保持 veil/cloak 兜底。三节点 lightpanda 0.10.5 二进制已就位;Storage Hook 三节点全启用。**
|
||
|
||
### 已突破
|
||
- 引擎接入全链路可用:克隆启动、impersonate MITM 链、cookie 桥、入池门槛、平均 RSS 75MB(veil 同池 ~450MB)。
|
||
- Google 的 **captcha/sorry 硬门已突破**(0.10.2-0.10.4 头集修复:UA-CH 三件套含引号、navigation accept 全段、accept-encoding 值序)。
|
||
- **enablejs/critical-ch 软门已突破(0.10.5,2026-11-04)**:给 impersonate-proxy 加了受控转发头 dump(env 门控 `IMPERSONATE_HEADER_DUMP=<目录>`(+可选 `_FILTER=<url子串>),默认零开销;源码在 /home/bigcode/data/dev/impersonate-proxy,该仓库 deployed-but-uncommitted 状态保持),veil vs xlp 同 Profile 同 IP 同 MITM 抓包对比,锁定门因:
|
||
- **Accept-CH client hints 全套缺失**。Google 响应声明 accept-ch/critical-ch 后,Chromium 对同源后续请求自动回带全部高熵提示(arch/bitness/full-version(-list)/model/platform-version/wow64/form-factors/prefers-color-scheme/downlink/rtt/ect);xlp 一概不带,Google critical-ch-check 判客户端撒谎 → enablejs 门壳 → hop2 302 /sorry。
|
||
- 次要差异:accept-language 多了 `,en;q=0.8` 第三段(veil/Chromium 实测 `de-DE,de;q=0.9` 无英文兜底)。
|
||
- 修复:0.10.5 Client.noteAcceptCh/appendClientHints(Accept-CH 持久化+每跳回带,值取自指纹 ctx 高熵集合)+ accept-language 去兜底。
|
||
- 验证:ETH-33 xlp 灰度池 pagefetch `ok=true 9 结果 0.9~1.7s`(与 veil 同形);新鲜实例单测通过。
|
||
- **已知的非引擎限制**:同一实例被连续高频手打搜索(≥7 次)后会在 navigate 回退跳吃 /sorry——频率疲劳,veil 同样如此,非引擎门;温池轮换天然规避。
|
||
|
||
### 灰度操作
|
||
- 开:`node.env` 加 `SERP_BROWSER_KIND=xlightpanda` → `systemctl restart serpmax-node`。
|
||
- 关:删该行 → 重启,立即回 veil/cloak(Profile 元数据不动)。
|
||
- 二进制升级:`upstream/zig-out/bin/lightpanda`(ReleaseFast + `-Dtarget=x86_64-linux-gnu.2.36`)→ 节点 `/opt/{serpmax,profilemax}/bin/lightpanda`;先 `sudo pkill -f "lightpanda [s]erve"`(注意 pkill 模式勿自匹配 ssh 命令行,否则 ssh 会话被杀 exit 255)。
|
||
|
||
## 6. 后续(不在本轮)
|
||
|
||
- StorageFS FUSE/Rust/Pack(02_STORAGE_HOOK.md Phase 2+),另行立项。
|
||
- xLightpanda localStorage/IndexedDB 落盘(SERP 场景 cookie 足够)。
|
||
|
||
## 6.5 typed 搜索调查(2026-11-04 下午,node 0.49.0/0.49.1)
|
||
|
||
**用户判断(定稿):go-fetch 打 302/门壳标的 Profile,WebDesk 里 veil 手动输入搜索全畅通 ⇒ 只要 xLightpanda 能像真实浏览器一样打开 google.com 在输入框填词回车,搜索应当没问题;两处部署动作:①`/nodes` 编辑弹窗设置多了加 Tabs 分类;②温池搜索路径保证「粘真实浏览器」。受此推动做的实测链:**
|
||
|
||
1. **pagefetch 门壳不再直接采信(0.49.0,1475479)**:`~10k Profile 只绑 3 个上游 IP` 的密度下,pagefetch 类 XHR 拿 0 结果/sorry/verify 概率高,而真浏览器路径畅通 ⇒ 改为仅当 `results>0 且 !sorry&&!verify` 采信,其余一律回退 **fill 搜索词 + Enter** 导航路径(真实浏览器行为)。
|
||
2. **JS 引导就绪门(0.49.1,55eb63d)**——本地 xLightpanda 复现实锤:
|
||
- Google 主包(xjs)未初始化完成时填词提交 → **原生 form GET**(抓到 `biw=&bih=` 空、`ie=GB2312`、无 sxsrf)→ Google 判异常流量 **302 /sorry**(title "302 Moved" 半秒转sorry);
|
||
- 等就绪(`readyState=complete` + `gk 命名空间≥30/联想容器 .UUbT9/隐藏域 biw` 有值,约需 10-15s 本地)之后同样操作 → **自然结果**(带 sxsrf/sca_esv 富参数);
|
||
- 故 navigate 提交前等待就绪标记(上限 10s,日志 `serp.pool_boot_gate`),温页早已就绪因此实测 `ms≈1-2` 即通过,零延迟副作用。
|
||
3. **ETH-33 生产复测:typed 就绪后提交,入参富化正确(sei= 等),但 Google 仍 302→/sorry** —— 剩余根因嫌疑二选一:① 每上游 IP 的 trip 计数(池 64 ≈21/IP, Typed 探针集中于少数 Profile);② impersonate MITM 链对**导航型请求**的头序/TLS 会话特征与真 Chromium 型有残余差异(veilWebDesk 同代理畅通是对照组)。**待 MITM 详查** = `IMPERSONATE_HEADER_DUMP` 开窗抓 xlp 导航 vs 规范浏览器导航头序对比(xlp 0.10.5 已留工具)。
|
||
4. 部署注记:node 0.49.1 三节点 `/app/version=20261104.1300`(ETH/HZ/KS5B 全部 xlightpanda 温池态,版本戳一处更新)。
|
||
5. admin 1.81.0(144955f):`/nodes` 编辑节点弹窗改 **Tabs 三页(基本信息/存储与缓存/温池与守卫)**;Hook 与守卫面板改为各自「恢复默认」按钮(原「联动恢复默认」取消)。前端已构建,HZ-DE-245 侧 profilemax-admin 已重启生效。
|
||
|
||
**排查小径(可复用)**:在服务器上 spawn 一只不走 MITM 的 `lightpanda serve` + `/app/node_modules/playwright-core` 装载 typed 探针,可隔离 MITM 因素做二元定位;直连(无 proxy 无 MITM)typed 探针发现 Google 主包就绪但 Enter 提交**不触发导航**,生产池路径(有 MITM)却能正常提交——驱动/键事件传递在直连实例上的差异也收入待修(独立小问题,非 sorry 主因)。
|
||
|
||
### 6.6 typed 决胜局:生产 dump 对照(2026-11-04 下午二)(0.49.1→0.49.2)
|
||
|
||
**背景**:用户拿 `24447424 / 2305745 / 65368457` 三只被限 Profile 在 WebDesk(veil)手测**全畅通** ⇒ IP 无恙,差异收敛到 xlp 引擎/MITM 链。用 `impersonate-proxy-dbg`(IMP dump 工具)在生产抓上游可见头,拿到关键证据并各进一环:
|
||
|
||
1. **生产 dump 三连发(34221790)**:req0 pagefetch XHR(`sec-fetch-mode:cors`/`accept:*/*`,形正常);**req1 typed 导航 = `sec-fetch-site:none` + 无 Referer + 裸 q 提交**(真 Chrome 表单回车应为 `same-origin` + `Referer:https://www.google.com/` + sxsrf 富化);req2(sei= 重定向链,same-origin+referer 正确)。→ 引擎把「激活型提交」送出了地址栏/CDP 型导航特征,Google 判异常。
|
||
2. **本地直连 typed 对照(reprobe10/11)**:引导就绪后首轮与结果页二连 typed 均 **organic**(sxsrf/newwindow/sca_esv 富化,10 结果);本地 echo 自建表单提交分类 `same-origin+referer` 正确 ⇒ 引擎直连形态本身良好,问题在生产恢复页态 + MITM 链。
|
||
3. **0.49.1 进站门实测有效但不够**:boot 门标志(`readyState+gk/ac/biw`)温页 1-2ms 即过(免延迟),但提交后 Typed 每 0 结果 —— gate 抓的是页内引导而非请求指纹。
|
||
4. **0.49.2(55b594c)「typed 回家门」**:pagefetch 门壳回退时若温页是结果/sorry 页,先 `goto google 首页` 再输入(与用户「新开 google → 输入框填词」路径完全对齐),boot 门上限扩到 15s。部署三节点(版本戳 20261104.1240)。
|
||
5. **复测仍 0 结果** —— 回家门在位、提交链通,Google 依旧 302→/sorry:剩余根因收敛于 **impersonate MITM 链对 document 导航请求的 HTTP/2/TLS 帧特征(h2fp 的 SETTINGS/伪头序/TLS preset chrome 与 Chrome 146 不匹配)**。同一链路 pagefetch(XHR 类)如常 0.9~1.7s organic,而 document(GET)一击即中 —— Google 对 document GET 的 JS/一致性门更严。**待修专项:Chrome 146 帧级对齐 h2fp(与上述直连 typed 字同步联动验证)。**
|
||
|
||
пери压测余量与守卫机制不受影响;搜流量主体照旧 pagefetch 健康;typed 兜底环节在 h2fp 对齐完成前保持现状。
|
||
|
||
## 7. 极限压测 + 全节点温池化(2026-11-04,node 0.48.0 / admin 1.80.0)
|
||
|
||
**用户定稿:ETH-33 旧 veil 池架构经常死机(实测 10-24~11-03 五崩四次,11-03 xlp 灰度后稳定);测新架构极限,系统资源保留 20% 保证不死机;全部节点切温池,全部 SERP 请求走温池路径。**
|
||
|
||
### 7.1 节点资源守卫(node 0.48.0,git f50a13f)
|
||
- `src/core/system/resource.guard.ts`:可用内存(MemTotal-MemAvailable)< 20% 或 load1/核心数 > 80% ⇒ 拒绝**新预热**(SERP_POOL_FULL 语义,admin 补池 15s 重试自愈);池内 ready/busy 与进行中搜索不动。配置 `node-settings.json` 的 `resourceGuard` 键(admin /nodes 可视化编辑,1.80.0)+ `RESOURCE_GUARD_ENABLED=0` 逃生口;判定用 load1(load5 衰减太慢会压着守卫十几分钟)。失败读数不阻塞(降级语义)。
|
||
- /serp/pool 响应即带 guard 水位;metrics 新增 mem_free_pct / system_load_pct / serp_pool_guard_rejections_total;`resource.guard.test.ts` 5 用例(bun test 190 全过)。
|
||
- xLightpanda 端口扫描数可配 `XLIGHTPANDA_PORT_COUNT`(默认 64 → 压测时可放更深)。
|
||
|
||
### 7.2 ETH-33 极限压测数据(12 核 / 64G,守卫版压测)
|
||
| 档位 | 池态 | lightpanda 总 RSS(≈单实例) | 内存可用 | 稳态 load1 | 结论 |
|
||
|---|---|---|---|---|---|
|
||
| 64 | 64/64 ready | 6.1G(95MB) | 82-89% | ~0.2(闲) | 资源余量极大 |
|
||
| 96 | 96/96 ready | 8.6G(88MB) | 85.6% | ~0.2(闲) | 同上 |
|
||
| 128 | 128/128 ready | 11.7G(91MB) | 82% | ~0.04(闲) | 内存仍远未到保留线 |
|
||
|
||
- **机器资源极限远未到**:128 深池内存只占 18%,闲时 CPU≈0;负载尖峰(ll 12-19)全部来自共租任务(保活 veil 浏览器 churn、重启风暴),守卫在尖峰窗口正确拒绝增容、尖峰过后(分钟级)自动恢复补池——“保留 20% 保证不死机”机制实测有效。
|
||
- **真正的瓶颈是 Google 每 IP 会话配额**:ETH-33 全部 ~10k Profile 只绑 3 个上游代理 IP。池深 20(≈7 会话/IP)时搜索 0.9-1.7s 正常;128 深突发(43 会话/IP + 6 分钟 128 连发)后单实例首搜即 302→/sorry,5 分钟未恢复。**操作定值:ETH-33 池收在 64(≈21/IP)**;曾冲到 128 的会话密度待 IP 冷却后另行评估。
|
||
- 压测期间 admin 补池 15s×4/轮,自 0 填满 128 仅 ~7 分钟(重启风暴窗口守卫会自动压住几分钟后恢复)。
|
||
|
||
### 7.3 全节点温池化(2026-11-04 16:xx 前)
|
||
| 节点 | SERP_POOL_SIZE | admin override | 状态 |
|
||
|---|---|---|---|
|
||
| OVH-ETH-33 | 64 | 64 | xlightpanda,64/64 回填完成 |
|
||
| HZ-DE-245 | 50 | 50 | xlightpanda(原 veil 兜底),回填中 |
|
||
| OVH-DEDI-KS5B | 80 | 80 | xlightpanda(原 veil 兜底),回填中 |
|
||
- 服务名:ETH/HZ=serpmax-node(/opt/serpmax),KS5B=profilemax-node(/opt/profilemax);统一 WorkingDirectory=/app;三节点 /app/version=20261104.1300(/system/version 显示之)。
|
||
- admin serpConfig `fetchPerSec: 1→0`:令牌桶永不放行 go-fetch,**SERP 请求 100% 走浏览器温池**(go-fetch 代码保留;回滚 = 改回正数即可)。依据:错误请求集中于 go-fetch 直连路径,温池路径无此问题(用户 2026-11-04 定稿)。
|
||
- Storage Hook 三节点保持 enabled(合并写修复后 /system/dirs 保存不再覆盖 storageHook 块);资源守卫全部默认开启(20/20)。
|
||
- 回滚:节点删 node.env 的 SERP_BROWSER_KIND 行重启即回 veil/cloak 温池。
|
||
|
||
### 7.4 admin 1.80.0(git 07f696c)
|
||
- /api/nodes/:name/settings(中继节点 GET /system/dirs)+ PUT /api/nodes/:name 支持 storageHook/resourceGuard(undefined=不动/null=恢复默认/对象=合并下发)。
|
||
- /nodes 编辑弹窗新增「Storage Hook(缓存路由 tmpfs)」与「资源守卫(温池准入)」设置区,打开即回显节点现值;节点 /system/dirs 增加 GET,保存按顶层键合并(修复只改目录导致手配 storageHook 被抿掉的隐患)。前端已构建,profilemax-admin 已重启。
|
||
(注:守卫与 Hook 值均为节点侧即读即生效,保存无需重启。)
|