以编程方式在Spring Boot应用程序中重新启动HikariPool怎么做?

huangapple go评论106阅读模式
英文:

Programmatically restart HikariPool in Spring Boot application?

问题

我有一个使用Hibernate和HikariDataSource / HikariPool与数据库交互的Spring Boot应用程序。

应用程序中的一个特殊功能会触发数据库重新启动。目前这会导致HikariPool中的连接中断:

Caused by: org.postgresql.util.PSQLException: ERROR: relation "relation_which_really_exists" does not exist
Position: 113
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2532)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2267)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:312)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:448)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:369)

应用程序的旧版本确实以编程方式调用了org.hibernate.SessionFactory.close();,这会导致HikariDataSource / HikariCP的重新启动:

2020-08-17T11:36:42.628Z [qtp1340328248-76] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
2020-08-17T11:36:42.698Z [qtp1340328248-76] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.
2020-08-17T11:36:51.266Z [qtp1340328248-12] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-2 - Starting...
2020-08-17T11:36:51.515Z [qtp1340328248-12] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-2 - Start completed.

我想做同样的事情,但如何在我的应用程序中以编程方式重新启动连接池呢?我看到过像这样的东西:https://stackoverflow.com/questions/25063995/spring-boot-handle-to-hibernate-sessionfactory 获取sessionFactory的句柄,也许类似的方法可以获取DataSource或CP的句柄...但是强制关闭/重新启动这些对象是否安全?Spring Boot上下文是否设计成能够正确处理此类操作?

可能有一些HikariCP配置参数,我可以开始尝试,以尝试达到相同的最终结果,但复制旧实现似乎是最简单/最容易理解的,并且最有可能达到相同的最终结果。

英文:

I have a Spring Boot application which uses Hibernate, and HikariDataSource / HikariPool to talk to the database.

A special feature in the app triggers database restart. Currently this breaks the connections in HikariPool:

Caused by: org.postgresql.util.PSQLException: ERROR: relation "relation_which_really_exists" does not exist
Position: 113
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2532)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2267)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:312)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:448)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:369)

Old version of the app does call programmatically org.hibernate.SessionFactory.close(); which causes restart of HikariDataSource / HikariCP:

2020-08-17T11:36:42.628Z [qtp1340328248-76] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
2020-08-17T11:36:42.698Z [qtp1340328248-76] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.
2020-08-17T11:36:51.266Z [qtp1340328248-12] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-2 - Starting...
2020-08-17T11:36:51.515Z [qtp1340328248-12] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-2 - Start completed.

I would like to do the same, but how can I programmatically restart the connection pool in my app? I've seen things like https://stackoverflow.com/questions/25063995/spring-boot-handle-to-hibernate-sessionfactory to get a handle to sessionFactory, and maybe something similar to get a handle to DataSource or CP....but is it OK to close / restart those objects violently, is the Spring Boot context designer to handle such action properly?

There's probably some HikariCP configuration parameters that I can start to experiment with to try reach the same end result, but replicating the old implementation tempts as the easiest / most figured out and most probable to reach same end result.

答案1

得分: 7

经过一些研究,发现可以通过以下方式获取HikariCP的句柄,并触发连接驱逐:

HikariDataSource hikariDs = (HikariDataSource) dataSource;
HikariPoolMXBean poolBean = hikariDs.getHikariPoolMXBean();
poolBean.softEvictConnections();
英文:

After some study, found out that you can get handle of HikariCP and trigger connection eviction by:

    HikariDataSource hikariDs = (HikariDataSource) dataSource;
    HikariPoolMXBean poolBean = hikariDs.getHikariPoolMXBean();
    poolBean.softEvictConnections();

答案2

得分: 1

HikariCP中有一个参数叫做connectionTestQuery
这是在从池中获取连接之前将被执行的查询,以验证与数据库的连接是否仍然有效。因此,我认为您可以使用它来检查连接是否仍然存活,然后进行必要的操作。但他们在文档中提到:“如果您的驱动程序支持JDBC4,强烈建议不要设置此属性。这适用于不支持JDBC4 Connection.isValid() API的“遗留”驱动程序”。

英文:

There is a parameter in HikariCP which is connectionTestQuery
This is the query that will be executed just before a connection is given to you from the pool to validate that the connection to the database is still alive. So I think you can use it to check if the connection is still alive or not and then force things. But they mention this in the documentation "If your driver supports JDBC4 we strongly recommend not setting this property. This is for "legacy" drivers that do not support the JDBC4 Connection.isValid() API"

答案3

得分: 0

以下是翻译好的内容:

有以下几种可能性。

  1. 确保在配置中提供 allowPoolSuspension。
  2. 确保使用 Hikari 版本 4 或更高。

重置凭据:-

HikariDataSource ds = (HikariDataSource) applicationContext.getBean("dataSource");
HikariPoolMXBean hikariPoolMXBean = ds.getHikariPoolMXBean();
if (hikariPoolMXBean != null) {

    hikariPoolMXBean.softEvictConnections();

}
ds.setUsername(userName);
ds.setPassword(password);
英文:

There are following possiblties.

  1. make sure allowPoolSuspension is available in configuration.
  2. make sure hikari version 4 or above.

reset credential:-

HikariDataSource ds = (HikariDataSource) applicationContext.getBean("dataSource");
HikariPoolMXBean hikariPoolMXBean = ds.getHikariPoolMXBean();
if (hikariPoolMXBean != null) {

    hikariPoolMXBean.softEvictConnections();
	
}ds.setUsername(userName);ds.setPassword(password);

答案4

得分: 0

正如Rajesh和Janne所提到的,softEvictConnections()方法将关闭池中的连接。
这个方法调用将“轻轻地”从池中逐出所有空闲连接,并且**标记活动连接在返回池时尽快被逐出。**这意味着没有正在进行的事务会突然终止,但所有连接最终都会被关闭和替换。

if(datasource instanceof HikariDataSource) {
    ((HikariDataSource) datasource).getHikariPoolMXBean().softEvictConnections();
}
英文:

As Rajesh, Janne mentioned, the softEvictConnections() method will close the connections in the pool.
This method call will "softly" evict all idle connections from the pool and mark active connections to be evicted as soon as they return to the pool. This means no abrupt termination of ongoing transactions, but all connections will eventually be closed and replaced.

if(datasource instanceof HikariDataSource) {
    ((HikariDataSource) datasource).getHikariPoolMXBean().softEvictConnections();
}

huangapple
  • 本文由 发表于 2020年8月17日 22:03:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/63452495.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定