Утечка соединения jdbcTemplate с базой данных postgresql в Spring Boot
Кажется, что мой сервис имеет утечку соединения с базой данных. Вчера после перераспределения я упомянул, что к базе данных postgres было открыто 27 соединений. Этим утром им 60 лет.
Выполняя этот запрос к моей базе данных, я вижу, что время последнего использования некоторых соединений было только вчера.
SELECT * FROM pg_stat_activity
ORDER BY state_change DESC
Кажется, что мой jdbcTemplate должен закрыть их, но он этого не сделал.
Вот моя конфигурация
@Configuration
public class DatabaseConfiguration {
// reading data from application properties
// ........
private DataSource configureDataSource(String url, String user, String password, String driverClassName){
DataSource ds = DataSourceBuilder.create()
.url(url)
.username(user)
.password(password)
.driverClassName(driverClassName)
.build();
org.apache.tomcat.jdbc.pool.DataSource configuredDataSource = (org.apache.tomcat.jdbc.pool.DataSource) ds;
configuredDataSource.setTestWhileIdle(connectionTestWhileIdle);
configuredDataSource.setValidationQuery( connectionValidationQuery);
configuredDataSource.setTimeBetweenEvictionRunsMillis(
toIntExact(connectionTimeBetweenEvictionRunsMillis));
return configuredDataSource;
}
@Bean(name = "qaDataSource")
public JdbcTemplate getQaJdbcTemplate() {
DataSource ds = configureDataSource(qaURL, qaUsername, qaPassword ,qaDriverClassName);
return new JdbcTemplate(ds);
}
Есть идеи, что не так с моей конфигурацией? Или, может быть, это неправильная конфигурация базы данных.
1 ответ
Похоже, что после нескольких часов расследований эта утечка соединения вызвана таймаутами http-запросов и другими сетевыми проблемами внутри нашего кластера.
Если мой сервис отправляет запрос в базу данных postgres и возникает проблема с сетью, соединение остается активным. Через некоторое время достигается максимальное количество активных соединений, и служба больше не может подключаться к базе данных.
В качестве обходного пути, пока источник сетевых проблем не найден, чтобы избежать отключения сервиса после некоторого времени работы, которое я настроил RemoveAbandoned
проверка в моем configureDataSource
метод
configuredDataSource.getPoolProperties().setRemoveAbandonedTimeout(300);
configuredDataSource.getPoolProperties().setRemoveAbandoned(true);
При этом будет проверено, что соединение в активном состоянии не превышает 5 минут, если это так, соединение будет считаться разорванным и будет закрыто. Не забудьте убедиться, что RemoveAbandonedTimeout
должно быть больше, чем самое длинное время выполнения любого SQL-запроса в вашем сервисе.