本节摘要:本节回答「浏览器会话从哪来」的最后一问:自建(第 7.2 节的容器加 steel-browser)还是外购(Browserbase 类托管服务)。先讲托管供给什么:规模(Browserbase 官网口径月 3500 万以上会话、约 1 万客户)、会话即 API(创建、连接、回收都是接口调用,第 7.2 节手工拼的沙箱在这里是平台内置)、稳定性供给(会话调度、故障迁移、隐式重试)与指纹管理(平台维护的环境一致性,工程细节以官方文档为准)。再给自托管与托管的四维对照表:成本模型(固定运维投入对按量计费)、数据面(域内对出域)、运维责任(自己背对平台背)、合规审查(自己的审计对供应商评估)。接入示例双语:Stagehand 的 env 切换(LOCAL 对 BROWSERBASE 一行换供给)、browser-use 经 CDP 接自托管会话。收在选择框架:数据能否出域与团队想背多少运维,这两个问题的答案划出分界线。混合形态(自托管引擎加托管浏览器)是两问各让一步的中间解。
第 7.2 节自建沙箱的成本是一次性工程投入加持续运维;托管服务把这笔投入变成了别人的生意。以 Browserbase 为例(商业 SaaS,官网口径月 3500 万以上会话、约 1 万客户),它供给的东西可以拆成四类:
| 价值 | 内容 | 对应自建时的痛 |
|---|---|---|
| 规模与弹性 | 并发会话按需扩缩,峰谷不用自己备容量 | 容量规划、闲置成本 |
| 会话即 API | 创建、连接、列表、回收全是接口 | 自己写会话管理面 |
| 稳定性供给 | 会话调度、故障迁移、隐式重试 | 自建高可用与故障恢复 |
| 指纹与环境一致性 | 平台维护的浏览器环境,工程细节以官方文档为准 | 第 8 章的指纹一致性自管 |
第四行要谨慎读:托管平台的环境一致性能力解决的是「会话之间环境不漂移」的工程问题,它不是在任何站点上畅通无阻的通行证——授权与礼仪的合规边界(第 8 章)不因买了托管而消失,反而因为规模化访问更需要自觉。这句话是本节与下一节的接缝。
| 维度 | 自托管(自建池或 steel-browser) | 托管(Browserbase 类 SaaS) |
|---|---|---|
| 成本模型 | 固定投入:服务器、工程、运维人力 | 按量计费:会话时长或条数 |
| 数据面 | 完全域内:页面内容、Cookie、轨迹不出公司网络 | 出域:流经供应商基础设施 |
| 运维责任 | 自己背:升级、扩容、故障恢复 | 平台背:自己只管用好 API |
| 合规审查 | 内部审计即可覆盖 | 需供应商评估:数据处理条款、留存策略 |
| 弹性上限 | 受自有容量限制,扩容有周期 | 平台弹性,理论上线高 |
| 适用初判 | 数据敏感、任务稳定、团队有运维 | 快速起步、峰谷明显、不想背浏览器运维 |
这张表的决策顺序建议:第一问数据能否出域——涉及客户数据、内部系统、受监管行业的任务,这一问经常直接结束讨论;第二问运维意愿与能力——第 7.2 节那些「环境税」(shm、限额、回收)愿不愿意长期交;第三问才轮到成本——两边的账都要按任务量算斜率,量小时自建固定投入摊不平,量大时托管按量计费的曲线会追上来。规模本身不是选托管的理由,「弹性的峰谷」才是。
Stagehand 的 env 选项是「换供给不改代码」的典型(第 3.2 节提过路标):
// remote_env.mjs —— Stagehand 的供给切换(写法示意,以官方文档为准) import { Stagehand } from "@browserbasehq/stagehand"; // 本地形态:浏览器在本机,开发调试用 const local = new Stagehand({ env: "LOCAL", modelName: "gpt-4o" }); // 托管形态:同一套代码,会话由平台供给(凭证一律走环境变量,见第 7.1 节) const cloud = new Stagehand({ env: "BROWSERBASE", modelName: "gpt-4o", // apiKey 经环境变量注入,代码与仓库零明文 }); console.log("两种供给形态构造完毕,业务代码不变");
自托管侧的等价物是 CDP 接入:把第 7.2 节沙箱里的浏览器暴露成调试端口,智能体框架连上去用——browser-use 的形态(写法示意):
# remote_session.py —— 经 CDP 接自托管浏览器会话(写法示意,以官方文档为准) import asyncio import os from browser_use import Agent, Browser from langchain_openai import ChatOpenAI async def main() -> None: browser = Browser(config={"cdp_url": os.environ.get("BROWSER_CDP", "")}) agent = Agent( task="打开 http://127.0.0.1:8080/demo_todo.html,读取页面标题并返回。", llm=ChatOpenAI(model="gpt-4o"), browser=browser, ) result = await agent.run() print(result.final_result()) await browser.close() asyncio.run(main())
两个示例合起来看:供给的切换点已经被框架抽象掉了。这正是 5.3 节形态光谱「地基层」的意义——地基换供应商,房子不动。评估新供给时的验收清单也因此很收敛:会话创建延迟、连接稳定性、回收是否干净、凭证注入面、日志导出能力——五项过关即可替换。
「会话即 API」的操作面也值得单独看一眼——无论自托管还是托管,会话生命周期都收敛成四个动词,这决定了接入层代码的形状:
| 操作 | 语义 | 工程注意 |
|---|---|---|
| create | 新建会话,返回标识与连接串 | 幂等设计(重试不重复建) |
| connect | 经 CDP 或平台协议接入受控会话 | 连接串是敏感物,按第 7.1 节台账管理 |
| extend | 延长即将到期的会话 | 长任务必配,防中途被回收 |
| release | 结束并销毁会话 | finally 里必调,第 10.1 节回收纪律 |
四个动词对齐的好处:接入层可以写成与供应商无关的薄封装,替换供给时只换适配器;坏处也要知道——各家的会话保活语义、过期宽限、并发配额各有细节,迁移评估时逐项对照,别默认等价。
两个极端之间有中间解:自托管引擎加托管浏览器(如 Skyvern 自托管加 Browserbase 出会话,5.3 节提过)——数据面里最敏感的部分(模型调用、轨迹、审计日志)留在域内,弹性最吃紧的部分(浏览器并发)外包。反向混合也存在:敏感任务走自建池、普通任务走托管,按任务分级路由。分级的依据应该写进任务定义文档,而不是运行时现场判断。
容量与成本的初算方法(示意框架,数字按你自己的量填):自建侧等于固定成本(服务器加人力)除以月任务量加单任务变动成本;托管侧等于单会话单价乘平均时长乘任务量加出口流量。两条线一画,交叉点就是「换档位」的参考位——记得把第 10 章的并发峰值与第 6.2 节的救援预算算进时长,别用理想时长算账:
月成本 ▲ 托管:单价 × 平均时长 × 任务量(随量近似线性) │ ╱ │ ╱ │ ╱ ← 量大之后斜率开始咬人 │ ╱ │ ─ ─ ─ ╱ ─ ─ ─ ─ ─ ─ ─ ─ 交叉点 ≈ 换档参考位 │ ╱ ────────────────────── 自建:固定投入 + 低斜率变动成本 └────────────────────────────▶ 月任务量
这张图的读法提醒:交叉点左侧托管便宜(固定投入摊不平),右侧自建的优势逐渐放大(斜率低);但「换档」本身有迁移成本(第 7.2 节那批环境税要重新交一遍),所以实际决策常在交叉点右侧一段距离才发生——把迁移成本画成纵轴上的一个跳变,图就完整了。
| 坑 | 现象 | 排查与处理 |
|---|---|---|
| 以为托管等于合规 | 规模化访问被站点限流 | 速率礼仪自管,第 8 章 |
| 用理想时长算账 | 实际账单远超预期 | 把重试与救援预算计入时长模型 |
| 供应商锁定 | 迁移时发现代码焊死 | 用 env 或 CDP 抽象供给切换点 |
| 数据出域未评审 | 法务事后叫停 | 上线前过供应商数据处理条款 |
| 凭证配在平台侧就不管 | 轮换断档 | 轮换流程覆盖所有持凭证方(第 11.3 节) |
会话、沙箱、供给三层基建就位。但无论会话从哪来,站点都会问同一个问题:你是谁。下一章进入全书最需要清醒的部分——指纹、检测面、stealth 的工程与伦理红线,以及让每一步自动化都可举证的审计留痕。