---
type: arch
status: active
created: 2026-09-01
step: P2 / plan-20260901-02
---
# onesvm-browser-server 设计与整合方式总览(入门导览)
> 读者:项目 owner 与后续接手工程师。本文是**梳理与导读**,回答四问——**我们如何整合自部署服务?目前整合哪些?怎么整合的?提供什么样的服务?怎么做并发排队的?**
> 权威关系:决策结论以 `plan-final-20260901.md` 为准,机制细节以 `design-arch-20260901.md` 为准,选型理由见 `decision-candidates-20260901.md`;本文只做组织与串联,数字全部引用自既有文档与 bench 产物(2026-09-01 本机实测)。
## 0. 一段式总览
onesvm-browser-server 是一个**面向智能体消费者的自构建联网搜索服务**:所有消费者(Vlepontas、EAI 等)在统一出口网关注册主体、拿 key,以 MCP(主)或 HTTP(兜底)调用两类意图(`search` / `read`);请求经认证、合规预检后进入**零 Redis 的 SQLite WAL 队列**(60 会话接纳上限),由单写者 scheduler 按能力标签路由给 **Dock 适配器集群**——目前整合了 5+1 个自部署组件(双 SearXNG、Trafilatura、Lightpanda、chrome-headless-shell、mihomo 代理数据面);适配器只产出原始结果,统一由**共享 worker 模版层(整合器)**做体积守卫、正文提纯、安全扫描后封装成 AI 原生信封返回。全栈常驻内存实测 ~380MB,承诺 ≤1GB 渐进扩容。
```mermaid
flowchart LR
C[智能体消费者
Vlepontas / EAI / 注册主体] --> G[统一出口网关 ×N 无状态
MCP 主 POST /mcp + HTTP 兜底 /v1/*
X-Service-Token 认证 · 配额预扣]
G --> POL1[合规·请求侧
SSRF / 域名策略]
POL1 -->|overlay POST /enqueue| S[scheduler 单副本
SQLite WAL 单写者 · ADMIT_MAX=60]
S --> RT{能力路由
region / render 标签}
subgraph DOCK[Dock worker 集群(共享模版层 = 整合器)]
subgraph WA[A 无浏览器]
AA1[适配器: searxng-cn
searxng-global]
AA2[适配器: trafilatura-http]
end
subgraph WB[B 轻渲染]
AB[适配器: lightpanda]
end
subgraph WC[C 保真·按需槽]
AC[适配器: chrome-headless-shell]
end
TPL[共享模版层
RawResult → Size guard → fit markdown
→ 安全扫描/PII redact → 统一信封
词表单源版本化]
WA & WB & WC --> TPL
end
RT --> WA & WB & WC
DOCK -.插拔预留 render=full+headful.-> HD[(有头档·默认不部署)]
WB & WC --> PM[ProxyManager 单副本
mihomo vless 热池 · 域名路由]
AA1 -->|国内域| DI[国内直连]
AA1 -->|境外搜索| PM
TPL -->|Envelope ok/error| C
```
(机制细节拓扑见 design-arch §1;接入时序见 design-arch §3.5。)
## 1. 目前整合了哪些自部署服务
5 个消费组件 + 1 个代理数据面,全部经 2026-09-01 本机 Docker 实测(darwin arm64,cgroup 口径;原始数据 `bench/*/results.json`):
| 组件 | 镜像与版本 pin | 角色 | idle | 单会话峰 | 60 burst 峰 | 出处 |
|---|---|---|---:|---:|---:|---|
| searxng-cn | `searxng/searxng:2026.8.29-d226b78bc`(digest b36af798) | 国内搜索(百度/搜狗/360/必应中国) | 98.9MB | 121.6MB | 170.5MB | S3b-summary §2 |
| trafilatura-http | 自构建 `python:3.12-slim-bookworm` + `trafilatura==2.2.0` | 正文精读(纯 HTTP) | 33.0MB | 35.2MB | 40.6MB | S3b-summary §2 |
| searxng-global | 同 SearXNG 镜像第二实例(Google/Bing/DDG/Brave 等) | 国外搜索(实测 Bing-only,见 D2) | 121.6MB | 149.6MB | 181.3MB | S3c-summary §1 |
| lightpanda | `lightpanda/browser:0.3.7`(digest eae2c7f8) | 默认轻 JS 渲染核 | **3.6MB** | 251.4MB(重 Shopify 页) | 143.4MB | S3c-summary §1 |
| chrome-headless-shell | `chromedp/headless-shell:151.0.7922.109`(digest 2d349b54) | 保真渲染单槽(L2 按需/L3 常驻) | 37.5MB | 394.0MB(同页) | 179.3MB | S3c-summary §1 |
| mihomo(ProxyManager 数据面) | `metacubex/mihomo` v1.19.24 | 代理出口(vless 热池 52 节点实测全活) | 小(未单独采样,估算·待校准) | — | — | proxy-probe.md |
为什么选它们(含排除与预留):见 `decision-candidates-20260901.md` §1–§3。
## 2. 怎么整合的(Dock Protocol)
设计全文:design-arch §3。核心四件套:
1. **适配器契约(五方法)**:`init / health / execute / teardown / capabilities`。`health()` 强制上报 `rss_bytes / startup_ms / slots_free`;`capabilities()` 声明支持的意图、渲染分级(`none|light|full`)、出口需求(`domestic|overseas`)、自身并发上限、是否必须走代理。适配器负责把统一意图翻译成引擎原生调用(SearXNG `format=json`、CDP navigate 等),**只产出 RawResult,原生结构不出适配器**。
2. **共享 worker 模版层(= 整合器,S7 架构审查锁定归属)**:所有适配器共用同一层完成 `RawResult → Size/Type guard → fit markdown → 安全扫描 + PII redact + 注入包裹 → 统一信封`;词表/规则**单源版本化**(`wordlist_version` 入审计),N 个适配器零合规代码,杜绝门闩漂移。
3. **能力路由(标签制)**:`region=domestic` 直连、`region=overseas` 经 ProxyManager、`render=none/light/full` 分流到 A/B/C 类适配器;约 90% 流量(搜索 + 纯 HTTP 读)不进浏览器槽。
4. **降级链**:C 槽满 → B → A → `blocked/upstream`,不静默降数据质量(打 `warnings`);`cloudflare/waf/captcha` 拦截不拿渲染空转,直接 `blocked`(站点矩阵实测纪律,decision-candidates §6)。
### 接入第 6 个方案要做什么(示例:新增 RSSHub 适配器)
1. 部署或接入 RSSHub 实例(自部署 Docker,内网端点),版本 pin 写入 stack;
2. 在 worker 代码里新增 `RsshubAdapter` 实现五方法:`capabilities() = {intents:[search,read], render:none, regions:[domestic,overseas], proxy_required:false, formats:[markdown,links]}`;`execute()` 把 `Search/Read` 意图译为 RSSHub 路由请求,返回 RawResult;
3. 在 scheduler 路由表注册标签(如 `region=domestic, render=none, kind=rss`),按需挂路由规则;
4. **不需要写任何合规/提纯代码**——共享模版层自动生效;只需确认 RawResult 字段映射正确;
5. 跑 bench 三档内存 + 模板断言(参照 `bench/plan.md`),数字回填档位表;超预算则开评审。
## 3. 提供什么样的服务
设计全文:design-arch §2/§3.3;决策摘要:plan-final §1/§3。
- **两类意图**:
- `Search{query, max_results≤20, time_range?, lang?, region}` → 返回 `results[{title,url,content≤800字,score 0–1,engine}]`,不含全文;
- `Read{url, formats=["markdown"], max_chars, extract?, region}` → 返回 fit markdown(实测提纯 420–500 倍:1.44MB Shopify 壳 → 2.9–3.4KB)+ 可选 `extract` 结构化抽取(默认零 LLM 路径:JSON-LD/OG/CSS)。
- `browse`(多步交互)协议预留,默认关闭。
- **region 参数**:`domestic` / `overseas` 由消费者按 MCP 文档**自行选择**(国内直连数据 vs 经代理的外域数据);网关仍按域名路由表强制合规兜底。
- **统一信封**:`{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?}}`。
- **错误码**(MCP/HTTP 两面对齐):`blocked | denied | timeout | quota | rate_limited | extract_failed | upstream`。
- **双形态**:MCP Server 为主(`POST /mcp`,Streamable HTTP,2026 无状态;2025 兼容腿挂 O9 待决)+ HTTP API 兜底(独立端口 `:8640` + `/bs-api` 前缀,D3 待确认);认证 `X-Service-Token`,禁 Bearer 塞静态 key。
- **能力边界**(20 站实测矩阵):纯 HTTP 够 7 站、须 JS 4 站、当前出口打不过 9 站(Amazon/Medium/Reddit/X/知乎/微博等)——逐场景结论见 `decision-candidates-20260901.md` §6,原始数据 `site-matrix.md`。
## 4. 怎么做并发排队(零 Redis)
设计全文:design-arch §4;实测校准:plan-final §2。
**为什么不要 Redis**:60 深度远低于 SQLite WAL 舒适区;Redis 白占 30–80MB 直接威胁 1GB 预算;NATS Core 不可靠、JetStream 是另一个中间件;PG SKIP LOCKED 需要现成 PG(本集群没有为此单拉)。
**入队路径**:消费者 → gateway(无状态:认证/配额预扣/合规预检)→ overlay 内网 `POST /enqueue` → scheduler(**SQLite 唯一写者**)进程内快通道 + 立即落 WAL → 落盘成功才 ACK 排队位;scheduler 不可达 → 503 + `Retry-After`(fail-closed,gateway 本地不落盘)。
**背压三层**:`ADMIT_MAX=60`(running+queued 合计)→ 超限 429/503 只拒新不杀旧;`CONCURRENT` 浏览器槽 = 1 起步;`HEALTH` 内存阈 60–70%;渲染互斥规则 `shell_active ⇒ lightpanda 停接新任务`(入队侧执行,无需预知页面重量);租约 + reaper + 指数退避(attempts≤2)+ 死信表。
**实测行为锚点**(为什么这样设计):
| 实测现象(2026-09-01) | 对应设计 |
|---|---|
| chrome-headless-shell CONCURRENT=1:60 任务 FIFO 全入队、顺序执行、**0 拒绝 0 OOM**、墙钟 74.0s | 60 是队列深度不是浏览器并发;保真槽单实例排队复用 |
| lightpanda 4 槽:60/60 全过、28.2s(2.13 jobs/s) | 轻渲染多槽并行,承载 JS 流量主力 |
| searxng-cn 裸 60 并发:HTTP 全 200 但断言仅 4/60——百度/搜狗被 CAPTCHA 打灭,必应中国 60/60 | 网关对上游钳 4–8 并发 + 每 host 最小间隔 + 短缓存;**多副本不能分散 CAPTCHA**(反爬按出口 IP 计) |
| trafilatura 60/60、p50 0.115s、burst 仅 40.6MB | 纯 HTTP 读走高并发快通道,不占浏览器槽 |
**负载结论**:60 会话稳态占用率——搜索 ~21%、读取 ~3%、渲染 ~5%(换算见 plan-final §2.5);1GB 可维持 Vlepontas + EAI 日常负载,扩容触发条件与 L3 增量见 D1。
## 5. 延伸阅读
| 想深入了解 | 去读 |
|---|---|
| 决策点与档位表 | `plan-final-20260901.md` §2/§7 |
| 机制细节(队列字段/代理池策略/合规五道) | `design-arch-20260901.md` §4/§5 |
| 为什么选这 5 套、能力边界矩阵 | `decision-candidates-20260901.md` |
| 实测原始数据 | `bench/*/results.json`、`.dsh/artifacts/run-20260901-browser-arch/` |