Утечка соединения jdbcTemplate с базой данных postgresql в Spring Boot - PullRequest
0 голосов
/ 16 мая 2018

Похоже, у моего сервиса утечка соединения с базой данных. Вчера после перераспределения я упомянул, что было 27 открытых соединений с базой данных postgres. Этим утром им исполняется 60 лет.

Выполняя этот запрос к моей базе данных, я вижу, что время последнего использования некоторых соединений было только вчера.

SELECT * FROM pg_stat_activity
ORDER BY state_change DESC

enter image description here

Кажется, что мой 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 Ответ

0 голосов
/ 22 мая 2018

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

Если запрос в базу данных postgres из моей службы отправляется, и возникает какая-то проблема с сетью, соединение остается активным. Через некоторое время достигается максимальное количество активных подключений, и служба больше не может подключаться к базе данных.

В качестве обходного пути, в то время как источник проблем с сетью не найден, чтобы избежать отключения сервиса после некоторого времени работы, я настроил RemoveAbandoned проверку в моем configureDataSource методе

configuredDataSource.getPoolProperties().setRemoveAbandonedTimeout(300);
configuredDataSource.getPoolProperties().setRemoveAbandoned(true);

Это проверит, что соединение в активном состоянии не превышает 5 минут, если это так, соединение будет считаться разорванным и будет закрыто. Не забудьте убедиться, что RemoveAbandonedTimeout должно быть больше, чем самое длительное время выполнения любого SQL-запроса в вашем сервисе.

...