onesvm-browser-server/docs/plan-final-20260901.md
chii 983259836d chore: init workspace with onesvm-dev-md + casa-commander
docs: 联网搜索服务架构方案全套(plan-final/design-arch/选型决策/整合导览/MCP文档/部署预设/联调手册)
bench: 5 方案 + 代理 + 站点矩阵本机实测工程(无密钥)
部署目标:primary mgr1 先行测试(待批准后执行)
2026-09-01 15:19:52 +08:00

18 KiB
Raw Permalink Blame History

type status created step
arch active 2026-09-01 S5 / plan-20260901-01 / run-20260901-browser-arch

onesvm-browser-server 最终方案 v1(用户 review 版)

时间口径 Asia/Shanghai。本文整合:S1 调研(research/01–05)、S2 筛选(select.md)、 S3a 代理探活(proxy-probe.md)、S3b/S3c 本机 Docker 实测(bench/S3b-summary.md / S3c-summary.md,原始数据 bench/*/results.json)、 S4 架构设计全文(docs/design-arch-20260901.md,机制细节权威;冲突处以本文为准)。 本文所有性能数字均为 2026-09-01 本机实测(darwin arm64 / Docker Desktop 29.4.0),非纸面推算;外推处显式标注。 权威关系:本文为决策与结论权威;机制细节权威为 design-arch(冲突处以本文为准)。

flowchart LR
    C[智能体消费者<br/>Vlepontas / EAI / 注册主体] --> G[统一出口网关 ×N 无状态<br/>MCP 主 + HTTP 兜底 · X-Service-Token]
    G -->|overlay enqueue| S[scheduler 单副本<br/>SQLite WAL 队列 · ADMIT_MAX=60]
    S --> D{Dock 适配器}
    D --> A[A 无浏览器<br/>SearXNG-CN/Global · Trafilatura]
    D --> B[B 轻渲染<br/>Lightpanda]
    D --> H[C 保真按需槽<br/>chrome-headless-shell]
    D -.插拔预留.-> HD[(有头档·默认不部署)]
    B & H --> P[ProxyManager 单副本<br/>mihomo · vless 热池 · 合规路由]
    A -->|国内域| DI[国内直连]
    A -->|境外搜索| P
    G --> POL[合规拦截·策略包单源<br/>请求侧@网关 / 响应侧@worker模版层]

0. TL;DR

  1. 1GB 够开机、也够维持 Vlepontas 60 会话级 + EAI 日常使用——前提是三条纪律:60 = 队列深度而非浏览器并发;渲染槽 ≤5 且重页互斥;保真 Chrome 槽按需启动。详见 §2 与 §7-D1。
  2. 实测最痛的不是内存,是上游反爬:60 并发裸打 SearXNG,百度/搜狗全灭(CAPTCHA)、必应中国 60/60 扛住;国外方向数据中心 vless IP 下 Google/DDG/Brave 全灭、只有 Bing 出结果。两者都由「网关排队 + 每 host 限速 + 缓存」消化,不由加内存解决。
  3. 入选 5 套:国内 SearXNG-CN + Trafilatura-HTTP;国外 SearXNG-Global(带质量警示)+ Lightpanda + chrome-headless-shell。预留 Camoufox(强对抗,需住宅代理)。
  4. 架构零 Redis:SQLite WAL 队列 + 进程内快通道;网关无状态 ×N,scheduler/ProxyManager 单副本。
  5. 需你拍板 6 个决策点(§7),最关键的是 D1 内存档位 与 D2 国外搜索质量路线。

1. 任务 1:统一消费出口

设计全文:docs/design-arch-20260901.md §2。要点:

  • 注册/凭证:Consumer(注册主体:vlepontas、eai…)+ ApiKey(可吊销、带 scopes/rpm/日配额/月配额/并发会话数)+ QuotaLedger(预扣防超卖)。明文 key 只回传一次,库存 hash,hmac.compare_digest 比对。
  • 双形态同一内核:MCP Server 为主(POST /mcp,Streamable HTTP,无协议会话态)+ HTTP API 兜底(/v1/search /v1/read,/v1/extract 特权);同一 Auth → Policy → Queue → Engine 流水线,错误码两面对齐。
  • 认证头遵循组织 service-secret-protocol:静态 key 走 X-Service-Token: bs_<random>,🔴 禁 Authorization: Bearer 塞静态 secret;密钥 ${VAR:?required} fail-closed。
  • urlapi:HTTP 监听独立端口(提议 :8640,见 §7-D3;S4 原设计值 :8300 与 dev-swarm voc-analysis-dev 冲突,已改),反代前缀 /bs-api(对齐组织 /search-api 先例),strip 后转发。
  • 管理面(签发/吊销 key)仅 overlay 内网 + 独立 admin token,CLI + SQL 先行。

2. 任务 2:集群规格与无 Redis 排队(bench 校准后)

2.1 排队机制(零 Redis)

入队路径(跨文档统一定义):消费者 → gateway(无状态:认证/配额预扣/合规预检)→ overlay 内网 POST /enqueue → scheduler(SQLite 唯一写者)进程内 bounded queue 快通道 + 立即落 SQLite WAL → 落盘成功才经 gateway 向消费者 ACK 排队位。scheduler 不可达时 gateway 返回 503 + Retry-After(fail-closed,gateway 本地不落盘)。执行侧:scheduler 用 UPDATE…RETURNING 原子抢单派发 worker;租约 + reaper 收割 + 指数退避(attempts≤2,仅瞬时错误重试)+ 死信表。背压三层:ADMIT_MAX=60(running+queued 合计)→ 超限 503/429 + Retry-After 只拒新不杀旧。理由与机制细节:design-arch §4。

2.2 实测内存底账(2026-09-01 cgroup 口径)

组件 idle 单会话峰值 60 burst 峰值 建议 cgroup
searxng-cn 99 MB 122 MB 170 MB 192m
trafilatura-http 33 MB 35 MB 41 MB 64m
searxng-global 122 MB 150 MB 181 MB 192m
lightpanda 3.6 MB 251 MB(重 Shopify 页) 143 MB 320m
chrome-headless-shell 37 MB 394 MB(同页) 179 MB 400m
mihomo(代理数据面) 小(探活期运行平稳;RSS 未单独采样,估算·待部署后校准) — — 64m
gateway + scheduler(Go/Rust 单二进制+SQLite,估算·待首轮实现校准) — — — 96m 合计(64m+32m)

2.3 渐进档位表(实测校准版)

记账口径(P1-1 修订):「档标」= 常驻业务峰预算(实测 idle + burst 峰值推算 + 余量);各组件 cgroup limit 是防暴走天花板,允许超配(上限合计可超档标)——重页峰值由渲染互斥调度保证不同时发生,超限杀 worker 不杀网关。实测依据:§2.2 底账。

档 档标(常驻业务峰) 实测 idle / 业务峰推算 cgroup 天花板合计 组成 能力(实测/换算)
L0 起步 ~350MB ~350MB idle ≈178MB / 峰 ≈257MB 352m gateway×1(64m) + scheduler(32m) + searxng-cn(192m) + trafilatura(64m) 国内搜索+正文精读全开;搜索单发 p50 0.63s;读取 p50 0.06s
L1 标准 ~700MB ~700MB idle ≈350MB / 峰 ≈627MB 960m L0 + ProxyManager(32m) + mihomo(64m) + searxng-global(192m) + lightpanda(320m) 国外搜索(仅 Bing 可用,见 D2)+ 轻渲染 4 槽(实测 2.13 jobs/s)
L2 满配 1GB ≤1GB idle ≈380MB / 峰 ≈660MB 1024m 常驻;shell 按需 400m 非常驻,与 lightpanda 重页互斥 L1 + gateway×2(+64m) + shell 按需槽 +保真渲染 1 槽(实测 FIFO 60/60、74s 零拒绝)
L3 舒适 1.5GB(扩容提议,见 D1/§2.5) ~1.5GB —(推算) ~1536m L2 且 shell 常驻 400m + searxng-cn/global 各 ×2 + 余量 渲染槽 4+1 免互斥;搜索双副本冗余;见 §2.5 换算
L4 强对抗档(另议) 3–4GB + 住宅代理 — — + Camoufox ×2(150–300MB/实例) Amazon/Medium 级 WAF 目标(实测确认数据中心 IP 打不过)

节点布局:【2026-09-01 用户更正】目标环境为 primary 生产 Swarm(mgr1 .51 / mgr2 .52 / mgr3 .53),非 dev-swarm。测试期全部署于 mgr1 单节点;扩展期:mgr1 控制面(scheduler + ProxyManager + 本地卷 SQLite + gateway×1)、mgr2 国内组+轻渲染(searxng-cn + trafilatura + lightpanda)、mgr3 国外组+保真(searxng-global + shell 按需槽 + gateway×1)。有状态钉节点,网关可漂移。部署细节权威为 deploy-prod-preset-20260901.md。(原 dev-swarm .61/.62/.63 布局作废——1GB 内存约束与档位表不变。)

注(P6 F1):若适配器采用 scheduler 进程内形态(deploy 预设 D8),scheduler 由 32m 提额至 64m,L2 常驻天花板 1024m → 1056m(超配口径,档标不变)。

2.4 为什么 60 不是 60 个浏览器(实测证据)

  • chrome-headless-shell CONCURRENT=1:60 任务全部 FIFO 入队、顺序执行、0 拒绝、0 OOM,墙钟 74s。
  • lightpanda 4 槽:60/60 全过,28s。
  • searxng-cn 裸 60 并发:HTTP 全 200 但断言仅 4/60——瓶颈是百度/搜狗 CAPTCHA;必应中国 60/60、360 53/60。结论:网关把对上游并发钳在 4–8 + 每 host 最小间隔 + 短缓存,队列深度照常 60。
  • 注意:国内反爬按出口 IP计,dev-swarm 出口 IP 单一,多副本不能分散 CAPTCHA,只能靠限速与缓存(这是设计结论,不是缺陷)。

2.5 负载模型与扩容换算(D1 的决策依据)

实测吞吐锚点(bench 原始数据换算):

通道 实测 持续吞吐换算
国内搜索(searxng-cn) 单发 p50 0.63s 上游钳 6 并发 → ≈9.5 qps
国外搜索(searxng-global,仅 Bing) T3 p50 4.68s 钳 4 并发 → ≈0.85 qps(质量受限见 D2,非容量受限)
正文读取(trafilatura) p50 0.058s @8 并发 服务侧潜力 ≫100/s,瓶颈在上游站点限速
轻渲染(lightpanda 4 槽) 60 任务/28.2s 2.13 jobs/s
保真渲染(shell 1 槽) 60 任务/74.0s 0.81 jobs/s

负载模型(假设·比例待你校准):60 会话活跃,每会话每分钟 2 次搜索 + 3 次读取 + 0.1 次渲染 → 搜索 2 qps、读取 3 qps、渲染 0.1 jobs/s。 结论:L2(1GB)稳态占用率——国内搜索 ~21%、读取 ~3%、渲染 ~5%,可维持 Vlepontas 60 会话级 + EAI 日常负载;压力只在「60 同发突发」与「重页叠加」两个瞬间,由队列(ADMIT_MAX=60)与渲染互斥消化。 L3 1.5GB 的增量价值:① shell 常驻,省每次冷启动(估算 5–10s/次·未单独测);② 重页免互斥,消除渲染互斥排队等待;③ searxng 双副本,滚动重启不断流;④ gateway×2 滚动发布不断线。提议:1GB 承诺不变先上线 L0→L2;若渲染等待或重页互斥成为日常痛点,再申请升至 L3(dev-swarm 节点各 6.5GB,1.5GB 总预算宽裕)。

3. 任务 3:Dock 协议 + 整合器 + 统一输出

设计全文:design-arch §3。要点:

  • DockAdapter 五方法:init / health / execute / teardown / capabilities;health() 强制上报 rss_bytes / startup_ms / slots_free;适配器负责「统一意图 → 引擎原生调用」的输入转换,只产出 RawResult;「RawResult → 统一信封」的输出整合(Size guard → fit markdown → 安全扫描 → Schema 封装)收敛在 Dock worker 共享模版层(整合器),词表/规则单源版本化,N 个适配器零合规代码(S7 架构审查锁定);回收按 N 页/T 分钟硬重启。
  • 统一输入两类意图:Search{query, max_results≤20, time_range?, lang?} 与 Read{url, formats=[markdown], max_chars, extract?};第三类 browse 协议预留默认关闭。
  • 消费者自选国内/国外:MCP 工具暴露 region: domestic|overseas 参数(对应任务 3 的「两种接口类型」),消费者按 MCP 文档自行选择;网关仍按域名路由表强制合规(选了 overseas 也不会把国内域送代理)。
  • 统一 AI 原生信封:{ok, kind, request_id, took_ms, usage{credits,engine,tokens_estimate}, provenance{url,retrieved_at+08:00,adapter,proxy_exit,cached}, error{code,message,retry_after_s?}};search 给 results[{title,url,content≤800字,score 0–1,engine}];read 给 fit markdown(实测提纯:Shopify 壳页 1.44MB HTML → 2.9–3.4KB 正文,约 420–500 倍,lightpanda/chrome 两内核样本)+ 可选 extract 旁路(默认零 LLM 路径:JSON-LD/OG/CSS);错误码 blocked|denied|timeout|quota|rate_limited|extract_failed|upstream 与 HTTP 对齐。
  • 降级链:C(保真)槽满 → B(轻渲染)→ A(HTTP+fit)→ blocked/upstream,不静默降数据质量。
  • 有头浏览器仅抽象插拔预留:Dock Protocol 预留 render=full+headful 能力位(有头/Camoufox 档),默认不装镜像、不占内存预算。

4. 任务 4:ProxyManager + 合规双向保险

设计全文:design-arch §5。要点:

  • 数据面 mihomo + 控制面自研(单副本):订阅解析(实测 SUB-1 为 Clash YAML,69 节点:vless 52 全活、hy2 17 容器 UDP 全灭弃用);多订阅容灾位已留(SUB-2 待你提供);探针 google generate_204,活跃出口 30s、全池 5min/轮;P2C 轮换 + 同域名 sticky;主圣何塞(167ms 实测)备东京。
  • 域名路由表:国内域/*.onesvm.com → DIRECT;黑名单 → deny;高对抗域 → 标记 render=full;默认境外 → vless 池。
  • 生产侧出口拦截(统一策略包单源 + 两个执行点,Schema 之前,MCP/HTTP 共用):请求侧在 gateway(入队前:SSRF fail-closed 每次重定向重验、仅 80/443 → 域名 blocklist + robots 普通 key 遵守);响应侧在 Dock worker 共享模版层(fetch 后、封装前:体积/Content-Type 白名单 → 关键词分类词表对齐《生成式 AI 办法》第 4 条(NFKC 归一,高危 block,PII 默认 redact)→ 注入防护包裹)。词表版本化(wordlist_version 入审计)。命中合规即 error.code=denied 并写审计(consumer_id,url,rule_id,ts+08:00),不假装成功。
  • 消费侧 MCP 文档规则(server instructions 固化):不得用于非法采集、破登录/支付墙/验证码(默认无此能力)、整站搬迁式 crawl、汇总公开个人信息成档案、把含境内个人信息的 query 发往境外引擎。
  • 法律主路径结论(research/05,非法律意见,上线前法务复核):境内集群拉境外公开网页回境内 ≠ 数据出境;但一旦走境外托管 SaaS(Tavily/Jina 云)query 即出境 → 默认境内闭环。
  • 订阅 URL 只进环境变量;节点凭据脱敏;日志禁记 key 明文/query 原文(记 hash+长度)。

5. 任务 5:实测评定结论

评分卡(权重:内存三档 30% / 质量 25% / 成功率 20% / 延迟 15% / 运维 10%;门槛 综合≥60):

方案 组 综合分 实测亮点 实测短板 结论
trafilatura-http 国内 96.8 60/60、p50 0.06s、41MB burst gov.cn 联播壳页 favor_precision 弃取(能力边界) P0 默认开机
searxng-cn 国内 71.5 单发 5/5、p50 0.63s、政策域命中准 60 burst 断言 4/60(百度/搜狗 CAPTCHA;bing-cn 60/60) P0(须网关排队钳 4–8 + 短缓存)
lightpanda 国外 91.0 idle 3.6MB、JS 对照 3/3、T5 60/60 重 Shopify 页 251/320m;CF/Amazon 过不去 P2 默认 JS 核
chrome-headless-shell 国外 85.5 JS 对照 3/3、Shopify 列表价更完整、单槽 FIFO 零拒绝 重页 394/400m;Medium/Amazon 仍拦 P3 保真槽(L2 按需 / L3 常驻)
searxng-global 国外 62.0 实例稳、181MB burst 安全 T3 断言 0/5:vless 数据中心 IP 下 Google/DDG/Brave 全 CAPTCHA/429,仅 Bing 且偏题 擦线入选,部署但产品层不承诺多源(见 D2)

排除:playwright-distributed(Redis 硬依赖)、browser-swarm(仅 macOS,不适配 Swarm)、Browserless(官方建议 4GB 档,重)、Jina reader:oss(捆绑 Chrome+LibreOffice;云端出境)、FerrumMCP/firefox-docker-mcp(生态弱)、Bouncy(无官方镜像、维护风险,列备选)。 预留:Camoufox(强对抗,须住宅代理,150–300MB/实例)→ L4 档。 强对抗事实:Amazon WAF 验证页 / Medium Cloudflare / Reddit 匿名 403——本代理池打不过,设计记 blocked 交预留档,不加并发硬刚。

复跑入口:bench/<方案>/run.sh(无密钥);代理 bench/proxy/up.sh(读 PROXY_SUB_URL)。

6. 任务 6:交付 review

即本文。请你重点过:§2.3 档位表、§5 评分与结论、§7 决策点。

7. 决策点(请你拍板)

# 决策 我的提议 依据
D1 内存档位 先按 L0→L2 渐进上线(≤1GB 承诺不变);若渲染互斥/冷启动成为日常痛点,再申请升 L3 1.5GB。1GB 稳态可维持(占用率见 §2.5),L3 增量是体验与冗余 §2.2/2.3 实测底账 + §2.5 换算
D2 国外搜索质量路线 三选一:a) 接受「仅 Bing + 可能偏题」零成本先用;b) 补充更优质代理套餐/住宅出口(成本项,质量恢复多源);c) 接 Brave Search API 等官方 key(质量好,但 query 出境,须法务确认 + 特权 scope)。提议 a 起步、b 列入采购、c 仅特权 S3c §2 引擎矩阵
D3 端口与前缀 :8640 + /bs-api(:8300 已被 voc-analysis-dev 占用;8640 邻近 WSG 8620 段,无冲突;确认后同步 inventory) inventory §3.2/§5
D4 域名策略默认姿态 blocklist + 高危类 deny(白名单档做成可选配置,政企交付再开) design-arch §5.4
D5 Camoufox 强对抗档 暂不建;等你确认有 Amazon/Medium 类刚需 + 住宅代理预算再启 L4 S3c §7
D6 MCP 兼容 首版仅 2026 Streamable HTTP 无状态;出现旧客户端再加 2025 腿 research/01 §4.1

其余开放问题(SUB-2 容灾订阅、审计留存期、境外 SaaS 特权通道、办法适用性法务判定、scheduler 卷备份演练、amd64 复测、镜像 tag 约定等)见 design-arch §8 O1–O13。

8. 产物索引与验收状态

产物 路径
架构设计全文(任务1–4) docs/design-arch-20260901.md
调研 5 份 .dsh/artifacts/run-20260901-browser-arch/research/
候选筛选+评分卡 .dsh/artifacts/run-20260901-browser-arch/select.md
代理探活 .dsh/artifacts/run-20260901-browser-arch/proxy-probe.md
实测汇总+原始数据 .dsh/artifacts/run-20260901-browser-arch/bench/ + bench/
实测计划/模板 bench/plan.md
Verify / Reverify / Arch-Review .dsh/artifacts/run-20260901-browser-arch/{review,reverify,arch-review}.md

验收链(已闭环,各经一轮 ITERATE 修订后复审通过):S6 Verify PASS → S6 Reverify PASS → S7 Architecture Review PASS(报告:.dsh/artifacts/run-20260901-browser-arch/{review,reverify,arch-review}.md)。