强制 Hikari/Hibernate 关闭陈旧的(泄露的?)连接
Force Hikari/Hibernate to close stale (leaked?) connections
我正在使用 Hibernate 5.3 和 Hikari 2.7 在 Spring Boot 2 中通过 the official JDBC driver 使用 FileMaker 16 数据源。
FileMaker 服务器性能较差,SQL 大表的查询执行时间可达一分钟。有时它会导致连接泄漏,当连接池充满了从未释放的活动连接时。
问题是如何强制池中已挂起两分钟的活动连接关闭,将它们移至空闲状态并可供再次使用。
例如,我使用 org.springframework.data.repository.PagingAndSortingRepository
中的 findAll
方法通过 RestController 访问 FileMaker 数据源:
@RestController
public class PatientController {
@Autowired
private PatientRepository repository;
@GetMapping("/patients")
public Page<Patient> find(Pageable pageable) {
return repository.findAll(pageable);
}
}
在原始文件中多次调用 /patients
会导致连接泄漏,这是 Hikari 报告的内容:
2018-09-20 13:49:00.939 DEBUG 1 --- [l-1 housekeeper]
com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Pool stats
(total=10, active=10, idle=0, waiting=2)
它也会抛出这样的异常:
java.lang.Exception: Apparent connection leak detected
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128) ~[HikariCP-2.7.9.jar!/:na]
我需要的是,如果 repository.findAll
花费的时间超过 N 秒,则必须终止连接并且控制器方法必须抛出异常。如何实现?
这是我的 Hikari 配置:
allowPoolSuspension.............false
autoCommit......................true
catalog.........................none
connectionInitSql...............none
connectionTestQuery............."SELECT COUNT(*) FROM Clinics"
connectionTimeout...............30000
dataSource......................none
dataSourceClassName.............none
dataSourceJNDI..................none
dataSourceProperties............{password=<masked>}
driverClassName................."com.filemaker.jdbc.Driver"
healthCheckProperties...........{}
healthCheckRegistry.............none
idleTimeout.....................600000
initializationFailFast..........true
initializationFailTimeout.......1
isolateInternalQueries..........false
jdbc4ConnectionTest.............false
jdbcUrl.........................jdbc:filemaker://***:2399/ec_data
leakDetectionThreshold..........90000
maxLifetime.....................1800000
maximumPoolSize.................10
metricRegistry..................none
metricsTrackerFactory...........none
minimumIdle.....................10
password........................<masked>
poolName........................"HikariPool-1"
readOnly........................false
registerMbeans..................false
scheduledExecutor...............none
scheduledExecutorService........internal
schema..........................none
threadFactory...................internal
transactionIsolation............default
username........................"CHC"
validationTimeout...............5000
HikariCP 只关注连接池管理,以管理它从中形成的连接。
loginTimeout
- HikariCP 等待与数据库建立连接的时间(基本上是 JDBC 连接)
spring.datasource.hikari.connectionTimeout=30000
maxLifetime
- 连接在关闭前在池中存活多长时间
spring.datasource.hikari.maxLifetime=1800000
idleTimeout
- 未使用的连接在池中存在多长时间
spring.datasource.hikari.idleTimeout=30000
如果请求超过定义的超时时间,请使用 javax.persistence.query.timeout 取消请求。
javax.persistence.query.timeout(长-毫秒)
The javax.persistence.query.timeout hint defines how long a query is
allowed to run before it gets canceled. Hibernate doesn’t handle this
timeout itself but provides it to the JDBC driver via the JDBC
Statement.setTimeout method.
filemaker JDBC 驱动程序忽略 javax.persistence.query.timeout
参数,即使在 java.sql.setQueryTimeout
setter 的驱动程序实现中设置了超时值。因此,我通过扩展 class com.filemaker.jdbc.Driver
并覆盖 connect
方法解决了这个问题,以便将 sockettimeout
参数添加到连接属性。有了这个参数,如果在超时期间没有数据来自套接字,FM JDBC 驱动程序会中断连接。
我还向 filemaker 提交了一个问题:https://community.filemaker.com/message/798471
我正在使用 Hibernate 5.3 和 Hikari 2.7 在 Spring Boot 2 中通过 the official JDBC driver 使用 FileMaker 16 数据源。
FileMaker 服务器性能较差,SQL 大表的查询执行时间可达一分钟。有时它会导致连接泄漏,当连接池充满了从未释放的活动连接时。
问题是如何强制池中已挂起两分钟的活动连接关闭,将它们移至空闲状态并可供再次使用。
例如,我使用 org.springframework.data.repository.PagingAndSortingRepository
中的 findAll
方法通过 RestController 访问 FileMaker 数据源:
@RestController
public class PatientController {
@Autowired
private PatientRepository repository;
@GetMapping("/patients")
public Page<Patient> find(Pageable pageable) {
return repository.findAll(pageable);
}
}
在原始文件中多次调用 /patients
会导致连接泄漏,这是 Hikari 报告的内容:
2018-09-20 13:49:00.939 DEBUG 1 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Pool stats (total=10, active=10, idle=0, waiting=2)
它也会抛出这样的异常:
java.lang.Exception: Apparent connection leak detected
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128) ~[HikariCP-2.7.9.jar!/:na]
我需要的是,如果 repository.findAll
花费的时间超过 N 秒,则必须终止连接并且控制器方法必须抛出异常。如何实现?
这是我的 Hikari 配置:
allowPoolSuspension.............false
autoCommit......................true
catalog.........................none
connectionInitSql...............none
connectionTestQuery............."SELECT COUNT(*) FROM Clinics"
connectionTimeout...............30000
dataSource......................none
dataSourceClassName.............none
dataSourceJNDI..................none
dataSourceProperties............{password=<masked>}
driverClassName................."com.filemaker.jdbc.Driver"
healthCheckProperties...........{}
healthCheckRegistry.............none
idleTimeout.....................600000
initializationFailFast..........true
initializationFailTimeout.......1
isolateInternalQueries..........false
jdbc4ConnectionTest.............false
jdbcUrl.........................jdbc:filemaker://***:2399/ec_data
leakDetectionThreshold..........90000
maxLifetime.....................1800000
maximumPoolSize.................10
metricRegistry..................none
metricsTrackerFactory...........none
minimumIdle.....................10
password........................<masked>
poolName........................"HikariPool-1"
readOnly........................false
registerMbeans..................false
scheduledExecutor...............none
scheduledExecutorService........internal
schema..........................none
threadFactory...................internal
transactionIsolation............default
username........................"CHC"
validationTimeout...............5000
HikariCP 只关注连接池管理,以管理它从中形成的连接。
loginTimeout
- HikariCP 等待与数据库建立连接的时间(基本上是 JDBC 连接)
spring.datasource.hikari.connectionTimeout=30000
maxLifetime
- 连接在关闭前在池中存活多长时间
spring.datasource.hikari.maxLifetime=1800000
idleTimeout
- 未使用的连接在池中存在多长时间
spring.datasource.hikari.idleTimeout=30000
如果请求超过定义的超时时间,请使用 javax.persistence.query.timeout 取消请求。
javax.persistence.query.timeout(长-毫秒)
The javax.persistence.query.timeout hint defines how long a query is allowed to run before it gets canceled. Hibernate doesn’t handle this timeout itself but provides it to the JDBC driver via the JDBC Statement.setTimeout method.
filemaker JDBC 驱动程序忽略 javax.persistence.query.timeout
参数,即使在 java.sql.setQueryTimeout
setter 的驱动程序实现中设置了超时值。因此,我通过扩展 class com.filemaker.jdbc.Driver
并覆盖 connect
方法解决了这个问题,以便将 sockettimeout
参数添加到连接属性。有了这个参数,如果在超时期间没有数据来自套接字,FM JDBC 驱动程序会中断连接。
我还向 filemaker 提交了一个问题:https://community.filemaker.com/message/798471