Files

83 lines
8.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 宿主机浏览器控制面
> 当前实现说明,基于已同步的 `main@7e3808cf4ce453b3583079680a3b59ca2ed64ad4`。单节点 native browser + Xvfb 已实现;真实平台、代理、LAN 和多节点能力仍以[验证文档](../native-browser-verification.md)为准。业务范围以 [plan01](../plan01.md) 为准,部署步骤见[部署说明](../deployment.md)。
## 技术选型
- 前端: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`。
## 调用链与职责
```text
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。
## 运行与恢复
使用[部署说明](../deployment.md)中的变量和命令。首次部署时在 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 验收的项目见[验证记录](../evidence/native-browser-verification-2026-09-18.md)。多节点、A/B、跨机故障恢复和性能对比明确移出本目标。