Загрузочное приложение 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, будет отключен после первоначального запуска.
- Проблема GitHub, связанная с этим изменением: https://github.com/spring-projects/spring-boot/issues/13832
- Привод пружинного башмака (см.
12. Liquibase
: https://docs.spring.io/spring-boot/docs/2.0.6.RELEASE/actuator-api/html/
Я не знаю, почему liquibase не закрывает соединение, возможно, это ошибка, и вы должны создать для этого проблему.
Чтобы установить пул соединений для liquibase, вы должны создать собственный источник данных и пометить его как @LiquibaseDataSource
аннотаций.
Связанные проблемы предоставляют больше деталей: