I moved my project to HikariCP. Everything is going fine so far, but with one setting I'm having trouble.
It's the .setMaxLifetime(30*1000)
setting in HikariConfig object. I get this warning
WARN com.zaxxer.hikari.HikariConfig - maxLifetime is less than 120000ms, using default 1800000ms.
I know that they recommend not setting is that low as I am trying to. But Unfortunately due to circumstances that I can not change, every TCP connection that is open longer than 50 secods will be terminated in our production environment.
"HikariCP is solid high-performance JDBC connection pool. A connection pool is a cache of database connections maintained so that the connections can be reused when future requests to the database are required.
// maxLifetime is the maximum possible lifetime of a connection in the pool. Connections that. // live longer than this many milliseconds will be closed and reestablished between uses. This. // value should be several minutes shorter than the database's timeout value to avoid unexpected.
Hikari is a JDBC DataSource implementation that provides a connection pooling mechanism. Compared to other implementations, it promises to be lightweight and better performing.
spring.datasource.hikari.maxLifetime: This property controls the maximum lifetime of a connection in the pool. An in-use connection will never be retired, only when it is closed will it then be removed. The minimum allowed value is 30000ms (30 seconds).
i don't know your HikariCP
Version, but in the version 2.2.4 you will find the reason why it will throw the above warning.
HikariConfig.class
(in the com.zaxxer.hikari.HikariConfig
):
private void More ...validateNumerics()
{
Logger logger = LoggerFactory.getLogger(getClass());
if (connectionTimeout == Integer.MAX_VALUE) {
logger.warn("No connection wait timeout is set, this might cause an infinite wait.");
}
if (minIdle < 0 || minIdle > maxPoolSize) {
minIdle = maxPoolSize;
}
if (maxLifetime < 0) {
logger.error("maxLifetime cannot be negative.");
throw new IllegalArgumentException("maxLifetime cannot be negative.");
}
else if (maxLifetime > 0 && maxLifetime < TimeUnit.SECONDS.toMillis(120)) {
logger.warn("maxLifetime is less than 120000ms, using default {}ms.", MAX_LIFETIME);
maxLifetime = MAX_LIFETIME;
}
if (idleTimeout != 0 && idleTimeout < TimeUnit.SECONDS.toMillis(30)) {
logger.warn("idleTimeout is less than 30000ms, using default {}ms.", IDLE_TIMEOUT);
idleTimeout = IDLE_TIMEOUT;
}
else if (idleTimeout > maxLifetime && maxLifetime > 0) {
logger.warn("idleTimeout is greater than maxLifetime, setting to maxLifetime.");
idleTimeout = maxLifetime;
}
from this code, the maxLifeTime is at least 120000ms, using default 1800000ms. so you can't set the maxLifeTime
to 30000ms(30*1000). I guess your HikariCP
version is at least older than 2.2.4.
But when you find the latest HikariCP
version 2.7.4. it said "We strongly recommend setting this value, and it should be at least 30 seconds less than any database or infrastructure imposed connection time limit."
the same class HikariConfig.class
:
private void validateNumerics() {
if(this.maxLifetime != 0L && this.maxLifetime < TimeUnit.SECONDS.toMillis(30L)) {
LOGGER.warn("{} - maxLifetime is less than 30000ms, setting to default {}ms.", this.poolName, Long.valueOf(MAX_LIFETIME));
this.maxLifetime = MAX_LIFETIME;
}
if(this.idleTimeout + TimeUnit.SECONDS.toMillis(1L) > this.maxLifetime && this.maxLifetime > 0L) {
LOGGER.warn("{} - idleTimeout is close to or more than maxLifetime, disabling it.", this.poolName);
this.idleTimeout = 0L;
}
if(this.idleTimeout != 0L && this.idleTimeout < TimeUnit.SECONDS.toMillis(10L)) {
LOGGER.warn("{} - idleTimeout is less than 10000ms, setting to default {}ms.", this.poolName, Long.valueOf(IDLE_TIMEOUT));
this.idleTimeout = IDLE_TIMEOUT;
}
if(this.leakDetectionThreshold > 0L && !unitTest && (this.leakDetectionThreshold < TimeUnit.SECONDS.toMillis(2L) || this.leakDetectionThreshold > this.maxLifetime && this.maxLifetime > 0L)) {
LOGGER.warn("{} - leakDetectionThreshold is less than 2000ms or more than maxLifetime, disabling it.", this.poolName);
this.leakDetectionThreshold = 0L;
}
if(this.connectionTimeout < 250L) {
LOGGER.warn("{} - connectionTimeout is less than 250ms, setting to {}ms.", this.poolName, Long.valueOf(CONNECTION_TIMEOUT));
this.connectionTimeout = CONNECTION_TIMEOUT;
}
if(this.validationTimeout < 250L) {
LOGGER.warn("{} - validationTimeout is less than 250ms, setting to {}ms.", this.poolName, Long.valueOf(VALIDATION_TIMEOUT));
this.validationTimeout = VALIDATION_TIMEOUT;
}
if(this.maxPoolSize < 1) {
this.maxPoolSize = this.minIdle <= 0?10:this.minIdle;
}
if(this.minIdle < 0 || this.minIdle > this.maxPoolSize) {
this.minIdle = this.maxPoolSize;
}
}
from this code, the maxLifeTime
has been updated to 30000ms at least in this version.
So now please update your HikariCP
version to the latest version 2.7.4 if you want to set maxLifeTime to 30000ms.
But if you update your HikariCP version to 2.7.4 with JDK 8, i also recommend you two points:
1. to set maxLifeTime
value to be at least 30000ms.
2. to set maxLifeTime
value few minute less than mysql's wait_timeout
(show variables like "%timeout%"
) to avoid broken connection exception.
Using Hikari version 2.7.9 and I made the following settings:
HikariConfig cpConfig = new HikariConfig();
cpConfig.setJdbcUrl(jdbcUrl);
cpConfig.setUsername(username);
cpConfig.setPassword(password);
cpConfig.setMaximumPoolSize(15);
cpConfig.setConnectionTestQuery("SELECT 1");
// performance senstive settings
cpConfig.setMinimumIdle(0);
cpConfig.setConnectionTimeout(30000);
cpConfig.setIdleTimeout(35000);
cpConfig.setMaxLifetime(45000);
cpConfig.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
HikariDataSource cpDatasource = new HikariDataSource(cpConfig);
localContainerEntityManagerFactoryBean.setDataSource(cpDatasource);
localContainerEntityManagerFactoryBean.setJpaProperties(jpaProperties);
localContainerEntityManagerFactoryBean.afterPropertiesSet();
and it works. But please be careful with:
cpConfig.setMinimumIdle(0);
If your DB e.g. like MSSQL has infinite MaxLifetime this has to be set strictly to 0 or else you will have many connections not closed infinitely (indefinitely)
Cheers,
Artanis Zeratul
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With