Selenium 容器会话卡住时如何避免 RemoteWebDriver 创建阻塞?
结论
可以为 Selenium Java 客户端的 HTTP 请求设置连接超时和读取超时,限制 RemoteWebDriver 构造时等待 Selenium 服务端响应的时间。构造函数会同步请求远端创建 WebDriver 会话;如果服务端没有响应,调用会一直停在 new RemoteWebDriver(...),直到请求超时或返回。
客户端超时只能让 Spring Boot 调用方停止等待,不能确认 Selenium 容器中的浏览器或会话已经清理。如果容器确实卡住,还需要通过 Selenium Grid 管理会话,或重启容器恢复服务。
在创建 RemoteWebDriver 时设置超时
Selenium Java 4 的 ClientConfig 可以设置 HTTP 连接超时和读取超时。将原来的构造语句替换为带 ClientConfig 的重载即可:
import java.net.URL;
import java.time.Duration;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.http.ClientConfig;
// containerLocator 已由 driverSocket 转换得到
ChromeOptions options = new ChromeOptions();
ClientConfig clientConfig = ClientConfig.defaultConfig()
.connectionTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(45));
RemoteWebDriver driver = new RemoteWebDriver(
containerLocator,
options,
clientConfig
);
示例中的 10 秒和 45 秒需要根据容器启动浏览器、创建会话所需的时间调整。连接超时控制客户端等待建立连接的时长,读取超时控制客户端等待服务端响应的时长。具体可用的构造函数和行为与项目使用的 Selenium Java 版本有关,请核对项目依赖中的 API。
创建失败时,应捕获异常并记录远端地址和错误信息,不能把异常当作可用的 driver 返回。构造函数未成功返回时,调用方还没有拿到 driver 对象,因此超时后不要继续调用 driver.getSessionId()。
超时后检查并恢复容器
客户端超时不代表远程会话已经取消。服务端可能还在处理创建请求,也可能已创建会话,只是响应没有送达客户端。可以根据部署方式检查 Selenium 容器日志和 Grid 状态,并清理已知的遗留会话。若容器无法恢复,重启容器可以清除其中的会话,但也会中断该容器上的其他任务。
多个异步任务共用一个 Selenium 容器时,应限制并发创建数量,并避免多个任务同时清理或重启同一容器。否则,超时重试可能增加排队请求,或产生重复会话。
确保正常结束时调用 quit
driver 创建成功后,应在 finally 中执行清理。这样即使解析过程抛出异常,也会尝试结束会话:
RemoteWebDriver driver = createDriver();
try {
doParsingTask(driver, sessionId);
} finally {
if (driver != null) {
driver.quit();
}
}
这种方式可以处理应用代码异常退出的情况,但无法应对进程被强制终止、网络中断或 Selenium 容器失去响应。遇到这些情况,仍需通过 Grid 或容器层面的监控与恢复来处理。
Selenium 官方 Java API 提供了接受 ClientConfig 的 RemoteWebDriver 构造函数。相关说明见 RemoteWebDriver API 和 ClientConfig API。
备注:内容仅供参考。
