Утечка соединения 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-запроса в вашем сервисе.

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