8.7 KiB
宿主机浏览器控制面
当前实现说明,基于已同步的
main@7e3808cf4ce453b3583079680a3b59ca2ed64ad4。单节点 native browser + Xvfb 已实现;真实平台、代理、LAN 和多节点能力仍以验证文档为准。业务范围以 plan01 为准,部署步骤见部署说明。
技术选型
- 前端:React 19 + Vite 8 + Refine + shadcn/ui + Tailwind CSS,图标 RemixIcon;项目自有 Layout 与 HashRouter。
- 控制面:Go、Fiber v3、Viper、Logrus、Cobra。控制面编排浏览器 gateway、环境、账号、任务和审计,不直接启动浏览器。
- 浏览器 gateway:Python 3.12+ 标准库 HTTP/进程/文件/socket 能力;以非 root
systemctl --user服务运行,在宿主机管理 Xvfb、native/fingerprint browser、Profile、CDP、代理和运行代次。 - 数据:PostgreSQL 保存网关登记、环境绑定、运行实例、清理状态、租约、账号、任务、结果和审计。浏览器可执行文件、默认版本和路径映射属于 gateway 宿主机配置,不进入 control-plane 管理数据。
- 部署:Compose 只提供控制面和 PostgreSQL;gateway 与 Xvfb 在宿主机运行。控制面在 Compose 中通过
host.docker.internal:8081访问 gateway,裸机运行使用127.0.0.1:8081。
调用链与职责
React ── /api/* (Basic Auth) ──> control-plane ──> PostgreSQL
│
└─ /v1/browsers (Bearer token)
└─ host-native browser gateway
├─ Xvfb display
├─ fingerprint browser + Profile
├─ CDP endpoint
└─ loopback proxy / event stream
控制面是业务事实源,gateway 是本机浏览器资源事实源。gateway 不接受任意 Profile 路径、不暴露通用 CDP、不创建 Docker 资源;Profile 由 gateway 根据 profile_id 映射到 gateway 自己管理的目录。
生命周期契约
生命周期操作都必须带当前 binding_version,并在需要时带 runtime_id、network_id 和 runtime_instance_id。服务端以 alias 串行化操作,拿锁后重新读取账号、环境、版本和出口。
| 接口/动作 | 当前行为与失败语义 |
|---|---|
POST /api/browsers |
接收 alias、name、gateway、fingerprint、account_id、network_exit_id。账号必须满足授权/暂停规则,指定出口必须健康。先保存环境和稳定 binding,再向 gateway 创建停止态 runtime;失败保留环境、operation 和清理状态,不伪造成功。 |
GET /api/browsers、GET /api/browsers/{alias} |
返回数据库状态与 gateway 可达时的 runtime 快照,包括 node_id、generation、ready、运行状态、cleanup 状态和失败原因。不可达、版本缺失、Profile 占用和待清理均保持可见;读取不把未知状态改成 stopped。 |
POST /api/browsers/{alias}/start |
重新核对账号、Profile、出口和 binding。匹配的 ready runtime 可复用;缺失或不匹配时按当前 binding 创建新代次并激活。必需代理失败时不得直连。 |
POST /api/browsers/{alias}/stop |
以当前 generation 停止浏览器、Xvfb、代理和订阅,并记录独立 cleanup 状态。结果未知、强杀或清理失败返回可见失败/待清理状态,而不是请求发出即成功。 |
POST /api/browsers/{alias}/rebind |
接收有效 network_exit_id,要求没有执行中的 runtime-use 或业务任务;成功后递增 binding version。空值切直连不通过此接口隐式完成。 |
DELETE /api/browsers/{alias} |
回收当前 runtime 和本次临时资源,保留环境、稳定 binding、账号 Profile、正式结果和长期监听。旧 generation 的迟到清理不会触碰 successor。 |
每个 runtime 独立拥有:runtime_id、runtime_instance_id、generation、node_id、owner、Profile、display、CDP 端口、loopback proxy 端口、browser/Xvfb unit、日志目录和 cleanup 状态。runtime 结束后,任务目录按结果语义清理;正式素材和结果目录不由通用 runtime 清理逻辑删除。
网关与 Profile
GET/POST /api/gateways注册稳定 gateway endpoint、node name 和令牌;gateway/v1/info返回稳定node_id、默认运行时和能力。浏览器安装、默认版本及可选路径映射只由 gateway 宿主机配置,control-plane 不提供版本登记或升级入口。- 创建环境只绑定账号、gateway、指纹和网络出口;gateway 创建 runtime 时使用自己的默认浏览器配置。当前目标只调度单 gateway,不执行跨机迁移。
profile_id由控制面绑定账号和环境,gateway 只接受已登记的标识并生成目录。Profile 目录权限为 owner-only;同一 Profile 的第二个 runtime 在资源锁阶段拒绝。- 每个执行使用独立的
.runs/<execution_id>目录和不可变 token。业务结果引用相对 work root 的正式产物;路径穿越、绝对路径、跨 work 目录和临时文件均拒绝。
generation 与 runtime-use lease
- 激活 runtime 时保存 owner、node、binding version、runtime/network ID 和 runtime instance ID。所有 gateway 写操作核对这些值;旧代次收到迟到请求时返回冲突,不删除 successor。
- 业务任务和长期监听不共享“环境存在”这一隐含占用。
runtime_use_lease默认 60 秒,20 秒续租;任务、素材处理、平台读取、会话历史和监听均显式 acquire/renew/release。 - lease 续租失败会取消使用上下文并保留失败原因;释放操作幂等。gateway 重启后先按 runtime instance 恢复或标记 cleanup pending,再允许新 lease。
- 采集 task lease 与合法长期监听 lease 分开;监听重连会核对 node/generation/binding,事件去重和 UID 冷却仍由 creator 数据层负责。
代理边界
控制面只把经过校验的出口配置交给 gateway。gateway 代理绑定 127.0.0.1 动态端口,并以 alias、binding version、runtime/network generation 绑定;代理恢复或移除失败必须可见。必需代理启动失败时不切换直连,不把不确定的写结果转换成成功。
出口凭据只存在于控制面单次请求和 gateway 内存代理,不能进入 URL、日志、数据库、浏览器命令行或 API 响应。代理检查、重启恢复和清理均按当前 generation fence。
非 root 与系统边界
- gateway 由宿主机非 root 用户的
systemctl --user服务运行;Xvfb、browser 和 Profile 的 unit 都属于该用户。 - native gateway 不读取 Docker socket,不创建/删除浏览器 container、image、volume 或 network,也不保留 Docker fallback。
- 启动命令拒绝
--no-sandbox等越权参数;无法满足 sandbox、磁盘、路径、端口、权限或版本条件时直接失败并记录原因。 /healthz用于存活;其它 gateway API 使用 Bearer token。控制面继续按现有部署策略提供 Basic Auth;本目标不新增 RBAC。
运行与恢复
使用部署说明中的变量和命令。首次部署时在 gateway 宿主机配置已安装的浏览器和 Xvfb,再以 scripts/install-native-browser-gateway.sh 安装 gateway user service,随后在控制面注册 gateway、账号和出口。
启动、停止和回收分别写 requested/finished operation;gateway 不可达、返回未知、cleanup pending 和 Profile 被占用都在页面和 API 显示。gateway 重启只恢复仍匹配当前代次的 runtime;机器重启不自动恢复已过期短任务。控制面后台 heartbeat 续租 running runtime 并调和 cleanup,读取列表不会用轮询伪装业务事件监听。
阶段 A 与 Creator 业务边界
阶段 A 账号、凭据引用、确认、任务和审计继续由 PostgreSQL 持久化。账号身份在每次写操作前由 gateway 返回的实际 UID 与已授权 platform_account_key 核对;Cookie、密码、token 和 provider reference 不回显。
Creator 采集流程使用独立 runtime-use lease:登录二维码、身份核对、抖音读取、评论/私信历史、素材下载、音频提取和指标处理完成后才释放浏览器使用权。结果保存与资源清理分开记录;结果未知时保留执行目录和证据,不能重复写入或删除可能仍被引用的素材。
当前仍需真实账号、真实代理和人工 LAN 验收的项目见验证记录。多节点、A/B、跨机故障恢复和性能对比明确移出本目标。