Looking around for a connection pool solution on App Engine, with Cloud SQL, multiple entries show up with the suggestion that HikariCP should work because it allows for an external ThreadFactory configuration. For example;
- JDBC connection pool compatible with App Engine
- Connection pool on app engine with Cloud SQL
The configuration would be something like this:
import com.google.appengine.api.ThreadManager;
...
HikariConfig lConfig = new HikariConfig();
config.setThreadFactory(ThreadManager.backgroundThreadFactory());
...
But there are problems;
HikariCP on Google App Engine
And indeed, a quick attempt exposed multiple problems due to App Engine's restricted "sandbox" environment.
So the question remains; did someone successfully implement HikariCP on Google App Engine?
Yes i've implemented HikariCP on Google App Engine, but there are some considerations;
Google App Engine uses three types and instance classes;
- Automatic Scaling
- Basic Scaling
- Manual Scaling
Only the types Basic and Manual Scaling allow background threads and are therefore the only candidates for use with HikariCP.
I've used Basic Scaling which is no problem with a approximately known user base (for example one company for each deployed instance). This type enables some other nice features like session support and a powerful B8 instance (1024 MB / 4.8 GHz).
For most of my applications i prefer one powerful initialized instance above multiple instances.
Property threadFactory is only available via programmatic configuration, so i implemented my own connection provider;
public class MyConnectionProvider implements ConnectionProvider, Configurable, Stoppable
{
...
public void configure(Map props) throws HibernateException
{
try
{
mHikariConfig = HikariConfigurationUtil.loadConfiguration(props);
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Production)
{
mHikariConfig.setDriverClassName("com.mysql.jdbc.GoogleDriver");
mHikariConfig.setJdbcUrl("jdbc:google:mysql://project-xxx:database/xxx");
mHikariConfig.setThreadFactory(ThreadManager.backgroundThreadFactory());
}
else
{
mHikariConfig.setDriverClassName("com.mysql.jdbc.Driver");
mHikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/xxx");
}
mHikariConfig.addDataSourceProperty("databaseName", "xxx");
mHikariConfig.setUsername("USERNAME");
mHikariConfig.setPassword("PASSWD");
mHikariConfig.setRegisterMbeans(false);
mHikariConfig.setMaximumPoolSize(12);
mHikariConfig.addDataSourceProperty("cachePrepStmts", "true");
mHikariConfig.addDataSourceProperty("useServerPrepStmts", "true");
mHikariConfig.addDataSourceProperty("prepStmtCacheSize", "250");
mHikariConfig.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
mHikariDataSource = new HikariDataSource(mHikariConfig);
}
catch (Exception e)
{
throw new HibernateException(e);
}
}
...
}
The database name is already in the JdbcUrl but i had to specify it again.
Another important configuration setting is
mHikariConfig.setRegisterMbeans(false);
this disables the on App Engine's restricted java management extensions.