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