Загрузочное приложение Liquibase in Spring поддерживает 10 открытых соединений.

Я работаю над приложением Spring Boot с интеграцией 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.

Прямо сейчас, в разработке, 40 из 74 активных соединений заняты Liquibase. Если мы когда-нибудь захотим перейти на работу с этим, имея включенное автоматическое масштабирование для всех микросервисов, это будет означать, что нам придется расширять базу данных, чтобы не нарушать никаких ограничений соединения.

Есть ли способ

  • скажите liquibase, чтобы не использовать пул соединений из 10 соединений
  • скажите liquibase, чтобы остановить или закрыть соединения

До сих пор я не нашел документации о том, как это сделать.

2 ответа

Решение

Благодаря ответу Славы мне удалось решить проблему с помощью следующего класса конфигурации источника данных

@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: время в миллисекундах, чтобы сохранить это соединение. Когда соединение возвращается в пул, пул проверит, было ли достигнуто время - когда подключено> maxAge, и если да, то оно закрывает соединение, а не возвращает его в пул. Значение по умолчанию равно 0, что означает, что соединения будут оставаться открытыми, и проверка возраста не будет выполняться при возврате соединения в пул.
  • minEvictableIdleTimeMillis: минимальный период времени, в течение которого объект может бездействовать в пуле, прежде чем он будет допущен к выселению.

Таким образом, это не похоже на утечку соединения, это просто конфигурация источника данных по умолчанию, которая не оптимальна для Liquibase, если вы используете выделенный источник данных. Я не ожидаю, что это станет проблемой, если ваш источник данных представляет собой источник данных liquibase.

Это изменение в управлении пулом соединений было введено в версии Spring Boot. 2.0.6.RELEASE, и вступает в силу только при использовании Spring Boot Actuator. Существует конечная точка привода (включена по умолчанию), которая позволяет вам получать наборы изменений, применяемые Liquibase. Для этого Liquibase поддерживает соединения с базой данных открытыми. Вы можете отключить конечную точку с помощьюmanagement.endpoint.liquibase.enabled = false, и в этом случае пул соединений, используемый Liquibase, будет отключен после первоначального запуска.

Я не знаю, почему liquibase не закрывает соединение, возможно, это ошибка, и вы должны создать для этого проблему.

Чтобы установить пул соединений для liquibase, вы должны создать собственный источник данных и пометить его как @LiquibaseDataSource аннотаций.

Связанные проблемы предоставляют больше деталей:

Другие вопросы по тегам