Spring Batch Java应用调用ChromeDriver.quit()触发SocketException警告
Spring Batch集成Selenium时ChromeDriver quit()触发Socket连接重置警告的处理方案
问题场景
在Spring Batch框架的Java应用中使用Selenium,调用ChromeDriver.quit()时会触发onError警告,抛出java.net.SocketException: Connection reset异常;调试模式下不会出现该问题。
相关日志
Starting ChromeDriver 110.0.5481.77 (65ed616c6e8ee3fe0ad64fe83796c020644d42af-refs/branch-heads/5481@{#839}) on port 58642 Only local connections are allowed. Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe. ChromeDriver was started successfully. [1678747030.900][WARNING]: virtual void DevToolsClientImpl::AddListener(DevToolsEventListener *) subscribing a listener to the already connected DevToolsClient. Connection notification will not arrive. [2m2023-03-13 23:37:10.946[0;39m [32m INFO[0;39m [35m15264[0;39m [2m---[0;39m [2m[ null to remote][0;39m [36mo.o.selenium.remote.ProtocolHandshake [0;39m [2m:[0;39m Detected dialect: W3C [2m2023-03-13 23:37:10.993[0;39m [32m INFO[0;39m [35m15264[0;39m [2m---[0;39m [2m[ restartedMain][0;39m [36mo.o.selenium.devtools.CdpVersionFinder [0;39m [2m:[0;39m Found exact CDP implementation for version 110 [2m2023-03-13 23:38:33.789[0;39m [32mDEBUG[0;39m [35m15264[0;39m [2m---[0;39m [2m[ restartedMain][0;39m [36mo.s.b.item.database.JdbcBatchItemWriter [0;39m [2m:[0;39m Executing batch with 1 items. [2m2023-03-13 23:39:19.811[0;39m [32mDEBUG[0;39m [35m15264[0;39m [2m---[0;39m [2m[ restartedMain][0;39m [36mo.s.b.item.database.JdbcBatchItemWriter [0;39m [2m:[0;39m Executing batch with 1 items. [2m2023-03-13 23:39:19.856[0;39m [33m WARN[0;39m [35m15264[0;39m [2m---[0;39m [2m[cHttpClient-1-4][0;39m [36mo.a.netty.handler.WebSocketHandler [0;39m [2m:[0;39m onError java.net.SocketException: Connection reset at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394) ~[na:na] at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426) ~[na:na] at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:258) ~[netty-buffer-4.1.79.Final.jar:4.1.79.Final] at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132) ~[netty-buffer-4.1.79.Final.jar:4.1.79.Final] at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:357) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) ~[netty-transport-4.1.79.Final.jar:4.1.79.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.79.Final.jar:4.1.79.Final] at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.79.Final.jar:4.1.79.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.79.Final.jar:4.1.79.Final] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
原代码示例
System.setProperty("webdriver.chrome.driver", "src\\main\\resources\\chromedriver.exe"); ChromeOptions options = new ChromeOptions(); options.addArguments("--headless=new"); ChromeDriver chromeDriver = new ChromeDriver(options); chromeDriver.get("https://www.google.com/"); //select web items, interact with them chromeDriver.quit();
原因分析
该警告本质是:调用quit()时,ChromeDriver会直接终止Chrome浏览器进程并关闭自身服务,而Selenium底层通过Netty维护的WebSocket连接还未正常断开,客户端仍尝试向已关闭的连接发送请求,从而触发连接重置异常。调试模式下进程退出速度较慢,连接有足够时间正常关闭,因此不会出现该问题。
解决方案
1. 调整资源释放顺序
先关闭浏览器窗口,再停止驱动服务,最后调用quit(),确保连接正常断开:
System.setProperty("webdriver.chrome.driver", "src\\main\\resources\\chromedriver.exe"); ChromeOptions options = new ChromeOptions(); options.addArguments("--headless=new"); ChromeDriver chromeDriver = new ChromeDriver(options); chromeDriver.get("https://www.google.com/"); // 业务逻辑处理 // 调整释放顺序 chromeDriver.close(); // 先关闭窗口 chromeDriver.getSession().getDriverService().stop(); // 停止驱动服务 chromeDriver.quit(); // 最后调用quit
2. 过滤特定日志警告
如果不需要关注该警告,可在日志配置(如logback.xml)中关闭对应日志输出:
<logger name="org.asynchttp.netty.handler.WebSocketHandler" level="OFF"/>
3. 手动管理ChromeDriver生命周期
使用ChromeDriverService手动控制驱动的启动和停止,确保资源正确释放:
ChromeDriverService service = new ChromeDriverService.Builder() .usingDriverExecutable(new File("src\\main\\resources\\chromedriver.exe")) .build(); service.start(); ChromeOptions options = new ChromeOptions(); options.addArguments("--headless=new"); ChromeDriver chromeDriver = new ChromeDriver(service, options); chromeDriver.get("https://www.google.com/"); // 业务逻辑处理 // 释放资源 chromeDriver.quit(); service.stop();
4. 确保Chrome与ChromeDriver版本匹配
版本不兼容可能导致进程异常退出,需保证Chrome浏览器和ChromeDriver的主版本号完全一致,避免因版本差异引发的连接问题。
内容的提问来源于stack exchange,提问作者Genaut
相关产品推荐
相关产品推荐

