ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Selenium Grid 4实战指南:分布式测试部署与踩坑记录

Selenium Grid 4实战指南:分布式测试部署与踩坑记录 1. 为什么需要Selenium Grid先聊聊单机测试的瓶颈第一次听到Selenium Grid这个词时我正被一套“跑不完”的回归测试折磨得够呛。项目里维护了三百多条用例全部串行执行要跑将近两个小时每次发版前跑一遍开发等得暴躁测试也没时间分析真正的失败用例。后来试过在自己的笔记本上开线程池强行并发结果Chrome一多机器风扇狂转用例不是这里超时就是那里找不到元素最后连失败原因是代码问题还是环境问题都分不清。真正切换到Selenium Grid做分布式测试之后这套状况才彻底改观。我接触到的很多测试同学对Grid的第一印象是“这玩意儿要维护Hub和Node太重了”。这个刻板印象并不全对——从Selenium 4开始Grid的架构已经发生了很大的变化部署成本比想象中低得多尤其是配合Docker之后一个docker-compose命令就能起一套支持并行执行的浏览器集群。这篇文章我就用自己的实际落地经验把Selenium Grid的部署、代码接入、并发设计和踩坑记录都捋一遍。适合已经会用Selenium写脚本、但一直没用上分布式执行、或者用了但总出各种诡异问题的人。1.1 串行执行的成本不该被忽视先算一笔简单的账。假设你的回归用例有200条每条平均耗时30秒那么串行跑一遍大概需要100分钟。如果每天需要回归三次光执行时间就是5个小时。人力和CI资源被大量占用不说测试结果出来得晚就意味着缺陷被发现的时机也晚。你可能觉得这是“测试本来就慢”但你换个角度想这200条用例之间往往并没有严格的先后依赖它们只是被动地在一个进程里排队执行而已。早期项目里我试过用JUnit的线程池直接并行两个线程、四个线程都试过。小规模的时候确实快了不少但一旦线程数超过8本机就扛不住了。Chrome每个进程吃内存非常凶开6到8个浏览器实例时16GB内存的机器已经开始卡顿。更麻烦的是并发跑的时候浏览器之间会互相干扰偶发的等待超时、元素定位失败变多最终你很难判断失败到底来自代码还是环境。所以串行执行TA的痛点不只是“慢”还有对机器资源的不合理使用。单机多线程之所以不靠谱是因为它的瓶颈从执行时间转移到了CPU、内存和浏览器稳定性上。分布式执行的意义就是把这些负担分摊到多台机器、多个独立的浏览器进程上去。1.2 本地线程池方案解决的假并发有些人会反驳用线程池不行那用Jenkins多Job并行跑或者用TestNG/Pytest的进程级并行是不是就够了这些方案确实能让用例跑得快一些但它们本质上是“在同一个节点上抢资源”只是把串行变成了有限并发。TestNG的并行如果配置不当所有线程同时在同一个JVM里创建多个WebDriver实例每个实例都会启动独立浏览器进程内存耗尽只是时间问题。Jenkins多Job并行的问题另有一层——结果聚合很麻烦。10个Job并行跑完你得打开10个HTML报告去分别看哪些用例挂了失败信息撕裂在多个报告里不方便统计也不好对接企业内部的测试平台。而且这种方案的扩展性非常差如果今天需要30并发你得手动创建30个Job明天只想跑10个又得去改配置。1.3 Grid对应的三个典型场景Selenium Grid解决的不是“怎么写测试用例”的问题它解决的是“同一套用例如何跑在很多浏览器或很多机器上”。以我的使用经验来看它主要覆盖三类场景。第一类是并行加速用例量足够大需要把它分散到多个Node上同时跑把执行时间从小时级压到分钟级。第二类是跨浏览器兼容性矩阵同一个应用要在Chrome、Firefox、Edge甚至不同操作系统上验证Grid可以在一次调度里把不同浏览器的请求路由到对应的Node上而不需要测试人员手动切换环境、逐个浏览器跑一遍。第三类是统一执行环境后端开发、前端开发、测试同学的本地环境千奇百怪驱动版本、浏览器版本、屏幕分辨率都不一样把测试统一放到Grid节点上执行能极大减少“在我机器上能过在你机器上就挂”的扯皮。方案优点瓶颈串行执行结果稳定、排错简单执行时间线性增长单机线程池配置简单、见效快内存/CPU受限并发极不稳定Jenkins多Job无需写代码、门槛低报告割裂、扩展性差、维护成本高Selenium Grid横向扩展、结果统一、环境隔离需要部署和维护初期学习成本2. Grid 4架构拆解请求是怎么跑到浏览器节点上的在动手部署之前我建议先理解一下Grid 4的内部结构。这个理解非常重要——很多人部署完发现“节点不见了”“请求超时了”“会话一直排队”其实都是对组件之间的关系没有概念导致的。我尽量用大白话把这套架构讲清楚。2.1 六大组件的分工Selenium Grid 4把传统的Hub拆成了几个职责更单一的组件整体上分六块Router、Distributor、Session Map、Session Queue、Node、Event Bus。Router整个Grid对外暴露的入口所有WebDriver HTTP请求都会打到Router上。它相当于“前台接待”先把请求接下来再看应该转给谁处理。Distributor负责“找能干的Node”。新会话请求来了之后Distributor会根据请求里的Capabilities去匹配哪些Node有能力处理然后分配会话。Session Map维护“当前有哪些会话、会话开在哪个Node上”的映射关系。测试执行过程中后续的命令需要通过Session Map找到具体的Node。Session Queue会话请求的等待队列。当所有Node都忙新请求会先在队列里排队而不是直接报错。Node真正跑浏览器的地方每个Node可以预先注册若干浏览器实例。Event Bus内部的消息总线负责组件之间的异步通信让Router、Distributor、Session Map、Node之间解耦。这些组件在Selenium 4里可以单独启动、单独扩容本质上就是微服务化的改造思路。组件核心职责类比Router所有HTTP请求的入口与路由前台接待Distributor匹配并分配会话给Node调度员Session Map会话与Node的对应关系档案室Session Queue新会话请求排队叫号机Node实际执行浏览器操作干活的工位Event Bus组件间异步消息通信公司内网群2.2 一次完整的分布式测试请求流转理解了组件分工之后流程就很好懂。当你的测试代码里用RemoteWebDriver发了一个POST /session请求链路是请求先打到RouterRouter把这个创建会话的请求放进Session Queue。Distributor从队列里拉取请求然后拿着请求里的Capabilities去匹配可用Node匹配成功就把sessionId返回给客户端。这个sessionId会写入Session Map记录“会话X分配给了Node Y”。在这之后你在测试代码里执行driver.get(url)、findElement这类命令请求依然发给RouterRouter通过Session Map查到会话X在哪台Node上再把命令转发过去执行。这么设计的好处是客户端永远只跟Router通信不需要关心背后到底有几个Node、浏览器到底跑在哪台机器上。这个抽象很关键也让后续Node的扩缩容对测试代码完全透明。2.3 新版架构里Hub去哪儿了用过Grid 3的同学可能会问Hub呢在Grid 4里Hub这个名词已经不存在了它的角色被Router、Distributor、Session Map、Session Queue几个组件共同取代。Grid 3时代所有请求都经过一个Hub转发并发一大Hub本身很容易成为瓶颈而且单点故障会导致整个网格不可用。Grid 4拆开之后Router只负责接收请求Distributor负责分配两个角色可以分别部署、分别扩容降低了单点压力。同时Grid 4的Docker镜像已经把所有组件打包好用docker-compose方式一键就能拉起整套环境。新手不用再像Grid 3时代那样手工下载jar包、配置-role hub或-role node参数部署复杂度大幅下降。有的网友在Stack Overflow上问“Grid 4还需要Hub吗”答案是不需要了。如果看到老教程里还在写selenium-server-standalone-x.x.jar -role hub那基本是Grid 3时代的文章可以直接忽略按Grid 4的方式重新部署。3. Docker部署实战从零搭建一套分布式测试环境下面进入实操环节。我不会讲纯Java jar方式的老路直接推荐用Docker Compose来部署。原因很简单环境隔离、版本可控、扩缩容方便。我自己一开始是用jar包手动部署的后来切到Docker之后光部署时间就从半小时缩短到几分钟出了问题也可以直接把容器删了重新拉镜像敢折腾了。3.1 为什么优先用Docker而不是jar包Grid 3时代的部署方式需要自己去下载Selenium Server jar还需要本地装好Java环境再分别启动Hub和Node。Node上要装对应版本的浏览器和driver每台机器都得手动配置一遍维护成本很高。Docker方式的好处是浏览器、driver、Selenium组件全部打包在镜像里Node要扩容时只要docker compose scale node-chrome5一条命令就多出5个浏览器节点。有人会担心容器里的浏览器没有图形界面跑不了复杂的交互测试。这个不用担心Selenium官方镜像默认用Xvfb虚拟显示浏览器照常渲染只是不显示在你的桌面上。如果需要看浏览器实际操作过程可以设置环境变量开启VNC用VNC客户端连接对应Node的5900端口实时查看。唯一的硬性前提是执行Docker的机器要有足够的内存和CPU这一点后面“资源规划”那节我再详细算。3.2 Compose配置逐段解析我提供一个可用的docker-compose配置模板。你可以直接复制把镜像版本号换成当前最新的Selenium版本即可。version: 3.8 services: event-bus: image: selenium/event-bus:4.25.0 container_name: grid-event-bus ports: - 5557:5557 networks: - grid restart: unless-stopped router: image: selenium/router:4.25.0 container_name: grid-router ports: - 4444:4444 depends_on: - event-bus environment: - SE_EVENT_BUS_HOSTevent-bus - SE_EVENT_BUS_PUBLISH_PORT4442 - SE_EVENT_BUS_SUBSCRIBE_PORT4443 networks: - grid restart: unless-stopped distributor: image: selenium/distributor:4.25.0 container_name: grid-distributor depends_on: - event-bus environment: - SE_EVENT_BUS_HOSTevent-bus - SE_EVENT_BUS_PUBLISH_PORT4442 - SE_EVENT_BUS_SUBSCRIBE_PORT4443 networks: - grid restart: unless-stopped session-map: image: selenium/session-map:4.25.0 container_name: grid-session-map depends_on: - event-bus environment: - SE_EVENT_BUS_HOSTevent-bus - SE_EVENT_BUS_PUBLISH_PORT4442 - SE_EVENT_BUS_SUBSCRIBE_PORT4443 networks: - grid restart: unless-stopped session-queue: image: selenium/session-queue:4.25.0 container_name: grid-session-queue depends_on: - event-bus environment: - SE_EVENT_BUS_HOSTevent-bus - SE_EVENT_BUS_PUBLISH_PORT4442 - SE_EVENT_BUS_SUBSCRIBE_PORT4443 networks: - grid restart: unless-stopped node-chrome: image: selenium/node-chrome:4.25.0 container_name: grid-node-chrome shm_size: 2gb ports: - 5900:5900 depends_on: - event-bus environment: - SE_EVENT_BUS_HOSTevent-bus - SE_EVENT_BUS_PUBLISH_PORT4442 - SE_EVENT_BUS_SUBSCRIBE_PORT4443 - SE_NODE_MAX_SESSIONS1 networks: - grid restart: unless-stopped volumes: - /dev/shm:/dev/shm这个配置里有几个细节值得单独说。第一所有组件都放在自定义的grid网络里容器之间通过服务名互相访问不需要暴露内部端口到宿主机。对外只需要暴露Router的4444端口和Event Bus的5557端口。Node的5900端口用于VNC调试如果不需要实时看浏览器也可以不映射。第二SE_EVENT_BUS_HOSTevent-bus这几个变量非常关键。新版Grid中Node和各个组件都是通过Event Bus进行注册和通信的只有正确设置了Event Bus的地址和端口节点才能成功注册到Router上。第三/dev/shm挂载和shm_size: 2gb是很重要的。Chrome渲染页面时会把共享内存写满如果容器默认的共享内存太小浏览器会直接崩溃或者报DevToolsActivePort file doesnt exist一类的错误。这个问题在Docker里非常常见提前配好能省不少排查时间。第四SE_NODE_MAX_SESSIONS1表示这个Node容器最多同时执行一个会话。如果要让一个Node容器承载多个会话可以调高它但我更建议通过增加Node容器数量来扩展并发原因后面介绍。3.3 浏览器节点镜像怎么选Selenium官方提供了一系列镜像常见的有selenium/node-chrome、selenium/node-firefox、selenium/node-edge以及把浏览器和Grid组件合并在一起的selenium/standalone-chrome。如果你的场景只是在一台机器上小规模跑用standalone镜像最省事它内置了Router、Distributor和Node。但如果你想横向扩展就要用拆分组件的方式也就是我上面这个compose模板。镜像的版本号要和Selenium客户端版本保持一致或接近。举个例子如果你的Java项目用的是Selenium 4.20Grid镜像建议也用4.20.x版本差距过大可能出现一些协议兼容问题。这个坑我在后面踩坑部分会展开。3.4 启动自检与Grid控制台配置写好后执行命令docker network create grid 2/dev/null || true docker compose up -d所有容器启动后通过docker compose ps查看状态确保没有容器异常退出。然后访问http://localhost:4444/status应该能看到一个JSON格式的响应里面包含Grid总览、节点数量、空闲节点数、会话数等关键信息。再打开http://localhost:4444/ui这是Grid 4自带的网页控制台。Overview页面能看到节点概览Nodes页面能看到每个节点的操作系统、浏览器版本、最大会话数、当前会话数。部分镜像版本里还能直接在UI上看到节点的live view实时显示浏览器画面调试定位问题非常方便。我在第一次部署的时候就吃过一个亏docker compose起来之后立刻去看UI发现只有Router没有Node。其实是因为Node容器启动后需要一点时间完成注册通常几秒到几十秒不等。如果等了30秒以上还没看到Node就要去查Node容器的日志了这个排查过程我在第5章详细讲。4. 让测试真正跑起来RemoteWebDriver的接入与并发设计环境搭好之后接下来的事情就是把原来写好的WebDriver脚本改成走Grid执行。这一步的关键在于理解Capabilities匹配机制和并发参数的设计。4.1 Capabilities匹配逻辑Grid里的Node注册时会声明自己支持哪些能力比如浏览器是Chrome、版本是126.0、平台是Linux、最大会话数是多少。当测试请求带有Capabilities来创建会话时Distributor就会在所有Node里寻找能“匹配”这些能力的节点。最基本的Capabilities包括browserName、browserVersion、platformName。匹配规则可以简单理解为不写版本信息时任何版本都匹配写了版本信息时要以节点上报的版本为准。platformName在跨平台时比较有用比如你有Windows和Linux两类Node就可以通过它来定向分配。Capability作用配置示例browserName指定浏览器chromebrowserVersion指定浏览器版本126.0platformName指定操作系统linuxselenium:options浏览器高级参数如headless、参数、二进制路径{args: [--headless]}这里有个容易忽略的点Chrome的headless模式不会真的“无界面”它照样占用和普通模式差不多的内存和CPU只是不显示窗口。在容器里跑测试时默认的Xvfb已经提供了虚拟显示完全没必要再加--headless参数加了反而可能在某些页面交互逻辑上出现奇怪差异。4.2 代码接入示例Java端非常直接。原来是new ChromeDriver(options)现在改成ChromeOptions options new ChromeOptions(); options.setCapability(browserName, chrome); options.setCapability(platformName, linux); WebDriver driver new RemoteWebDriver( new URL(http://localhost:4444), options );需要注意的是构造URL时会抛出MalformedURLException实际代码里处理一下异常。如果用Python写则更简洁from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.set_capability(browserName, chrome) options.set_capability(platformName, linux) driver webdriver.Remote( command_executorhttp://localhost:4444, optionsoptions )跑起来之后Grid UI的Sessions页面里就能看到这个会话以及它在哪个Node上执行这对于后续判断“用例是不是都压在一个节点上”非常有帮助。4.3 并行策略并发数、节点数和队列之间的关系并行并不是无脑加大线程池。Grid的并发能力由多少个Node决定每个Node的SE_NODE_MAX_SESSIONS决定它能同时跑多少会话。当所有Node的会话额度占满后新的会话请求会进入Session Queue排队等待有Node释放。我做个简单的测算。假设你有5个Node容器每个Node的SE_NODE_MAX_SESSIONS1那么Grid同时能执行5个会话。如果压测任务里开了20个并发线程那么另外15个会排队等待。要不要增加Node取决于你的业务用例单条平均耗时和期望的P95等待时间。从成本角度出发一个Chrome容器至少要预留1.5GB内存加上系统开销和Grid组件本身一台16GB内存的机器撑10个并发会话已经比较紧了。我自己的经验是单Node容器内如果调大SE_NODE_MAX_SESSIONS到4或5每个会话的稳定性会明显下降浏览器实例之间会“抢”CPU和内存一些脚本里偶发超时就会变多。所以优先方式永远是“多Node、低单节点并发”这样每个测试会话环境更独立问题也更可控。4.4 分布式执行下的用例设计要点在Grid上跑用例和本地跑用例写代码的思路有一些差异需要适应。第一用例之间必须绝对独立不能依赖同一个静态变量、同一个用户账号、同一个本地文件。因为你不知道这次执行会被分到哪个Node上上次执行的状态也不会保留。测试数据尽量通过接口去构造或者用独立的测试账号体系避免互相污染。第二测试脚本里不要写死本地路径。比如上传文件、读取测试数据的文件路径在Node容器里很可能不存在。要么把文件放到测试资源里一起传递要么使用临时目录。我在容器里跑用例时经常踩这个坑后来统一用Java的System.getProperty(java.io.tmpdir)或Python的tempfile.gettempdir()去拼接临时路径问题立刻缓解。第三失败重试要考虑。分布式环境下单个Node偶尔出现网络抖动、资源紧张导致超时这并不代表用例本身有问题。所以我在实际项目里会给关键用例加一层重试机制比如TestNG的IRetryAnalyzer或Pytest的pytest-rerunfailures通常重试一次就够了太多会导致执行时间膨胀。5. 分布式环境里最容易踩的六个坑光看官方文档很多问题遇不到、想也想不到。这些坑是我实际用得比较久之后逐渐暴露出来的每一个都带过我走弯路我按“现象-排查-根因-解决”的方式记录下来希望对大家有帮助。5.1 no free slot found并发数超过节点承载上限“No free slot found in the node”是我在压测时遇到最多的一句话。现象就是新会话创建失败日志里明确提示当前没有可用槽位。很多人第一反应是“并发开太大了”其实这是句废话真正要判断的是“并发是否超过了节点规划”。排查时先看Grid UI的Nodes页面查看每个Node的Slots是否被占满、Session Queue是否堆积。如果队列很大说明并发请求确实超过了节点总承载量。这时有两个选择增加Node容器数量或者调高已有Node的SE_NODE_MAX_SESSIONS。我个人优先选择前者因为增加容器数量是水平扩展不牺牲稳定性。这里补充一点如果SE_NODE_MAX_SESSIONS调大了还要确认容器里是否有足够的内存。曾遇到过一个Node容器设置SE_NODE_MAX_SESSIONS6结果跑到第四个会话时浏览器直接崩溃一看监控容器内存耗尽被内核OOM杀掉。调参数前先算内存。5.2 节点注册失败UI上始终看不到Node部署完成后发现Grid UI里只有Router没有Node节点这是很多新手的第一个拦路虎。遇到这个情况我的排查顺序非常固定。第一步docker compose ps确认Node容器还在运行没有启动即退出。第二步查看Node容器的日志docker logs grid-node-chrome。第三部看日志里有没有“Node has been added”或者“registered”这样的关键字。如果没有说明Node根本没有和Event Bus通信成功。最典型的原因是Event Bus的地址或端口配置不对。这个配置不会报错只是节点静默注册失败所以排查起来比较隐蔽。确认SE_EVENT_BUS_HOSTevent-bus这个变量值和compose里服务名一致同时SE_EVENT_BUS_PUBLISH_PORT和SE_EVENT_BUS_SUBSCRIBE_PORT填的是Event Bus容器内部的端口默认4442和4443而不是宿主机映射的端口。有时候把这两个端口照抄成5557就会一直注册不上。5.3 浏览器驱动版本错位session not createdSelenium Grid的Node镜像里已经内置了对应版本的浏览器和driver正常情况下不会出现版本不匹配。但如果你使用了自定义镜像或者公司的私有镜像仓库缓存了老版本镜像就可能遇到“session not created: This version of ChromeDriver only supports Chrome version xxx”这样的报错。排查方式很简单登录到Node容器里执行chromedriver --version和google-chrome --version看两者版本是否对应。Chrome 115以后driver的版本要和Chrome大版本保持一致比如Chrome 126就需要ChromeDriver 126.x。如果发现不一致最省事的解法是删除本地旧镜像重新拉取官方最新版本镜像。不要在Node容器里手动去下载driver因为容器重建之后这些改动就丢了。如果企业环境必须用私有镜像仓库建议写一个自动化流水线定期同步Selenium官方镜像并强制所有节点使用同一版本标签避免“组件4.25、Node镜像4.20”这种混用情况。5.4 会话回收不及时会话泄漏导致资源耗尽测试脚本执行中断或者异常退出时没有调用driver.quit()这是典型的会话泄漏。会话不释放Node的槽位就一直被占用跑着跑着整个Grid就“堵死”了新请求全部排队页面看起来像全线超时。我给团队定了一条规矩WebDriver的创建和关闭必须配对Java用try-with-resources或AfterMethod/AfterTest统一关闭Python用try/finally或with语句。同时Grid自身也有兜底机制节点会在一段时间后自动回收空闲超时的会话相关的时间参数可以通过SE_SESSION_TIMEOUT环境变量控制单位为秒。但这个值不能设得太短否则一些长时间不操作页面的用例会被误杀我一般设置成300秒。5.5 Java版本与Selenium组件不兼容Grid 4的组件基于Java 11构建老项目如果一直用JDK 8直接跑最新版Selenium Grid会报“UnsupportedClassVersionError”。这个错误很好认异常信息里会直接写class file version。解法有两个要么升级JDK到11或17要么用Selenium 3.x的镜像和协议。既然Selenium 3已经停止维护与其迁就老环境不如下决心把JDK升级了。实际升级过程中主要是注意一些老项目用的编译器参数和依赖库是否兼容比如Mockito版本过低在JDK 17下需要换新版本。这个坑和Grid本身关系不大但确实是分布式测试落地时非常常见的环境阻碍。5.6 VNC调试时看到的画面和实际执行不一致Grid的Node容器默认带Xvfb虚拟显示器通过VNC连接容器5900端口能看到浏览器的真实操作过程。但有的时候打开VNC看到的不是当前执行的页面而是一个灰屏或者旧页面。这种现象多半是因为Node容器里同时有多个会话而VNC画面显示的是整个Xvfb桌面不是某个会话的专属视图。如果你只开SE_NODE_MAX_SESSIONS1VNC看到的通常就是当前会话的页面没有问题多个会话共享同一个虚拟桌面时画面就会互相覆盖。想要稳定观察某个会话的执行最可靠的方式还是通过Grid UI上的视频录制功能或者把SE_NODE_MAX_SESSIONS控制在1以观察单个用例为主。6. 上线之后的日常维护扩容、监控与资源规划Grid搭好、用例跑顺之后真正的挑战才开始。分布式环境的日常维护虽然不复杂但没有一套明确的流程出问题时会焦头烂额。我分享一下自己维护过程中的一些经验和建议。6.1 动态扩容与缩容的正确姿势Docker方式下扩容非常灵活。最简单的方式是修改compose文件里的服务数值重新执行docker compose up -ddocker compose up -d --scale node-chrome5这条命令会把node-chrome服务扩展到5个容器实例。注意如果你之前给容器指定过固定的container_name那么scale时会因为容器名冲突而失败因为多个实例不能共享同一个容器名。我上面的模板里给node-chrome写了container_name: grid-node-chrome一旦要scale就得先删掉这个字段。实际生产里大规模扩容更推荐配合Docker Swarm或Kubernetes来做不过对大多数中小团队来说docker compose加脚本已经够用。缩容时同样可以用--scale node-chrome2来降回两个。这里要提醒一句缩容前先确认当前有没有活跃会话跑在这些即将被移除的Node上硬砍容器会导致会话中断。我一般选择在测试任务空窗期做缩容操作先把对应的Node标记为离线等已有会话结束再移除。6.2 监控指标怎么看Grid自带的UI和/status接口能提供一些基础指标包括节点总数、空闲节点数、会话数、排队请求数。我用了一段时间后觉得光盯这些不够心里还是要有一本账。指标来源判断标准节点总数/status与预期Node数一致空闲节点数/status长期为0说明资源吃紧排队请求数/status长期大于0说明并发不足单节点CPU/内存docker statsCPU持续90%以上警惕会话成功率测试报告低于99%需要排查Node稳定性实践中我习惯在CI流水线里加一步跑测试前先获取/status接口判断空闲节点数量是否满足本次任务需要的并发数不够就直接报错提示而不是傻傻地把任务丢进去排队等到超时。这个“前置检查”逻辑非常简单但能省下很多不必要的等待时间。6.3 资源规划我的个人建议最后说说资源规划。很多人一上来就问“我要支持20并发该准备多少台机器”这个问题没有标准答案因为它取决于你的页面复杂度和用例逻辑。我提供一套快速估算的方法。单个Chrome节点的常规内存需求大致在1.5GB到2GB之间如果内容比较复杂3GB也不夸张。Grid核心组件Router、Distributor等加起来大约1GB左右。假设你要支撑20个并发会话按每个Node只跑1个会话来算至少需要20个Node容器总内存需求大约是20乘以2再加上1大致需要41GB以上的空闲内存。所以我们每次上线新项目都会先做压测拿一小批真实用例逐步增加并发数观察Node容器的内存增长曲线和会话成功率以这个数据来做容量规划。单纯靠估算很容易翻车。另外节点的镜像更新也不容忽视。Selenium每发布新版本都会同步推新镜像浏览器版本也会随之更新。我建议每1至2周拉一次最新镜像在预发环境先跑一遍回归确认稳定后再切换到生产节点。这个节奏不算频繁但能确保测试环境不会因为依赖版本过于陈旧而和线上应用脱节。分布式测试这件事技术本身并不复杂复杂的是把它持续稳定地跑起来。Selenium Grid提供了一个很好的基础设施但真正让它发挥价值的是一个团队对测试稳定性、资源成本和执行效率之间平衡的持续关注。
返回列表