14 KiB
共享 Xvfb 与指定 profile 窗口操作:讨论结论
1. 文档定位与完成标准
本文汇总 gateway 的 DISPLAY 配置、共享 Xvfb 的资源收益、窗口定位和 Openbox 激活机制,供后续需求迭代使用。
- 当前事实:依据现有代码、配置样例及本次讨论期间的只读查询。
- 建议方案:尚未实现,不能视为当前产品能力或已经批准的开发任务。
- 本次仅新增文档,不修改代码、配置,不启动或激活浏览器,不发送鼠标事件。
- 文档完成标准:覆盖讨论中的配置、限制、资源、两种输入方式、profile/窗口映射、风险、待办与验收条件,并明确证据边界。
相关资料:
本文讨论的新建议不改变上述文档已有的完成状态,也不表示共享 DISPLAY 或窗口激活功能已经通过验收。
2. 当前 gateway 的 DISPLAY 行为
2.1 默认模式
- 每个 runtime 启动独立 Xvfb。
- 默认从
:100到:199按顺序分配可用 DISPLAY。 - 当前默认屏幕配置为
1280x720x24。 - Chrome 启动时显式设置对应
DISPLAY,不是直接继承 gateway 进程的DISPLAY。 - 默认分配范围目前没有对应环境变量,只有 runtime manager 的构造参数。
2.2 外部 DISPLAY 模式
在 gateway 环境配置中设置:
RUNTIME_EXTERNAL_DISPLAY=99
含义:复用已经存在的 DISPLAY=:99。
- 配置值是正整数,不带冒号。
- 外部 Xvfb 必须事先运行;gateway 不负责启动或停止它。
- systemd 部署的环境文件通常是
~/.config/creatorhub/browser-gateway.env。 - 修改配置后需重启 gateway;已经运行的 Chrome 不会自动切换 DISPLAY。
- 当前可用性检查涉及 X11 socket 是否存在,不能将其等同于完整的显示服务健康检查。
配置和实现依据:
browser_gateway/server/http.py:环境配置解析。browser_gateway/runtime.py:DISPLAY 分配、启动、恢复及释放。deploy/browser-gateway.env.example:配置样例。deploy/creatorhub-browser-gateway.service.in:环境文件加载。
2.3 当前共享限制
Xvfb 本身支持多个 Chrome 共用同一个 DISPLAY;禁止共享是 gateway 当前的应用限制。
现有外部模式包含两层占用处理:
_reserve_display检查运行记录:如果其他未released的 runtime 已记录同一 DISPLAY,则拒绝启动。检查不只限于正在运行的浏览器,stopped记录也可能触发。DisplayAllocator.reserve_existing对 DISPLAY 使用独占文件锁;当前实现会在浏览器启动后释放 display lease,不能把它描述为贯穿运行期的独占锁。
若允许共享,应同时审查记录检查和外部模式的锁流程,不能只删除报错分支。默认模式自行启动 Xvfb 的分配锁仍有必要保留,避免两个启动流程竞争同一 DISPLAY。
3. 每增加一个 Xvfb 的资源开销
3.1 本次讨论期间的运行快照
| 屏幕配置 | 进程显示内存 RSS | 共享内存按比例分摊后的 PSS | 短时 CPU 均值 |
|---|---|---|---|
1280x720x24 |
约 64.8 MiB | 约 32.0 MiB | 0.00% |
1920x1080x24 |
约 53.3 MiB | 约 35.5 MiB | 0.33% |
测量来自现有 Xvfb 的 /proc/<pid>/smaps_rollup 和短时间 pidstat 采样,未为测量启动新进程。
解释与边界:
- RSS 含共享页,不能简单相加得出额外物理内存;PSS 是当前分摊值,也不是新增一个进程的严格边际成本。
- 两个进程运行历史和负载不同,不能根据表格推导较高分辨率反而更省内存。
- CPU 百分比按单核口径理解;本次近乎空闲的采样不代表视频、动画或频繁重绘时的消耗。
- Chrome、VNC、Openbox 的资源消耗均不包含在上述 Xvfb 数字中。
- 未保留完整的负载条件和连续曲线,因此这些数据是运行快照,不是性能基准。
3.2 容量规划建议
可暂按 每个 Xvfb 预留 50~70 MiB 估算,10 个约 0.5~0.7 GiB。该数字是当前快照下的粗略预留值,不是上限或保证。
24 位色的像素通常按 32 位存储,1280×720 单帧约 3.52 MiB,但 Xvfb 还包含绘图资源、字体、连接和缓存,不能只用单帧大小估算进程内存。
共享 DISPLAY 能减少独立 Xvfb 的重复固定开销;不会消除各个 Chrome 的内存,也不会让所有窗口绘图资源的占用归零。是否值得共享,仍需结合目标并发数和实际页面负载判断。
4. 共享 DISPLAY 的收益与代价
| 项目 | 独立 DISPLAY | 共享 DISPLAY |
|---|---|---|
| Xvfb 固定开销 | 每个 runtime 一份 | 多个 runtime 共用 |
| Chrome 数据目录、控制端口 | 各自独立 | 仍须各自独立 |
| 桌面鼠标、键盘焦点、剪贴板 | 各自独立 | 全部共享 |
| VNC 可见窗口 | 单个浏览器为主 | 多窗口可能遮挡 |
| Xvfb 故障影响范围 | 对应 runtime | 所有共享者 |
| 桌面输入协调 | 每个 DISPLAY 内协调 | 所有共享者统一协调 |
建议方向,尚未实现:默认保留独立 Xvfb;外部 DISPLAY 模式允许共享。
停止一个浏览器时,外部模式没有由该 runtime 持有的 Xvfb unit,现有清理流程不会主动关闭外部 Xvfb。共享后的启动、恢复、停止、状态判断仍需完整验证。
5. 指定 profile 的两种输入方式
5.1 直接控制网页:CDP
profile_id → runtime → 独立 cdp_port → 页面 targetId
Page.bringToFront:选择对应页面并请求置于前台。Input.dispatchMouseEvent:向指定页面发送鼠标事件。- 事件坐标是主框架视口内的 CSS 像素,不是 Xvfb 桌面坐标。
- 请求通过独立控制连接定位到对应 Chrome,无需按桌面位置寻找账号。
- 这不等于控制系统鼠标,也不覆盖浏览器工具栏或原生系统弹窗。
- 依赖前台焦点或页面可见性的行为仍需协调,不能笼统承诺所有操作均可并发。
推荐:只需网页内输入时优先采用 CDP。
5.2 桌面输入:X11 + Openbox
profile_id → runtime.browser_pid → X11 窗口 ID → 激活窗口 → 桌面输入
适用于需要真实桌面焦点、VNC 前台窗口或网页之外的操作。必须注意:同一个 DISPLAY 只有一套桌面鼠标和键盘焦点,不能把多个窗口理解为多个独立输入设备。
本文仅说明事件与目标窗口的对应机制,不涉及验证码识别、求解或自动绕过,也不保证网站接受合成输入。
6. Openbox 如何激活指定 profile 的窗口
6.1 职责和绑定关系
Xvfb 提供虚拟屏幕,例如 :99
Openbox 管理该屏幕上的窗口、桌面、遮挡顺序和焦点
Chrome 创建窗口,并声明窗口所属进程
gateway 保存 profile 对应的 Chrome 运行信息
Openbox 不认识 profile_id,也不保存账号绑定。绑定关系由 gateway 查询或维护:
profile_id
→ 当前 runtime 的 display、browser_pid、browser_start_time
→ 同一 DISPLAY 上 _NET_WM_PID 匹配的顶层窗口
→ X11 窗口 ID
→ 向 Openbox 发送激活请求
当前每个 profile 使用独立的 --user-data-dir 和 Chrome 进程,这是按 PID 对应 profile 的前提。若未来改为多个 profile 共用同一 Chrome 进程,这条映射将不再足够,不能沿用结论。
一个 DISPLAY 通常运行一个窗口管理器。Xvfb 自身不提供窗口管理;若该 DISPLAY 尚无窗口管理器,可由部署方在该 DISPLAY 上运行 Openbox。gateway 目前不会因此自动具备管理 Openbox 生命周期的能力。
6.2 命令示例
以下 PID、窗口 ID 是示意值;本次没有实际执行激活。
假设运行记录是 display=99、browser_pid=23456:
export DISPLAY=:99
# 查看窗口管理器。
wmctrl -m
# 查看顶层窗口:窗口 ID、桌面、PID、主机、标题。
wmctrl -lp
示意输出:
0x01200003 0 23456 host 抖音 - Google Chrome
0x01400003 0 34567 host 抖音 - Google Chrome
第三列匹配目标 Chrome PID,因此候选窗口是 0x01200003。可进一步检查:
xprop -id 0x01200003 _NET_WM_PID WM_CLASS
确认窗口唯一且仍属于目标 Chrome 后,请求激活:
timeout 5s xdotool windowactivate --sync 0x01200003
xdotool 通过 EWMH 窗口管理协议发送请求,Openbox 执行桌面切换、窗口置前和焦点分配;--sync 等待目标窗口成为激活窗口,外层超时避免无限等待。超时或失败必须报告,不能继续发送输入。
检查激活结果:
xdotool getactivewindow
xdotool getactivewindow getwindowpid
不仅检查 PID,还应确认激活的是选定窗口;同一 PID 可能有多个窗口。
6.3 只读验证证据
本次讨论期间,在本机 DISPLAY=:99 上只读检查发现:
wmctrl -m报告窗口管理器为 Openbox。- 一个 Chrome 窗口的
_NET_WM_PID与实际 Chrome 进程 PID 一致。 - 该 Chrome 进程命令行包含其独立
--user-data-dir。 - 本地
xdotool手册确认windowactivate --sync的激活等待行为。
这验证了环境与映射依据,不代表 gateway 已经实现或验证按 profile 激活窗口;本次未执行窗口切换、拖动或网页操作。
7. 窗口定位和输入的必要约束
- 不按标题或窗口顺序绑定:页面标题会变,不同 profile 可能打开相同页面。
- 重启后重新定位:PID 和 X11 窗口 ID 都可能改变;校验进程启动时间,防止 PID 被复用。
- 多窗口必须明确目标:一个 profile 可以有多个窗口。找不到窗口或找到多个候选时明确报错,不能自动取第一个。
- 窗口与标签页分开处理:激活 Chrome 窗口不代表选中了指定标签页。指定页面使用 CDP 的
targetId。 - 两种窗口 ID 不能混用:
Browser.getWindowForTarget返回的 CDPwindowId不等于 X11 窗口 ID。 - 同屏桌面操作串行:协调范围至少覆盖“定位、激活、确认、按下、移动、释放”,不能只锁激活步骤。若存在多个控制进程,必须明确单一控制者或跨进程协调方式。
- 人工操作也会抢焦点:VNC 使用者不受程序锁约束。操作期间应避免人工输入;检测到目标变化时中止并报告,不能声称程序锁能消除全部竞争。
- 错误必须可见:窗口管理器缺失、窗口不存在、映射歧义、激活超时、焦点丢失均应报告。中断输入时应清理本次按键/按钮状态,不能静默改投其他窗口。
8. 后续迭代事项(待确认后实施)
A. 外部 DISPLAY 共享
- 调整外部模式的运行记录独占检查和 display lease 处理。
- 保留默认独立模式的 Xvfb 分配和生命周期隔离。
- 核查共享模式的启动、停止、释放、gateway 重启恢复、显示服务失效等路径。
- 更新配置说明、相关测试及与行为发生冲突的既有文档。
B. 按 profile 激活窗口
- 从当前 runtime 获取 DISPLAY、浏览器 PID 和进程启动时间。
- 在对应 DISPLAY 上查询受管理的 Chrome 顶层窗口。
- 定义多窗口时的目标选择规则;未确定规则前,不新增猜测或兜底行为。
- 使用现有 X11 工具请求激活,并校验结果、设置超时、报告错误。
- 窗口 ID 优先即时查询,不为短生命周期标识新增数据库绑定表。
C. 输入方式及协调
- 根据实际需求明确采用网页 CDP 输入还是桌面 X11 输入,不把两者混作同一能力。
- 桌面输入按 DISPLAY 协调整个操作过程,并明确人工 VNC 输入的处理约定。
- 是否由 gateway 管理 Openbox、是否需要专用操作接口,由后续需求单独确认;当前不新增部署层或接口。
D. 日志与资源验证
- 关键记录至少包括:操作编号、profile、runtime、DISPLAY、浏览器 PID/启动时间、目标窗口、激活前后状态、耗时和失败原因。
- 区分“未找到窗口”“多个候选”“服务不可用”“激活失败”“焦点改变”,避免只记录通用失败。
- 若节省内存是迭代目的,应在相同页面、相同 profile 数量与相同负载下对比独立/共享模式;统计 Xvfb、Chrome、Openbox、VNC 整体资源,而不是只累加 RSS。
9. 后续开发验收条件
功能开发遵循 TDD,相关单元测试覆盖率至少 65%;不主动编写或运行 E2E 测试。
单元测试应覆盖
- 默认模式为不同 runtime 分配独立 DISPLAY。
- 共享外部模式允许多个 runtime 使用同一 DISPLAY,且保留独立数据目录和控制端口。
- 停止一个 runtime 不关闭外部 Xvfb,不影响另一个 runtime。
- gateway 恢复时正确识别共享 DISPLAY 与各自浏览器状态。
- 外部 DISPLAY 不可用时明确报错,不自动切换到其他屏幕。
- profile/PID/窗口定位成功、窗口缺失、多窗口歧义、PID 失效和窗口失效。
- 激活成功、超时、窗口管理器缺失与结果不匹配。
- 同一 DISPLAY 的桌面输入不会交叉执行;失败能释放协调资源并报告。
需要使用者明确授权的现场验证
- 两个独立 profile 共用一个 Xvfb,确认窗口和账号数据互不混淆。
- 按 profile 激活窗口,包含窗口被遮挡、位于其他桌面以及重启后的情形。
- 在普通可拖动页面验证目标窗口与输入坐标,避免以验证码求解作为验证标准。
- 检查停止其中一个浏览器后另一浏览器和外部 Xvfb 是否正常。
- 记录相同负载下的资源变化及日志证据。
实施前仍需确认:是否启用共享外部 DISPLAY、是否需要桌面输入、多窗口选择规则、Openbox 由谁管理。本文不替代这些决策。