Spring 启动应用程序中的 Liquibase 保持 10 个连接打开
Liquibase in Spring boot application keeps 10 connections open
我正在开发一个 Spring 带有 Liquibase 集成的启动应用程序来设置数据库。我们使用不同的用户来更改我们使用 application.properties 文件
配置的数据库
liquibase.user=abc
liquibase.password=xyz
liquibase.url=jdbc:postgresql://something.eu-west-1.rds.amazonaws.com:5432/app?ApplicationName=${appName}-liquibase
liquibase.enabled=true
liquibase.contexts=dev,postgres
我们目前部署了 3 个不同的微服务,我们注意到对于每个 运行 个实例,Liquibase 都会打开 10 个连接,并且它永远不会关闭这些连接,除非我们停止应用程序。这基本上意味着在开发中我们经常会达到 Amazon RDS 实例的连接限制。
目前,在开发中,74 个活动连接中的 40 个被 Liquibase 占用。如果我们想用它投入生产,为所有微服务启用自动缩放,这意味着我们将不得不过度扩展数据库,以免达到任何连接限制。
有没有办法
- 告诉 liquibase 不要使用 10 个连接的连接池
- 告诉 liquibase 停止或关闭连接
到目前为止,我没有找到有关如何执行此操作的文档。
我不知道为什么 liquibase 不关闭连接,也许这是一个错误,您应该 create an issue 为此。
要为 liquibase 设置连接池,您必须创建自定义数据源并使用 @LiquibaseDataSource
注释对其进行标记。
相关问题提供更多细节:
感谢 Slava 的回复,我设法通过以下数据源配置解决了问题 class
@Configuration
public class LiquibaseDataSourceConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(LiquibaseDataSourceConfiguration.class);
@Autowired
private LiquibaseDataSourceProperties liquibaseDataSourceProperties;
@LiquibaseDataSource
@Bean
public DataSource liquibaseDataSource() {
DataSource ds = DataSourceBuilder.create()
.username(liquibaseDataSourceProperties.getUser())
.password(liquibaseDataSourceProperties.getPassword())
.url(liquibaseDataSourceProperties.getUrl())
.driverClassName(liquibaseDataSourceProperties.getDriver())
.build();
if (ds instanceof org.apache.tomcat.jdbc.pool.DataSource) {
((org.apache.tomcat.jdbc.pool.DataSource) ds).setInitialSize(1);
((org.apache.tomcat.jdbc.pool.DataSource) ds).setMaxActive(2);
((org.apache.tomcat.jdbc.pool.DataSource) ds).setMaxAge(1000);
((org.apache.tomcat.jdbc.pool.DataSource) ds).setMinIdle(0);
((org.apache.tomcat.jdbc.pool.DataSource) ds).setMinEvictableIdleTimeMillis(60000);
} else {
// warnings or exceptions, whatever you prefer
}
LOG.info("Initialized a datasource for {}", liquibaseDataSourceProperties.getUrl());
return ds;
}
}
可以在 Tomcat 的站点上找到属性的文档:https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
- initialSize:池启动时创建的初始连接数
- maxActive: 可以同时从此池中分配的最大活动连接数
- minIdle:池中应始终保持的最小已建立连接数
- maxAge:保持此连接的时间(以毫秒为单位)。当连接返回到池中时,池将检查是否已达到 now - time-when-connected > maxAge,如果是,它会关闭连接而不是将其返回到池中。默认值为 0,这意味着连接将保持打开状态,并且在将连接返回到池时不会进行年龄检查。
- minEvictableIdleTimeMillis:对象在有资格被逐出之前可以在池中闲置的最短时间。
所以它似乎不是连接泄漏,它只是数据源的默认配置,这对于 Liquibase 如果您使用专用数据源 不是最佳的。如果 liquibase 数据源是您的主要数据源,我认为这不会成为问题。
更新:这已在 2.5.0-M2 中修复,Liquibase 现在使用 SimpleDriverDataSource
没有连接池。
原始答案:Spring 引导版本 2.0.6.RELEASE
中引入了对连接池管理的更改,并且只有在使用 Spring 引导执行器时才会生效。有一个执行器端点(默认启用),它允许您获取 Liquibase 应用的更改集。为此,Liquibase 保持其数据库连接打开。您可以使用 management.endpoint.liquibase.enabled = false
禁用端点,在这种情况下,Liquibase 使用的连接池将在初始 运行.
后关闭
- GitHub 与此更改相关的问题:https://github.com/spring-projects/spring-boot/issues/13832
- Spring 引导执行器(参见
12. Liquibase
:https://docs.spring.io/spring-boot/docs/2.0.6.RELEASE/actuator-api/html/
我正在开发一个 Spring 带有 Liquibase 集成的启动应用程序来设置数据库。我们使用不同的用户来更改我们使用 application.properties 文件
配置的数据库liquibase.user=abc
liquibase.password=xyz
liquibase.url=jdbc:postgresql://something.eu-west-1.rds.amazonaws.com:5432/app?ApplicationName=${appName}-liquibase
liquibase.enabled=true
liquibase.contexts=dev,postgres
我们目前部署了 3 个不同的微服务,我们注意到对于每个 运行 个实例,Liquibase 都会打开 10 个连接,并且它永远不会关闭这些连接,除非我们停止应用程序。这基本上意味着在开发中我们经常会达到 Amazon RDS 实例的连接限制。
目前,在开发中,74 个活动连接中的 40 个被 Liquibase 占用。如果我们想用它投入生产,为所有微服务启用自动缩放,这意味着我们将不得不过度扩展数据库,以免达到任何连接限制。
有没有办法
- 告诉 liquibase 不要使用 10 个连接的连接池
- 告诉 liquibase 停止或关闭连接
到目前为止,我没有找到有关如何执行此操作的文档。
我不知道为什么 liquibase 不关闭连接,也许这是一个错误,您应该 create an issue 为此。
要为 liquibase 设置连接池,您必须创建自定义数据源并使用 @LiquibaseDataSource
注释对其进行标记。
相关问题提供更多细节:
感谢 Slava 的回复,我设法通过以下数据源配置解决了问题 class
@Configuration
public class LiquibaseDataSourceConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(LiquibaseDataSourceConfiguration.class);
@Autowired
private LiquibaseDataSourceProperties liquibaseDataSourceProperties;
@LiquibaseDataSource
@Bean
public DataSource liquibaseDataSource() {
DataSource ds = DataSourceBuilder.create()
.username(liquibaseDataSourceProperties.getUser())
.password(liquibaseDataSourceProperties.getPassword())
.url(liquibaseDataSourceProperties.getUrl())
.driverClassName(liquibaseDataSourceProperties.getDriver())
.build();
if (ds instanceof org.apache.tomcat.jdbc.pool.DataSource) {
((org.apache.tomcat.jdbc.pool.DataSource) ds).setInitialSize(1);
((org.apache.tomcat.jdbc.pool.DataSource) ds).setMaxActive(2);
((org.apache.tomcat.jdbc.pool.DataSource) ds).setMaxAge(1000);
((org.apache.tomcat.jdbc.pool.DataSource) ds).setMinIdle(0);
((org.apache.tomcat.jdbc.pool.DataSource) ds).setMinEvictableIdleTimeMillis(60000);
} else {
// warnings or exceptions, whatever you prefer
}
LOG.info("Initialized a datasource for {}", liquibaseDataSourceProperties.getUrl());
return ds;
}
}
可以在 Tomcat 的站点上找到属性的文档:https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
- initialSize:池启动时创建的初始连接数
- maxActive: 可以同时从此池中分配的最大活动连接数
- minIdle:池中应始终保持的最小已建立连接数
- maxAge:保持此连接的时间(以毫秒为单位)。当连接返回到池中时,池将检查是否已达到 now - time-when-connected > maxAge,如果是,它会关闭连接而不是将其返回到池中。默认值为 0,这意味着连接将保持打开状态,并且在将连接返回到池时不会进行年龄检查。
- minEvictableIdleTimeMillis:对象在有资格被逐出之前可以在池中闲置的最短时间。
所以它似乎不是连接泄漏,它只是数据源的默认配置,这对于 Liquibase 如果您使用专用数据源 不是最佳的。如果 liquibase 数据源是您的主要数据源,我认为这不会成为问题。
更新:这已在 2.5.0-M2 中修复,Liquibase 现在使用 SimpleDriverDataSource
没有连接池。
原始答案:Spring 引导版本 2.0.6.RELEASE
中引入了对连接池管理的更改,并且只有在使用 Spring 引导执行器时才会生效。有一个执行器端点(默认启用),它允许您获取 Liquibase 应用的更改集。为此,Liquibase 保持其数据库连接打开。您可以使用 management.endpoint.liquibase.enabled = false
禁用端点,在这种情况下,Liquibase 使用的连接池将在初始 运行.
- GitHub 与此更改相关的问题:https://github.com/spring-projects/spring-boot/issues/13832
- Spring 引导执行器(参见
12. Liquibase
:https://docs.spring.io/spring-boot/docs/2.0.6.RELEASE/actuator-api/html/