关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

浏览器自动化跑到几百个会话就随机崩,问题通常不在并发数

发布时间:2026-10-13

集群白天跑得好好的,一到夜里跑批,跑到第三百个会话上下开始随机报 session not created、target window already closed,重跑一次又能过,重启节点立刻恢复,过两三个小时又来一遍。这种"能自愈、又反复发作"的故障最折磨人,因为它看起来像偶发,实际上是一条被慢慢耗尽的账。多数团队的第一反应是把并发数从 20 调到 12、再调到 8,故障确实变少了——但它只是被推迟了,跑到第八百个会话照样崩,而且崩的时间点更难预测。

先把结论摆在这里,后面逐条展开:

一、随机崩的第一怀疑对象应该是 /dev/shm,不是并发数。Linux 容器里 /dev/shm 默认通常只有 64MB,Chrome 与 Chromium 的官方文档及主流社区镜像普遍建议启动时放大它,社区常见做法是 --shm-size=2g。

二、单个浏览器实例的内存要按峰值算,不按均值算。公开经验区间从数百 MB 到 1GB 以上,取决于页面复杂度,实际数值仍需结合自身页面与并发实测确认。

三、临时 profile 目录和 inode 往往比内存更早撞线。df -h 还有空间,df -i 已经满了,这种场景在长时间跑批里非常常见。

四、会话没有 quit 干净,泄漏会随时间线性放大。僵尸进程、残留 profile 目录、没回收的端口与句柄,每一样都在偷偷吃掉下一次会话的启动资格。

五、往下调并发数只是把崩溃时间往后推。真正的解法是把资源账算清楚、把回收做干净、把故障域按节点切开。

会话随机崩的时候,先看是"资源没了"还是"进程卡了"

这两类故障的表面症状几乎一样:用例失败、会话超时、节点失联。但处理方式完全不同,混在一起排查就会陷入"加了内存还是崩"的死循环。

区分的办法其实很朴素,看故障发生的位置有没有规律。资源耗尽型的崩溃,几乎每次都发生在累计创建到第 N 个会话之后,N 的波动范围不大;重启节点、清空 /tmp、重新拉起容器之后能立刻恢复;日志里多半能翻到 OOM killer 的记录、exit code 137、或者"No space left on device"。进程卡死型则相反,它跟你跑了多少个会话没关系,可能第一个会话就卡,也可能第五百个;表现通常是超时而不是报错,节点在 Grid 里仍然显示为在线,但响应越来越慢;翻进程栈会发现卡在某个 JS 执行、某个网络等待或者某个同步锁上。

这里有个很实际的操作:在节点上记一条"本次节点生命周期内已创建会话累计数"的计数,故障发生时把数字打出来。如果三次故障分别发生在 290、305、298 附近,那就是资源账,别再往"用例不稳定"上想了;如果是 3、147、512 这种散点,那才该去查页面逻辑、超时设置和目标站点的响应波动。

还有一类混合情况值得单独提一句:泄漏本身不改变单次会话的稳定性,它只改变节点能撑多久。所以你会看到"前两百个会话一切正常、之后故障率陡增"这种曲线——这基本就是资源账的形状。

一个浏览器实例到底吃掉哪几类资源

要算密度,得先知道一个浏览器实例在机器上到底摊了几笔账。很多人只算内存,于是算出来的密度总是对不上。

内存:主进程、渲染进程与 GPU 进程是三笔账

现代 Chromium 内核是多进程架构,启动一个实例并不是只起一个进程:浏览器主进程、渲染进程、GPU 进程、网络服务进程、若干工具进程,一个会话轻易就能开出十来个进程。页面里的 iframe、跨域子页面还会再拆出独立的渲染进程。所以"一个实例占多少内存"这个问题的答案跨度极大——公开经验区间从数百 MB 到 1GB 以上,取决于页面复杂度、图片与视频数量、前端框架的内存习惯,实际数值仍需结合自身页面与并发实测确认。算密度时别用平均值,用你实测到的峰值,再乘一个余量系数。

CPU:突发型负载,不是持续型负载

浏览器对 CPU 的占用是典型的脉冲状:页面加载的头两三秒,解析 HTML、执行脚本、布局渲染、解码图片,CPU 可以瞬间打满;页面加载完之后,如果脚本里没有轮询或动画,CPU 会迅速回落到接近零。这个特性决定了两件事——一是按 CPU 均值算密度会严重高估承载能力,因为你真正要扛的是"同时有多少个实例正好在加载";二是短时间的超订是可行的,但超订倍数取决于你的用例里"加载态"占多大比例。

共享内存:一块被严重低估的区域

Chromium 会把一部分渲染过程中的临时数据放到 /dev/shm,这是 Linux 提供的共享内存文件系统。它不占用普通内存的账本,也不占用磁盘,属于独立的一块配额。问题在于容器环境下这块配额默认很小,于是它成了最先撞线的那个。下一章单独讲。

磁盘与临时目录 IO

每次创建会话,浏览器都会新建一个临时 profile 目录,通常在 /tmp 下。目录里放的是缓存、Cookie、本地存储、会话数据。页面越重、缓存策略越宽松,这个目录长得越快。同时还有磁盘 IO:缓存写入、截图落盘、下载文件。这块的特点是"慢",它不会让会话立刻崩,而是让会话启动越来越慢、超时越来越多,直到某个点突然全线失败。

文件句柄与进程号

一个 Chrome 实例会打开大量文件描述符:页面资源、缓存文件、socket、管道。乘以并发数之后,很容易顶到 Linux 默认的打开文件数上限(ulimit 里常见的 1024)。进程数也是同理,十几个进程一个实例,二十并发就是两百多个进程。这两项在短时间跑批时不会出问题,一旦进入长时间、大批量的节奏,就会以"resource temporarily unavailable"这种含糊的报错冒出来。

/dev/shm 默认那点空间为什么最先出事

在 Linux 容器里,/dev/shm 的默认大小通常是 64MB。这个数字对很多常规应用够用,对浏览器来说偏小。Chromium 官方文档与各类社区镜像里,普遍建议启动容器时把这块放大,社区常见的做法是 docker run 时带 --shm-size=2g。要写清楚的是:2g 属于官方与社区常见建议值,是否需要更大、能不能更小,需要结合你的页面类型实测确认——跑纯文本表单页面的集群和跑富媒体页面的集群,需求完全不是一回事。

为什么它最先出事?因为共享内存是"用完了就没了"的硬配额,不像普通内存那样有页缓存和交换机制可以缓冲。渲染进程申请共享内存失败,通常不会给你一条"共享内存不足"的清晰报错,而是表现为渲染进程崩溃、页面白屏、target window already closed,或者干脆在创建会话阶段就失败,报 session not created。这类报错信息会把排查方向引到并发数、驱动版本、浏览器版本上去,很少有人第一眼想到 /dev/shm,于是排查周期被拉得很长。

判断方法很简单:进到容器里执行 df -h /dev/shm,看这块的大小和已用比例。如果它是 64MB,那基本可以直接锁定。在节点跑批过程中持续采样这个数值,你会看到它随会话数起伏,撞到上限的时候就是崩溃的时刻。

调整办法有两条路。第一条是直接放大共享内存,容器启动时指定 --shm-size,物理机或虚拟机上则调整 /dev/shm 的挂载大小。第二条是给 Chromium 传 --disable-dev-shm-usage,让它改用 /tmp 而不是 /dev/shm。第二条路要清醒地认识它的代价:这不是把需求变没了,而是把压力从共享内存转移到了 /tmp 的磁盘空间和 IO 上。如果你的 /tmp 本身就是容器可写层或者一块普通云盘,那等于把一个隐蔽问题换成另一个隐蔽问题。真正干净的做法还是把 /dev/shm 放大到位。

会话没有正常关闭,泄漏是怎么被放大的

资源账算得再准,只要会话泄漏存在,账本就会被持续透支。泄漏本身不难理解,难的是它的隐蔽性——单次泄漏的影响微乎其微,累积三百次之后才致命。

最常见的来源是异常路径没走清理。测试脚本里写了 driver.quit(),但用例中途抛异常、超时被框架 kill、或者网络断开导致 driver 对象失联,那行 quit() 就永远不会执行。浏览器进程还在,内存还占着,profile 目录还留在 /tmp,调试端口还占着。Grid 的 Session Map 里这条会话可能仍然被记为有效,直到心跳超时才被判定失效,这中间的时间差里,节点的可承载额度已经被占掉一格。

僵尸进程是第二个放大器。父进程没有正确 wait 回收子进程,子进程退出后会留下一条内核进程表项,占着 PID 和少量资源但不可被调度。单个僵尸进程影响很小,问题是它们不会被自动清理,会一直累积到进程号配额或者进程表上限。

残留 profile 目录是第三个。每个会话新建一个临时目录,正常退出时应该被删除,泄漏时不会。跑一晚上下来,/tmp 下可能是几万个目录、几百万个小文件。这个时候 df -h 可能显示磁盘还有三成空间,但 df -i 显示 inode 已经用完了。于是新的会话连 profile 都建不出来,报的错却是创建会话超时。这个坑非常典型:只看 df -h 的团队会一直以为是内存问题。

端口与句柄同理。Chromium 的远程调试端口、WebDriver 的连接、页面里的长连接,泄漏时会不断累积,直到本地端口范围或者 fd 上限被顶穿。

怎么判断泄漏存在?对比两个数:Grid 侧记录的该节点活跃会话数,与节点上实际的 chrome/chromedriver 进程数。如果后者长期显著高于前者,且随运行时间单调增长,那就是泄漏。另一个更直接的指标是空闲时段的基线资源占用——跑批结束后等十分钟,节点内存和进程数如果回不到启动时的水平,就有东西没被回收。

处理上要做三件事:脚本层的 quit 放进 finally 或者框架的同级清理钩子里,保证异常路径也能执行;节点层加一个定时清扫,清理超时未活动的会话、超过 N 分钟的残留 profile 目录;集群层给节点设生命周期上限,比如累计处理到一定数量的会话或者运行到一定时长就主动重启一次,用可控的重启替代不可控的崩溃。

节点密度怎么估:核数、内存与突发负载三者的换算边界

密度测算没有万能公式,但有三个约束必须同时满足,取其中最小的那个作为上限。

第一个是内存约束,这是硬约束。算法是:可用内存 = 物理内存 - 系统预留 - Grid 组件占用 - 页缓存与安全余量;单实例额度 = 实测峰值内存 × 余量系数(一般取 1.2 到 1.5,取决于你的峰值样本够不够全);密度上限 = 可用内存 ÷ 单实例额度。这里的坑在于"实测峰值"——很多人拿空闲页面的占用去算,算出来的密度能跑纯静态页,一上真实业务页就崩。正确做法是拿你最重的那个页面,在并发条件下测,取峰值。

第二个是 CPU 约束,这是软约束。浏览器的负载是脉冲状的,所以并发数可以适当超过核数,但超订倍数要看用例画像:如果每个会话大部分时间在等待(显式等待、网络 IO、人工设定的思考时间),超订到核数的 1.5 到 2 倍通常还能接受;如果用例是密集的页面操作、频繁截图、大量 DOM 查询,那就应该往核数的 1 倍甚至更低靠。这些都是经验性的起点,不是结论,实际数值仍需结合自身页面与并发实测确认。

第三个是安全余量约束。别把内存算到 100%,长期跑批的机器要留 20% 到 30%。原因有两个:一是页缓存被挤掉后,临时目录 IO 会明显变慢,反过来拖累会话启动;二是留余量才有缓冲空间应对页面改版、目标站点加载了一个更重的资源这类突变。

举个估算示例,注意这是推算逻辑不是实测结论:一台 16 核 64GB 的节点,系统与其他组件预留 8GB,安全余量按 20% 计,可用约 45GB;若实测单实例峰值为 1GB、余量系数取 1.3,则单实例额度 1.3GB,内存约束给出的密度上限约 34。CPU 侧 16 核,按 1.5 倍超订给到 24。取小值,密度定在 24 左右,再往下压一点留作观察期。跑一周看曲线,再决定是否上调。

这个示例要强调的一点:决定最终密度的是内存而不是核数,这在这类负载里几乎是常态。所以"继续加内存"确实能提升密度,但提升幅度会越来越小——因为 /dev/shm、句柄、IO 这些约束并不跟着内存一起涨。

集群关键资源项与调整办法

把前面拆开的几类资源收拢成一张表,排查的时候按顺序过一遍,比凭感觉调参有效得多。需要说明的是,Selenium Grid 4 由 Router、Distributor、Node、Session Map、Session Queue、Event Bus 等组件构成,节点通过心跳向 Distributor 注册;Session Map 默认是内存态,生产环境需要考虑它的持久化形态,否则组件重启会带来会话映射信息丢失的问题。

资源项 常见默认值 为什么先撑不住 典型故障现象 调整办法
共享内存 /dev/shm 容器默认通常 64MB 渲染进程把临时缓冲放这里,是硬配额,没有页缓存兜底,页面越重用得越多 页面白屏、target window already closed、session not created,报错不指向真实原因 启动容器时 --shm-size=2g(官方与社区常见建议值,需结合页面类型实测);慎用 --disable-dev-shm-usage,它只是把压力转到 /tmp
单实例内存 公开经验区间数百 MB 到 1GB 以上 多进程架构叠加,页面复杂度决定跨度;密度按均值算必然算高 容器 exit code 137、节点整体掉线、Grid 显示节点不可用 按实测峰值 × 1.2–1.5 余量算额度,系统预留 20%–30%,不要压满
临时 profile 目录 每会话在 /tmp 下新建,退出时删除 泄漏时目录堆积,小文件极多,先耗尽 inode 而不是容量 磁盘显示有余量却报 No space left on device、会话启动越来越慢 独立挂载卷或 tmpfs;定时清理超时残留目录;同时监控 df -h 与 df -i
打开文件数与进程数 Linux 默认 nofile 常见 1024,nproc 亦有限制 一个实例开十几个进程与大量描述符,长跑批下线性累积 too many open files、resource temporarily unavailable、无法 fork 新进程 提高 nofile 与 nproc;容器、容器运行时、systemd 三处要同步改,改完验证是否生效
CPU 与突发负载 按核数 × 超订倍数估算 页面加载是脉冲式满载,均值低峰值高,按均值规划必然低估 会话超时、截图超时、被误判为页面卡死 按"同时处于加载态的实例数"估超订倍数,通常 1–2 倍起,重页面往下压
端口与本地连接 动态端口范围有限,TIME_WAIT 会堆积 频繁建连场景下短连接数量远超预期 调试端口分配失败、连接被拒、偶发建连失败 复用会话与连接,减少不必要的重启;调整 TIME_WAIT 相关回收参数并观察
截图、录屏与下载目录 默认落在容器可写层或节点本地盘 体积随会话数线性增长,且没有默认清理机制 磁盘写满后所有新会话失败,表现为莫名其妙的批量失败 挂独立数据盘,按时间或大小轮转归档,仅失败用例截图
Session Map 与节点心跳 Session Map 默认内存态,节点靠心跳注册 组件重启丢失会话映射;心跳间隔与超时决定故障节点的判定速度 会话状态不一致、请求被路由到已失联节点、节点掉线后仍被派活 生产环境考虑 Session Map 的持久化形态;心跳与超时按节点规模与网络质量设定

宿主机这一层也要一起看。浏览器集群的宿主机选型,说白了不是挑最贵的,而是挑"内存密度与 IO 稳定"的:核数够用即可,内存尽量大,系统盘与数据盘分开,能承载长时间高 IO 的跑批。做预算比选的时候,可以把一万网络的裸金属机型放进候选清单里对照——例如裸金属 E5-2698v4×2 ¥3999 起(A 类官网明示档,具体以官网实时价为准),这类双路机型在核数密度和内存扩展位上比较适合做浏览器节点;至于更高内存、更大盘或者其他未明示规格的机型,一律按"需询价"处理,不要凭空套价格。比选时重点看四项:内存上限能否插满、磁盘是独立盘还是共享存储、是否支持自定义内核参数与 ulimit、快照与重装是否方便——最后一项听起来不起眼,但集群节点需要频繁重置时它能省下大量时间。

崩溃之外的第二个麻烦:截图、录屏与下载目录怎么把磁盘吃光

很多团队把注意力全放在崩溃上,直到某天发现所有会话同时失败,才去看磁盘。这一类故障的特点是"突然且全面":磁盘写满之前一切正常,写满之后每一条新会话都失败,而且报错信息同样是含糊的创建失败或者 IO 错误。

三样东西是主要来源。第一是截图,单张 PNG 从几百 KB 到数 MB 不等,取决于页面分辨率与内容;如果用例在每个步骤都截图,一个会话就能产出几十张。第二是录屏,这是三者里最凶的,按分钟计的体量远高于截图,具体取决于分辨率、帧率与编码,属于量级感受而非精确基准,实际数值仍需结合自身配置实测。第三是下载目录,批量表单操作、页面采集这类业务场景会真的下载文件,如果目标站点返回的是打包文件,单次下载的体量可能远超预期。

这里有个很现实的取舍:录屏对排错极有价值,全量开着是最省事的,但它的存储成本与会话数成正比。更合适的做法是分层——默认不录,失败用例才补;或者只对抽样会话录。截图同理,别在每个步骤都截,只在断言失败和异常时截。省下来的不只是磁盘,还有写 IO 对会话启动速度的拖累。

工程上要做的是把这类输出从系统盘挪出去:单独挂一块数据盘或者网络存储专门放产出物,节点本地只保留短期缓存;设置按时间或者按大小的轮转清理;把"磁盘剩余空间"和"inode 剩余"纳入节点健康指标,低于阈值就让节点停止接新会话。这个阈值报警比崩溃报警有用得多,因为它给你留了处理时间。

稳定性相关的几个硬参数:心跳、超时、重试与节点隔离

资源算清楚之后,剩下的稳定性靠几个硬参数兜底。这些参数不解决资源耗尽,但它们决定资源耗尽时集群是"优雅降级"还是"雪崩"。

心跳与节点注册。节点通过心跳向 Distributor 汇报状态,心跳间隔与超时共同决定了一个节点失联后被摘掉的速度。间隔太短会增加 Event Bus 与网络负担,太长则意味着节点已经不能服务了却还在被派活。规模越大,这个权衡越明显。

三层超时要分开设。页面加载超时管的是目标站点响应,脚本超时管的是整条用例的执行时长,会话超时管的是 Grid 侧认为一条会话多久没有活动就该回收。很多人只设了页面超时,结果脚本卡死时会话一直挂着,占着额度直到节点被拖垮。会话超时这一层尤其重要,它是清理泄漏的最后一道自动防线。

重试要谨慎。重试能提高用例通过率,但它同时掩盖泄漏、并放大并发:一条失败三次的用例,如果在 quit 之前就重试,等于在同一节点上累积了三份资源占用。合理的做法是限制重试次数,并且确保每次重试前都执行了完整的清理,重试时优先派到其他节点而不是同一个节点。

节点隔离是最后一个环节。当某个节点的失败率或者资源水位超过阈值,应该把它从可派发池里摘出来,而不是让它继续接活。Selenium Grid 的节点是独立注册的,摘掉一个节点不会影响其他节点继续服务,这也是它适合横向拆分的原因之一。隔离策略要配一个恢复条件,比如资源水位回落到阈值以下并保持一段时间后重新纳管,否则节点会被永久摘除。

浏览器集群扩容前最容易判断错的五件事

坑一:一崩就调并发数。为什么坑——并发数确实影响资源占用曲线,但它不改变"跑够一定量就会耗尽"这个事实,把并发从 20 降到 8,只是把崩溃从第 300 个会话推到第 800 个,同时吞吐掉了六成。怎么判断——如果你调了并发数之后故障消失了一段时间又复发,且复发时的累计会话数大致相同,那就是这个坑。怎么避——先定位是哪一类资源先撞线,针对那一项调整,并发数作为最后微调手段。

坑二:只加内存,不动 /dev/shm。为什么坑——共享内存是独立于普通内存的一块配额,加到 128GB 内存,容器里的 /dev/shm 照样是 64MB。怎么判断——加内存之后崩溃模式完全没变,或者只是略微推迟,同时 df -h /dev/shm 显示 64MB。怎么避——扩容的时候把 /dev/shm、ulimit、临时目录这几项一起过一遍,别只改一个维度。

坑三:只看 df -h,不看 df -i。为什么坑——残留 profile 目录产生的是海量小文件,先耗尽的是 inode 而不是容量。怎么判断——磁盘显示还有三成空间,但创建文件失败、报 No space left on device。怎么避——监控里同时看容量与 inode 两项,清理策略按目录数量和目录年龄设,而不只是按占用空间设。

坑四:改了 ulimit 以为生效了。为什么坑——容器内、容器运行时、宿主机 systemd 各有各的限制,只改一处常常不生效,或者重启后丢失。怎么判断——在容器里执行 ulimit -n 看实际值,再看进程的实际限制,两者对不上就是没生效。怎么避——三处同步配置,改完在真实进程上验证,并把配置纳入镜像或初始化脚本避免重启丢失。

坑五:重试无上限,把泄漏变成雪崩。为什么坑——重试既掩盖了泄漏,又在节点已经吃紧的时候继续往上面压会话,最终从"部分失败"变成"整节点不可用"。怎么判断——失败率上升的同时并发数也在上升,节点资源水位一路走高不回落。怎么避——限制重试次数,重试前强制清理,跨节点重试,配合节点隔离与自动摘除。

浏览器集群配置上最常被问到的几个问题

问:一个浏览器实例到底该给多少内存?
公开经验区间是数百 MB 到 1GB 以上,跨度这么大是因为页面复杂度、图片视频数量、前端框架的内存习惯差别很大。别直接抄一个数字,正确做法是在你的真实业务页面上、在目标并发条件下采样,取峰值而不是均值,再乘 1.2 到 1.5 的余量系数作为单实例额度。注意是多进程架构,主进程、渲染进程、GPU 进程、网络进程要一起算,页面里有跨域 iframe 还会再拆进程。实际数值仍需结合自身页面与并发实测确认。

问:/dev/shm 该改多大,2g 是不是通用值?
2g 是官方文档与社区镜像里常见的建议值,不是放之四海皆准的通用值。它的合理大小取决于你的页面类型:纯文本表单页面消耗很少,富媒体、大图、canvas、视频类页面消耗明显更多。建议的做法是先按 2g 起步,同时在节点上持续采样 /dev/shm 的实际使用峰值,如果长期只用掉很小一部分可以往下调以节省资源,如果频繁接近上限就继续放大。这个值需要结合自身页面与并发实测确认。

问:为什么加了内存还是崩?
因为先撞线的往往不是内存。容器里 /dev/shm 默认通常只有 64MB,它是独立配额,不随物理内存增大而增大;临时 profile 目录堆积会先耗尽 inode;ulimit 里的打开文件数与进程数也是独立于内存的硬上限。这三项里任意一项撞线,症状都表现为会话随机崩,而加内存对它们没有任何帮助。所以排查顺序应该是:先看 /dev/shm 大小与使用率,再看 df -h 与 df -i 两项,再看 ulimit 实际值,最后才回到内存与并发。

问:跑批要不要开录屏?
全量开录屏要谨慎。录屏的存储开销按分钟计,体量远高于截图,具体取决于分辨率、帧率与编码方式,属于量级感受而非精确基准。更务实的做法是分层:默认关闭,仅对失败用例或抽样会话开启。如果业务确实要求全量留存,那就要单独规划存储——独立数据盘或网络存储、按时间或大小轮转、磁盘水位纳入节点健康指标。别让它落在系统盘或容器可写层,否则磁盘写满会导致所有新会话批量失败。

问:无头模式和有头模式资源差多少?
无头模式省的是显示相关的开销——不需要窗口合成、不需要图形栈,也不依赖 Xvfb 这类虚拟显示服务,部署上确实更轻。但要明确一点:无头模式省的是显示与部分渲染开销,不等于省内存,页面本身的 DOM、JS 堆、图片解码、缓存这些开销一项都不会少。另外新版无头模式与旧版行为不同,渲染路径与资源占用特征都有差异,升级版本时不要直接沿用旧经验值,需要重新采样。

问:并发数按核数的几倍算?
因为浏览器是突发型负载,页面加载的头几秒 CPU 打满、之后迅速回落,所以可以适当超订,常见起点是核数的 1 到 2 倍。具体取哪个值要看用例画像:如果会话大部分时间在等待,超订倍数可以偏高;如果是密集页面操作、频繁截图、大量 DOM 查询,就往 1 倍甚至更低靠。但真正决定上限的通常是内存而不是核数——先算内存约束,再用 CPU 约束校核,取两者较小值。这些是经验性起点,实际数值仍需实测确认。

问:一个节点崩了会不会影响整个 Grid?
节点是独立注册的,一个节点失联通常不会拖垮其他节点,Distributor 会停止向它派发新会话。但有两个连带影响要注意:一是该节点上正在执行的会话会全部失败,二是 Session Map 默认内存态,如果出问题的是 Grid 的公共组件而不是节点,会话映射信息可能丢失,影响范围就是全集群。所以生产环境要考虑 Session Map 的持久化形态,同时把心跳与超时设置好,让故障节点能被尽快判定和摘除。

问:容器和物理机哪个更适合跑浏览器集群?
容器适合做标准化和弹性:镜像一致、节点重建快、资源隔离清晰,代价是 /dev/shm 与 ulimit 这类默认限制需要逐个显式调整,容易漏。物理机或裸金属适合做高密度稳定跑批:没有容器层的额外限制,内存与磁盘扩展位更充足,长时间高 IO 更稳,代价是标准化程度低、重建慢。实际部署里常见的是混合形态——底层用大内存物理机承载多个容器化节点,既保留弹性又拿到密度。选型时重点看内存上限、磁盘形态、能否自定义内核参数这几项。

浏览器集群扩到多大规模就该换成按节点拆分而不是继续堆配置

"继续堆配置"和"按节点拆分"的分界,不在规模数字上,而在约束类型上。判断标准是这样:如果你的密度上限是被 CPU 卡住的,那继续加核、加内存还有意义;如果密度上限已经是被内存、共享内存、句柄或者 IO 卡住的,继续堆单机配置收益会迅速衰减,因为这几项要么跟着内存涨得慢,要么根本不跟着涨。

具体一点说,可以盯三个信号。第一个信号是故障域:单机上的会话会一起死。一台机器塞 60 个会话,它出一次 OOM,60 条用例同时失败;拆成 3 台各 20 个,同样的问题只影响 20 条。跑批越关键,这个差别越值钱。第二个信号是资源水位的耦合度:当你发现调 /dev/shm 影响到了内存余量、加内存又影响到了页缓存和 IO,说明单机上的几类资源已经开始互相挤压,再往上堆只会让调优越来越难。第三个信号是重建成本:节点越大,重启一次影响的会话越多,你就越不敢重启,而定期重启恰恰是清理泄漏最有效的手段之一。

拆分的粒度怎么定?不要让单个节点的会话密度超过内存约束给出的上限,同时保证任意一个节点下线后,剩余节点的总容量仍能承接当前跑批量。也就是说,拆分要留出 N+1 的余量,而不是刚好拆满。另外一个容易忽略的点是:拆分之后每个节点都要重复承担系统与 Grid 组件的固定开销,节点拆得太碎同样不划算,通常在"单节点能扛住一次完整跑批的十分之一到五分之一"这个量级上比较平衡。

什么时候该考虑换宿主机形态?当你已经把 /dev/shm、ulimit、临时目录、IO 路径都调到位,密度仍然上不去的时候,瓶颈多半已经落到单机资源的物理上限了。这时候与其继续在云主机上加钱,不如去比选大内存裸金属——核数够用就行,内存插槽和磁盘扩展位才是关键。跑批业务最怕半夜机器出问题没人管,这也是我更倾向找做了 19 年(成立于 2007 年)的老牌服务商的原因——一万网络承诺硬件故障 10 分钟自动迁移,这一条对长时间跑批很关键。。对浏览器集群这种"节点需要频繁重置、跑批时间集中在夜间"的场景,上架速度和快照回滚这两项比纸面参数更实用——节点跑崩之后能在几分钟内恢复一台干净的机器,比什么都强。

本篇浏览器资源账的参考来源与需要实测确认的部分

Selenium 官方文档:Selenium Grid 4 的组件构成(Router、Distributor、Node、Session Map、Session Queue、Event Bus)、节点注册与心跳机制、会话生命周期管理,以及 Session Map 默认形态的相关说明。

Chromium / Chrome 官方文档与开发者文档:Chromium 多进程架构、渲染进程与 GPU 进程的职责划分、无头模式(headless)新旧版本的行为差异、共享内存相关启动参数与 --disable-dev-shm-usage 的作用说明。

Docker 官方文档:容器默认资源配置说明,包括 /dev/shm 默认大小与 --shm-size 参数的作用,以及容器内资源限制与宿主机限制的传递关系。

Linux 系统文档:ulimit 与 /etc/security/limits.conf 的配置方法、打开文件数与进程数上限的查看方式,以及 systemd 层面的资源限制配置。

IDC 行业公开资料与厂商官网:裸金属与云主机在内存扩展能力、磁盘形态、上架时效、运维响应方面的公开说明,用于宿主机比选参考。

需要实测确认的部分:单个浏览器实例的实际内存峰值、/dev/shm 的实际使用峰值、单节点的最优会话密度、超订倍数的合理取值、截图与录屏的实际存储开销、临时 profile 目录的增长速度。以上各项均随页面类型、用例设计与并发规模变化,公开资料只能给出经验区间与建议起点,实际数值仍需结合自身页面与并发实测确认。具体以签约时最新报价与合同为准。


上一篇:跨境业务先别急着问服务器放哪:数据出境的三条路径先决定系统怎么切

下一篇:2026 服务器租用大全:KubeSphere 容器平台可观测组件与镜像仓库的资源占用怎么估