Reputation: 289
When deploying a Spring Boot application using HikariCP as the connection pool on Appengine, I get some errors related to database (threads), when performing some requests:
Caused by: java.sql.SQLNonTransientConnectionException: Could not create connection to database server.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:1008)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:825)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:455)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:207)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:136)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:369)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:198)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:467)
at com.zaxxer.hikari.pool.HikariPool.access$100(HikariPool.java:71)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:706)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:692)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
... 1 more
Caused by: com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call memcache.Get in a thread that is neither the original request thread nor a thread created by ThreadManager
Then I discovered that AppEngine only allow applications to create threads using its ThreadFactory. So I made sure to configure my Hikari to use AppEngine's Thread factory like the following :
DataSource ds = new HikariDataSource();
try {
final HikariConfig dataSourceConfig = new HikariConfig();
dataSourceConfig.setDriverClassName(applicationProperties.getDatasource()
.getDriverClassName());
dataSourceConfig.setJdbcUrl(applicationProperties.getDatasource()
.getUrl());
dataSourceConfig.setUsername(applicationProperties.getDatasource()
.getUsername());
dataSourceConfig.setPassword(applicationProperties.getDatasource()
.getPassword());
dataSourceConfig.setRegisterMbeans(false);
if (Objects.equal(ProfileResolver.getActiveCloudPlatform(env), ProfileConstants.SPRING_PROFILE_GCP)) {
log.info("[GCP] Set 'com.google.appengine.api.ThreadManager.backgroundThreadFactory()' "
+ "as the instance of the java.util.concurrent.ThreadFactory");
dataSourceConfig.setThreadFactory(ThreadManager.backgroundThreadFactory());
}
ds = new HikariDataSource(dataSourceConfig);
} catch (final Exception e) {
throw new IllegalStateException(e);
}
return ds;
It works on my local appengine (DevServer), But when deployed I get an exception at datasource initialisation, since Appengine's autoscaling modules doesn't allow the use of Background threads.
Is it possible to keep the "autoscaling" ability while using HikariCP on AppEngine ?
Upvotes: 1
Views: 751
Reputation: 3565
The Java 8 runtime doesn't have the same restrictions around threads like prior versions of App Engine. For example, this sample app uses HikariCP to connect to Cloud SQL, and works without a custom thread manager.
Upvotes: 0