Spring Boot JPA - настройка автоматического переподключения


107

У меня есть хорошее маленькое веб-приложение Spring Boot JPA. Он развернут на Amazon Beanstalk и использует Amazon RDS для хранения данных. Однако он используется не так часто и поэтому через некоторое время выходит из строя с таким исключением:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: последний пакет, успешно полученный от сервера, был 79870633 миллисекунды назад.
Последний пакет, успешно отправленный на сервер, был 79 870 634 миллисекунды назад. длиннее, чем заданное сервером значение 'wait_timeout'. Вам следует рассмотреть возможность истечения срока действия и / или проверки действительности соединения перед использованием в вашем приложении, увеличения значений, настроенных сервером для тайм-аутов клиента, или использования свойства соединения Connector / J 'autoReconnect = true', чтобы избежать этой проблемы.

Я не уверен, как настроить этот параметр, и не могу найти информацию о нем на http://spring.io (хотя и очень хороший сайт). Какие идеи или указатели на информацию?


Используйте это, чтобы распечатать DataSourceи проверить его свойства. stackoverflow.com/a/36586630/148844 Spring Boot не будет автоматически настраивать DataSourceфайлы, @Beansкоторые определяют файл DataSource. docs.spring.io/spring-boot/docs/1.5.16.RELEASE/reference/…
Хлоя,

Ответы:


141

Я предполагаю, что загрузка настраивает DataSourceдля вас. В этом случае и поскольку вы используете MySQL, вы можете добавить следующее в свой application.propertiesдо 1.3

spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1

Как было отмечена djxak в комментариях, 1.4+ определяет конкретные пространства имена для четырех соединений бассейнов Пружины загрузка поддерживает: tomcat, hikari, dbcp, dbcp2( dbcpнежелательно 1.5). Вам необходимо проверить, какой пул соединений вы используете, и проверить, поддерживается ли эта функция. Приведенный выше пример был для tomcat, поэтому в 1.4+ вам придется написать его следующим образом:

spring.datasource.tomcat.testOnBorrow=true 
spring.datasource.tomcat.validationQuery=SELECT 1

Следует отметить , что использование autoReconnectявляется не рекомендуется :

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


8
это потому, что мы согласовали способ написания ключей в документации. Мы всегда использовали мягкий переплет, так что и то, spring.datasource.testOnBorrowи другое spring.datasource.test-on-borrowподойдет. Проверьте документацию для получения более подробной информации.
Стефан Николл

17
Поскольку это может сбить с толку других: SELECT 1гарантирует, что соединение было протестировано перед передачей приложению. При использовании testOnBorrow = trueобъекты будут проверяться перед заимствованием из пула. Если объект не прошел проверку, он будет удален из пула и попытается заимствовать другой. ПРИМЕЧАНИЕ - для того, чтобы истинное значение оказало какое-либо влияние, параметр validationQuery должен быть установлен в ненулевую строку.
Рик

14
Предупреждение! Весной ботинке 1.4+ это изменилось : там было определено новые специфические пространства имен для четырех соединений бассейнов пружинных опор: tomcat, hikari, dbcp, dbcp2. Так, например, для tomcat-jdbcпула соединений свойства должны быть: spring.datasource.tomcat.testOnBorrow=trueи spring.datasource.tomcat.validationQuery=SELECT 1.
Руслан Стельмаченко

1
Если я сам настраиваю два разных источника данных, как мне предоставить эту конфигурацию? Нужно ли мне предоставлять эту конфигурацию для обоих источников данных, например spring.datasource.mydatasource1.tomcat.testOnBorrow = true spring.datasource.mydatasource1.tomcat.validationQuery = SELECT 1 spring.datasource.mydatasource2.tomcat.testOnBorrow = true spring.datasource. mydatasource2.tomcat.validationQuery = SELECT 1 Или есть что-то еще, за чем нужно следить ??
Нитиш Кумар

2
Предупреждение! Если вы определите какой-либо DataSource @Bean в своем приложении, то Spring Boot не будет настраивать пул. docs.spring.io/spring-boot/docs/1.5.16.RELEASE/reference/… If you define your own DataSource bean, auto-configuration will not occur. Я следовал руководству по OAuth2, и @Bean(name = "OAuth") public DataSource secondaryDataSource()...он не был автоматически настроен и не использовался testOnBorrow.
Хлоя

28

Приведенные выше предложения не сработали для меня. Что действительно сработало, так это включение следующих строк в application.properties

spring.datasource.testWhileIdle = true
spring.datasource.timeBetweenEvictionRunsMillis = 3600000
spring.datasource.validationQuery = SELECT 1

Вы можете найти объяснение здесь


5
В добавленной вами ссылке говорится, что если соединение с базой данных неактивно более 8 часов, оно автоматически закрывается, и возникает указанная выше ошибка. Итак, ваше решение - не позволять соединению оставаться неактивным в течение длительного времени. Есть ли способ подключиться к серверу SQL после его перезапуска?
Akeshwar Jha

9

Настройка spring.datasource.tomcat.testOnBorrow=trueв application.properties не сработала.

Программные настройки, как показано ниже, работали без каких-либо проблем.

import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;    

@Bean
public DataSource dataSource() {
    PoolProperties poolProperties = new PoolProperties();
    poolProperties.setUrl(this.properties.getDatabase().getUrl());         
    poolProperties.setUsername(this.properties.getDatabase().getUsername());            
    poolProperties.setPassword(this.properties.getDatabase().getPassword());

    //here it is
    poolProperties.setTestOnBorrow(true);
    poolProperties.setValidationQuery("SELECT 1");

    return new DataSource(poolProperties);
}

1
Если вы объявляете собственный источник данных, это может быть связано с тем, что вы пытаетесь использовать Spring по умолчанию .tomcat. Поэтому, если вы создаете пользовательский bean-компонент Datasource, добавьте @ConfigurationProperties (prefix = "spring.datasource.tomcat") к bean-компоненту DataSource, и тогда он должен позволить вам установить их в свойствах приложения. Мой пример .. @Bean (name = "managementDataSource") @ConfigurationProperties (prefix = "management.datasource") public DataSource dataSource () {return DataSourceBuilder.create (). Build (); } management.datasource.test-on-заимствовать = true
Джастин

8

Я только что перешел на Spring Boot 1.4 и обнаружил, что эти свойства были переименованы:

spring.datasource.dbcp.test-while-idle=true
spring.datasource.dbcp.time-between-eviction-runs-millis=3600000
spring.datasource.dbcp.validation-query=SELECT 1

2
Имена эквивалентны. См. Раздел об именовании свойств в документации Spring Boot .
Стивен Харрисон,

@StephenHarrison: обратите внимание на префикс dbcp. *, Добавленный в 1.4, ослабленная привязка в этом случае не применяется.
YM

1
@Pawel: в зависимости от того, какая реализация пула доступна в вашем проекте, это могут быть не свойства dbcp. *, См. Загрузка Spring с SQL и соответствующие свойства источника данных
YM

4

Ответ whoami правильный. Используя предложенные свойства, я не смог заставить это работать (используя Spring Boot 1.5.3.RELEASE)

Я добавляю свой ответ, поскольку это полный класс конфигурации, поэтому он может помочь кому-то, использующему Spring Boot:

@Configuration
@Log4j
public class SwatDataBaseConfig {

    @Value("${swat.decrypt.location}")
    private String fileLocation;

    @Value("${swat.datasource.url}")
    private String dbURL;

    @Value("${swat.datasource.driver-class-name}")
    private String driverName;

    @Value("${swat.datasource.username}")
    private String userName;

    @Value("${swat.datasource.password}")
    private String hashedPassword;

    @Bean
    public DataSource primaryDataSource() {
        PoolProperties poolProperties = new PoolProperties();
        poolProperties.setUrl(dbURL);
        poolProperties.setUsername(userName);
        poolProperties.setPassword(password);
        poolProperties.setDriverClassName(driverName);
        poolProperties.setTestOnBorrow(true);
        poolProperties.setValidationQuery("SELECT 1");
        poolProperties.setValidationInterval(0);
        DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
        return ds;
    }
}

Знаете ли вы, зачем нужен этот специальный код и почему Spring не просто читает эти свойства из файла свойств? У меня есть несколько свойств источника данных в моем файле, и он без проблем читает все остальные из них.
Дядя Длинные Волосы

3

У меня похожая проблема. Spring 4 и Tomcat 8. Решаю проблему с настройкой Spring.

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
    <property name="initialSize" value="10" />
    <property name="maxActive" value="25" />
    <property name="maxIdle" value="20" />
    <property name="minIdle" value="10" />
     ...
    <property name="testOnBorrow" value="true" />
    <property name="validationQuery" value="SELECT 1" />
 </bean>

Я тестировал. Это работает хорошо! Эти две строки делают все, чтобы повторно подключиться к базе данных:

<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT 1" />

3

Если кто-то использует собственный источник данных

@Bean(name = "managementDataSource")
@ConfigurationProperties(prefix = "management.datasource")
public DataSource dataSource() {
    return DataSourceBuilder.create().build();
}

Свойства должны выглядеть следующим образом. Обратите внимание на @ConfigurationProperties с префиксом. Префикс - это все, что находится перед фактическим именем свойства.

management.datasource.test-on-borrow=true
management.datasource.validation-query=SELECT 1

Ссылка на Spring Version 1.4.4.RELEASE


2

Как уже отмечалось некоторыми людьми, spring-boot 1.4+ имеет определенные пространства имен для четырех пулов соединений. По умолчанию в Spring-boot 2+ используется hikaricp. Таким образом, вам нужно будет указать здесь SQL. По умолчанию это SELECT 1. Вот что вам понадобится, например, для DB2: spring.datasource.hikari.connection-test-query=SELECT current date FROM sysibm.sysdummy1

Предупреждение : если ваш драйвер поддерживает JDBC4, мы настоятельно не рекомендуем устанавливать это свойство. Это для «устаревших» драйверов, которые не поддерживают API JDBC4 Connection.isValid (). Это запрос, который будет выполнен непосредственно перед тем, как вам будет предоставлено соединение из пула, чтобы убедиться, что соединение с базой данных все еще живо. Опять же, попробуйте запустить пул без этого свойства, HikariCP регистрирует ошибку, если ваш драйвер не совместим с JDBC4, чтобы вы знали. По умолчанию: нет


0

Для тех, кто хочет сделать это из YAML с несколькими источниками данных, есть отличное сообщение в блоге об этом: https://springframework.guru/how-to-configure-multiple-data-sources-in-a-spring-boot -применение/

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

@Bean
@Primary
@ConfigurationProperties("app.datasource.member")
public DataSourceProperties memberDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@Primary
@ConfigurationProperties("app.datasource.member.hikari")
public DataSource memberDataSource() {
    return memberDataSourceProperties().initializeDataSourceBuilder()
            .type(HikariDataSource.class).build();
}

Не забываем удалить @Primaryиз других источников данных.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.