Selenium Grid执行测试遇请求转发超时问题求助
解决Selenium Grid请求转发超时及节点离线问题
环境信息
- ChromeDriver版本:123.0.6312.58
- Chrome浏览器版本:123.0.6312.59
- selenium-webdriver版本:3.6.0
- Selenium Server版本:3.6.0
启动命令
Hub启动命令
java -jar selenium-server-standalone-3.6.0.jar -role hub
Node启动命令
java -Dwebdriver.chrome.driver=/usr/local/bin/chromedriver -jar selenium-server-standalone-3.6.0.jar -role node -hub http://localhost:4444
测试代码
const {By, Builder, Browser, until} = require('selenium-webdriver'); const assert = require("assert"); const chrome = require('selenium-webdriver/chrome'); const chromeDriverPath = '/usr/local/bin/chromedriver'; const options = new chrome.Options(); options.addArguments("--remote-allow-origins=*"); options.setChromeBinaryPath(chromeDriverPath); (async function firstTest() { let driver; try { driver = await new Builder().forBrowser(Browser.CHROME).setChromeOptions(options).usingServer('http://localhost:4444/wd/hub').build(); await driver.get('https://www.selenium.dev/selenium/web/web-form.html'); let title = await driver.getTitle(); assert.equal("Web form", title); await driver.manage().setTimeouts({implicit: 500}); let textBox = await driver.findElement(By.name('my-text')); let submitButton = await driver.findElement(By.css('button')); await textBox.sendKeys('Selenium'); await submitButton.click(); let message = await driver.findElement(By.id('message')); let value = await message.getText(); assert.equal("Received!", value); } catch (e) { console.log(e) } finally { await driver.quit(); } }())
问题现象
- Hub日志显示节点注册后很快被标记为离线,但Node日志显示注册成功
- 运行测试脚本后报错:
node test.js WebDriverError: Error forwarding the new session Error forwarding the request Connect to 10.32.40.97:5555 [/10.32.40.97] failed: Operation timed out at Object.checkLegacyResponse (/Users/zakjonat/seleniumStackOverflow/node_modules/selenium-webdriver/lib/error.js:546:15) at parseHttpResponse (/Users/zakjonat/seleniumStackOverflow/node_modules/selenium-webdriver/lib/http.js:509:13) at /Users/zakjonat/seleniumStackOverflow/node_modules/selenium-webdriver/lib/http.js:441:30 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) From: Task: WebDriver.createSession() at thenableWebDriverProxy.createSession (/Users/zakjonat/seleniumStackOverflow/node_modules/selenium-webdriver/lib/webdriver.js:769:24) at thenableWebDriverProxy.createSession (/Users/zakjonat/seleniumStackOverflow/node_modules/selenium-webdriver/chrome.js:761:15) at createDriver (/Users/zakjonat/seleniumStackOverflow/node_modules/selenium-webdriver/index.js:170:33) at Builder.build (/Users/zakjonat/seleniumStackOverflow/node_modules/selenium-webdriver/index.js:626:16) at firstTest (/Users/zakjonat/seleniumStackOverflow/test.js:21:131) at Object.<anonymous> (/Users/zakjonat/seleniumStackOverflow/test.js:54:2) at Module._compile (node:internal/modules/cjs/loader:1267:14) at Module._extensions..js (node:internal/modules/cjs/loader:1321:10) at Module.load (node:internal/modules/cjs/loader:1125:32) at Module._load (node:internal/modules/cjs/loader:965:12) { remoteStacktrace: '' } /Users/zakjonat/seleniumStackOverflow/test.js:52 await driver.quit(); ^ TypeError: Cannot read properties of undefined (reading 'quit') at firstTest (/Users/zakjonat/seleniumStackOverflow/test.js:52:18) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) Node.js v20.0.0
解决方案
1. 修复版本兼容性问题
Selenium 3.6.0是2017年的旧版本,完全不支持Chrome 123这类高版本浏览器,必须升级组件:
- 将
selenium-webdriver升级到4.19.0及以上版本(适配Chrome 123的最低兼容版本) - 替换Selenium Server为Selenium Grid 4.x,推荐使用独立模式(无需分开启动Hub和Node):
java -jar selenium-server-4.19.0.jar standalone
2. 解决节点网络可达性问题
Hub标记节点离线,核心原因是Hub无法访问Node的服务端口(默认5555):
- 启动Node时显式指定
--host为本地回环地址或0.0.0.0,同时固定端口避免冲突:java -Dwebdriver.chrome.driver=/usr/local/bin/chromedriver -jar selenium-server-standalone-3.6.0.jar -role node -hub http://localhost:4444 --host 127.0.0.1 --port 5555 - 若为跨机器部署,需确保Hub所在机器能ping通Node的IP,且端口未被防火墙拦截。
3. 修正测试代码错误
- 代码中
options.setChromeBinaryPath(chromeDriverPath)是错误用法:该方法用于设置Chrome浏览器可执行文件路径,而非ChromeDriver路径,正确写法是通过ServiceBuilder指定ChromeDriver路径:const service = new chrome.ServiceBuilder(chromeDriverPath).build(); options.setChromeService(service); - finally块中需先判断driver是否初始化成功,再执行quit:
finally { if (driver) { await driver.quit(); } }
4. 适配Node.js版本
Node.js 20.0.0与旧版selenium-webdriver 3.6.0存在兼容性问题,建议:
- 降级Node.js到16.x LTS版本,或直接升级selenium-webdriver到4.x版本(推荐后者)
最终调整后的测试代码(适配Selenium 4.x)
const {By, Builder, Browser} = require('selenium-webdriver'); const assert = require("assert"); const chrome = require('selenium-webdriver/chrome'); const chromeDriverPath = '/usr/local/bin/chromedriver'; (async function firstTest() { let driver; try { const service = new chrome.ServiceBuilder(chromeDriverPath).build(); const options = new chrome.Options(); options.addArguments("--remote-allow-origins=*"); driver = await new Builder() .forBrowser(Browser.CHROME) .setChromeOptions(options) .setChromeService(service) .usingServer('http://localhost:4444/wd/hub') .build(); await driver.get('https://www.selenium.dev/selenium/web/web-form.html'); const title = await driver.getTitle(); assert.equal("Web form", title); await driver.manage().setTimeouts({implicit: 500}); const textBox = await driver.findElement(By.name('my-text')); const submitButton = await driver.findElement(By.css('button')); await textBox.sendKeys('Selenium'); await submitButton.click(); const message = await driver.findElement(By.id('message')); const value = await message.getText(); assert.equal("Received!", value); } catch (e) { console.error(e); } finally { if (driver) { await driver.quit(); } } }())
内容的提问来源于stack exchange,提问作者Jonathan
相关产品推荐
相关产品推荐

