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 不关闭连接,也许这是一个错误,您应该 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 使用的连接池将在初始 运行.

后关闭