连接Cloud SQL实例时出现NoClassDefFoundError及连接超时问题求助
连接Cloud SQL实例时遇到初始化失败及连接超时问题
问题描述
尝试将服务连接至Cloud SQL实例时,触发java.lang.NoClassDefFoundError: Could not initialize class com.blacklight.common.DBManager错误,底层报错为连接超时导致的通信链路故障。
DBManager类代码
package com.blacklight.common; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; @WebListener("Initialize db upon initialization of application context") public class DBManager implements ServletContextListener { private static final Logger LOGGER = LoggerFactory.getLogger(DBManager.class); private static final Object dataSourceLock = new Object(); private static DataSource dataSource = null; static { dataSource = initDataSource(); } private static DataSource initDataSource() { synchronized (dataSourceLock) { try { String username = "aaaa"; String password = "bbbb"; String driverName = "com.mysql.jdbc.Driver"; String instance = "project-Id:location:database-name"; if (dataSource == null) { HikariConfig config = new HikariConfig(); config.setUsername(username); config.setPassword(password); config.setJdbcUrl("jdbc:mysql:///Features"); config.setUsername(username); config.setPassword(password); config.setDriverClassName(driverName); config.setConnectionInitSql("SET NAMES 'utf8mb4'"); config.addDataSourceProperty("socketFactory","com.google.cloud.sql.mysql.SocketFactory"); config.addDataSourceProperty("cloudSqlInstance", instance); config.addDataSourceProperty("characterEncoding", "UTF-8"); config.addDataSourceProperty("useUnicode", "true"); // config.addDataSourceProperty("noAccessToProcedureBodies", "true"); config.addDataSourceProperty("useSSL", "true"); config.addDataSourceProperty("ipTypes", "PRIVATE,PUBLIC"); config.setMaximumPoolSize(50); config.setMinimumIdle(5); config.setConnectionTimeout(10000); config.setIdleTimeout(600000); config.setMaxLifetime(1800000); dataSource = new HikariDataSource(config); } return dataSource; } catch (Exception e) { System.out.println("Error"); LOGGER.error(e.getMessage(), e); } throw new RuntimeException("Couldn't initialize datasource"); } } public static Connection getConnection() throws SQLException { if (dataSource == null) { dataSource = initDataSource(); } return dataSource.getConnection(); } @Override public void contextInitialized(ServletContextEvent event) { dataSource = initDataSource(); } @Override public void contextDestroyed(ServletContextEvent event) { if (dataSource != null) { ((HikariDataSource) dataSource).close(); } } }
错误日志(中文翻译)
com.blacklight.common.DBManager initDataSource: 初始化连接池失败:通信链路故障 最后一次成功向服务器发送数据包是在0毫秒前,驱动未收到来自服务器的任何数据包。 com.zaxxer.hikari.pool.HikariPool$PoolInitializationException: 初始化连接池失败:通信链路故障 最后一次成功向服务器发送数据包是在0毫秒前,驱动未收到来自服务器的任何数据包。 at com.zaxxer.hikari.pool.HikariPool.throwPoolInitializationException(HikariPool.java:596) at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:582) at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:81) at com.blacklight.common.DBManager.initDataSource(DBManager.java:71) at com.blacklight.common.DBManager.<init>(DBManager.java:26) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.eclipse.jetty.server.handler.ContextHandler$StaticContext.createInstance(ContextHandler.java:2902) at org.eclipse.jetty.servlet.ServletContextHandler$Context.createInstance(ServletContextHandler.java:1299) at org.eclipse.jetty.server.handler.ContextHandler$StaticContext.createListener(ContextHandler.java:2913) at org.eclipse.jetty.servlet.ListenerHolder.doStart(ListenerHolder.java:94) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73) at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:369) at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1449) at com.google.apphosting.runtime.jetty94.AppEngineWebAppContext.startWebapp(AppEngineWebAppContext.java:274) at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1414) at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:916) at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:288) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:524) at com.google.apphosting.runtime.jetty94.AppEngineWebAppContext.doStart(AppEngineWebAppContext.java:218) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73) at com.google.apphosting.runtime.jetty94.AppVersionHandlerFactory.doCreateHandler(AppVersionHandlerFactory.java:207) at com.google.apphosting.runtime.jetty94.AppVersionHandlerFactory.createHandler(AppVersionHandlerFactory.java:125) at com.google.apphosting.runtime.jetty94.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:82) at com.google.apphosting.runtime.jetty94.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:176) at com.google.apphosting.runtime.RequestRunner.dispatchServletRequest(RequestRunner.java:264) at com.google.apphosting.runtime.RequestRunner.dispatchRequest(RequestRunner.java:229) at com.google.apphosting.runtime.RequestRunner.run(RequestRunner.java:194) at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:273) at java.lang.Thread.run(Thread.java:750) 原因:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 通信链路故障 最后一次成功向服务器发送数据包是在0毫秒前,驱动未收到来自服务器的任何数据包。 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.jdbc.Util.handleNewInstance(Util.java:408) at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1117) at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:350) at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2416) at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2450) at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2235) at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:818) at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.jdbc.Util.handleNewInstance(Util.java:408) at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:404) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:307) at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:364) at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206) at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:476) at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ... 31 more 根本原因:java.net.ConnectException: 连接超时(连接超时) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:607) at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:293) at sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:173) at com.google.cloud.sql.core.CoreSocketFactory.createSslSocket(CoreSocketFactory.java:275) at com.google.cloud.sql.core.CoreSocketFactory.connect(CoreSocketFactory.java:229) at com.google.cloud.sql.core.CoreSocketFactory.connect(CoreSocketFactory.java:188) at com.google.cloud.sql.mysql.SocketFactory.connect(SocketFactory.java:41) at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:300)
排查与解决步骤
校验Cloud SQL实例配置与权限
- 确认
cloudSqlInstance参数值为正确格式:项目ID:区域:实例名,替换代码中的占位符为实际信息 - 确保应用运行环境的服务账号拥有
Cloud SQL Client角色权限,可在IAM控制台配置 - 若应用部署在非App Engine环境,需将应用所在IP加入Cloud SQL实例的授权网络列表
- 确认
检查依赖包兼容性
- 确认已引入
com.google.cloud.sql:mysql-socket-factory依赖,版本需与MySQL驱动、Cloud SDK适配 - 替换旧版MySQL驱动:将
com.mysql.jdbc.Driver改为com.mysql.cj.jdbc.Driver(适配MySQL 8.0+),同时升级驱动版本至兼容Socket Factory的版本
- 确认已引入
优化代码初始化逻辑
- 删除静态代码块中的数据源初始化:类加载阶段执行初始化易受上下文未就绪影响,仅保留
contextInitialized方法内的初始化逻辑 - 移除重复的
config.setUsername和config.setPassword调用,避免冗余配置 - 调整连接池参数:将
maximumPoolSize从50下调至10-20,匹配实际并发需求,减少资源占用
- 删除静态代码块中的数据源初始化:类加载阶段执行初始化易受上下文未就绪影响,仅保留
调整连接配置
- 若使用MySQL 8.0+,设置
useSSL=false(Cloud SQL Socket Factory已处理加密连接),或添加requireSSL=true - 移除
ipTypes=PRIVATE,PUBLIC配置,默认Socket Factory会自动选择最优连接路径
- 若使用MySQL 8.0+,设置
内容的提问来源于stack exchange,提问作者Sahil
相关产品推荐
相关产品推荐

