Spring Boot JPA - konfigurowanie automatycznego ponownego łączenia

107

Mam fajną, małą aplikację internetową Spring Boot JPA. Jest wdrażany na Amazon Beanstalk i używa Amazon RDS do utrwalania danych. Jednak nie jest używany tak często i dlatego po pewnym czasie zawodzi z tego rodzaju wyjątkiem:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Ostatni pakiet pomyślnie odebrany z serwera był 79 870 633 milisekund temu.
Ostatni pakiet pomyślnie wysłany do serwera był 79 870 634 milisekund temu. jest dłuższy niż wartość „wait_timeout” skonfigurowana przez serwer. Aby uniknąć tego problemu, należy rozważyć wygaśnięcie i / lub przetestowanie ważności połączenia przed użyciem w aplikacji, zwiększenie skonfigurowanych przez serwer wartości limitów czasu klienta lub użycie właściwości połączenia łącznika / J „autoReconnect = true”.

Nie jestem pewien, jak skonfigurować to ustawienie i nie mogę znaleźć informacji na jego temat na http://spring.io (choć bardzo dobra strona). Jakie są pomysły lub wskazówki do informacji?

sztywniejszy
źródło
Użyj tego, aby wydrukować swoje DataSourcei zweryfikować jego właściwości. stackoverflow.com/a/36586630/148844 Wiosna Boot nie będzie auto-Konfiguracja DataSourcejeśli masz jakieś @Beans, które definiują DataSource. docs.spring.io/spring-boot/docs/1.5.16.RELEASE/reference/…
Chloe

Odpowiedzi:

141

Zakładam, że boot konfiguruje DataSourcedla Ciebie. W tym przypadku i ponieważ używasz MySQL, możesz dodać następujące elementy do swojej wersji application.properties1.3

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

Jak djxak zauważono w komentarzu, 1.4+ Definiuje specyficzne przestrzenie nazw dla czterech połączeń basenów Wiosna Boot Obsługuje: tomcat, hikari, dbcp, dbcp2( dbcpjest przestarzała 1,5). Musisz sprawdzić, której puli połączeń używasz i czy ta funkcja jest obsługiwana. Powyższy przykład dotyczy tomcata, więc w 1.4+ musiałbyś napisać go następująco:

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

Należy pamiętać, że używanie autoReconnectjest nie zalecane :

Używanie tej funkcji nie jest zalecane, ponieważ ma efekty uboczne związane ze stanem sesji i spójnością danych, gdy aplikacje nie obsługują poprawnie SQLExceptions i jest przeznaczone do użycia tylko wtedy, gdy nie możesz skonfigurować aplikacji do obsługi SQLExceptions wynikających z martwe i nieaktualne połączenia.

Stephane Nicoll
źródło
8
to dlatego, że zharmonizowaliśmy sposób, w jaki zapisujemy klucze w dokumentacji. Zawsze używaliśmy luźnego spoiwa, więc oba spring.datasource.testOnBorrowi spring.datasource.test-on-borrowbędą działać dobrze. Sprawdzić dokumentację po więcej szczegółów.
Stephane Nicoll
17
Ponieważ może to mylić innych: SELECT 1gwarantuje, że połączenie zostało przetestowane przed przekazaniem aplikacji. Używając testOnBorrow = true, obiekty zostaną sprawdzone przed wypożyczeniem z puli. Jeśli obiekt nie przejdzie walidacji, zostanie usunięty z puli i spróbuje pożyczyć inną. UWAGA - aby wartość true miała jakikolwiek efekt, parametr validationQuery musi być ustawiony na ciąg inny niż null.
Rick
14
Ostrzeżenie! Wiosną Boot 1.4+ ten został zmieniony : nie określono nowe przestrzenie nazw specyficznych dla czterech połączeń basenów podpór sprężystych: tomcat, hikari, dbcp, dbcp2. Na przykład dla tomcat-jdbcpuli połączeń właściwości powinny być następujące: spring.datasource.tomcat.testOnBorrow=truei spring.datasource.tomcat.validationQuery=SELECT 1.
Ruslan Stelmachenko
1
Jeśli sam konfiguruję dwa różne źródła danych, w jaki sposób mogę zapewnić tę konfigurację? Czy muszę podać tę konfigurację dla obu źródeł danych, takich jak 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 Czy jest jeszcze coś do naśladowania?
Nitish Kumar
2
Ostrzeżenie! Jeśli zdefiniujesz dowolne źródło danych @Bean w swojej aplikacji, Spring Boot nie skonfiguruje puli. docs.spring.io/spring-boot/docs/1.5.16.RELEASE/reference/… Postępowałem If you define your own DataSource bean, auto-configuration will not occur. zgodnie z przewodnikiem dla OAuth2 i miałem @Bean(name = "OAuth") public DataSource secondaryDataSource()...i nie został on automatycznie skonfigurowany ani użyty testOnBorrow.
Chloe,
28

Powyższe sugestie nie działają dla mnie. To, co naprawdę zadziałało, to włączenie następujących wierszy do pliku application.properties

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

Możesz znaleźć wyjaśnienie tutaj

Soumya
źródło
5
Dodane łącze mówi, że jeśli połączenie z bazą danych jest nieaktywne przez ponad 8 godzin, zostanie automatycznie zamknięte i wystąpi powyższy błąd. Dlatego Twoim rozwiązaniem nie jest pozostawienie połączenia nieaktywnego przez dłuższy czas. Czy istnieje sposób, w jaki mogę połączyć się z serwerem SQL po jego ponownym uruchomieniu?
Akeshwar Jha
9

Ustawienie spring.datasource.tomcat.testOnBorrow=truew application.properties nie działa.

Programowe ustawienie jak poniżej działało bez żadnych problemów.

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);
}
kim jestem
źródło
1
Jeśli deklarujesz niestandardowe źródło danych, może to być spowodowane próbą użycia domyślnego pliku .tomcat sprężyny. Jeśli więc utworzysz niestandardowy komponent bean Datasource, dodaj @ConfigurationProperties (prefix = "spring.datasource.tomcat") do komponentu bean DataSource, a następnie powinno umożliwić ustawienie ich we właściwościach aplikacji. Mój przykład .. @Bean (name = "managementDataSource") @ConfigurationProperties (prefix = "management.datasource") public DataSource dataSource () {return DataSourceBuilder.create (). Build (); } management.datasource.test-on-borrow = true
Justin
8

Właśnie przeniosłem się do Spring Boot 1.4 i odkryłem, że nazwy tych właściwości zostały zmienione:

spring.datasource.dbcp.test-while-idle=true
spring.datasource.dbcp.time-between-eviction-runs-millis=3600000
spring.datasource.dbcp.validation-query=SELECT 1
Jose Jurado
źródło
2
Nazwy są równoważne. Zobacz sekcję dotyczącą nazewnictwa właściwości w dokumentacji Spring Boot .
Stephen Harrison
@StephenHarrison: zwróć uwagę na prefiks dbcp. * Dodany w 1.4, w tym przypadku nie ma zastosowania łagodne wiązanie.
YM
1
@Pawel: w zależności od tego, która implementacja puli jest dostępna w Twoim projekcie, może to nie być właściwość dbcp. *, Zobacz Rozruch sprężynowy z SQL i odpowiednie właściwości źródła danych
YM
4

odpowiedź whoami jest poprawna. Używając właściwości zgodnie z sugestią, nie mogłem tego uruchomić (używając Spring Boot 1.5.3.RELEASE)

Dodaję odpowiedź, ponieważ jest to pełna klasa konfiguracji, więc może pomóc komuś używającemu 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;
    }
}
naoru
źródło
Czy wiesz, dlaczego ten niestandardowy kod jest potrzebny i dlaczego Spring nie odczyta po prostu tych właściwości z pliku właściwości? Mam kilka właściwości źródła danych w moim pliku i czyta wszystkie pozostałe bez problemu.
Wujek długie włosy
3

Mam podobny problem. Spring 4 i Tomcat 8. Rozwiązuję problem z konfiguracją Springa

<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>

Testowałem. To dobrze działa! Te dwie linie robią wszystko, aby ponownie połączyć się z bazą danych:

<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT 1" />
grep
źródło
3

W przypadku, gdy ktoś używa niestandardowego źródła danych

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

Właściwości powinny wyglądać następująco. Zwróć uwagę na @ConfigurationProperties z prefiksem. Przedrostek to wszystko przed rzeczywistą nazwą właściwości

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

Odniesienie do wersji wiosennej 1.4.4. RELEASE

Justin
źródło
2

Jak niektórzy już zauważyli, spring-boot 1.4+ ma określone przestrzenie nazw dla czterech pul połączeń. Domyślnie hikaricp jest używany w spring-boot 2+. Będziesz więc musiał określić tutaj SQL. Wartość domyślna to SELECT 1. Oto, czego potrzebujesz na przykład dla DB2: spring.datasource.hikari.connection-test-query=SELECT current date FROM sysibm.sysdummy1

Uwaga : jeśli sterownik obsługuje JDBC4, zdecydowanie odradzamy ustawianie tej właściwości. Dotyczy to sterowników „starszych”, które nie obsługują funkcji API JDBC4 Connection.isValid (). Jest to zapytanie, które zostanie wykonane tuż przed uzyskaniem połączenia z puli w celu sprawdzenia, czy połączenie z bazą danych nadal działa. Ponownie spróbuj uruchomić pulę bez tej właściwości, HikariCP zarejestruje błąd, jeśli sterownik nie jest zgodny z JDBC4, aby Cię o tym powiadomić. Domyślnie: brak

code4kix
źródło
0

Dla tych, którzy chcą to zrobić z YAML z wieloma źródłami danych, jest na ten temat świetny wpis na blogu: https://springframework.guru/how-to-configure-multiple-data-sources-in-a-spring-boot -podanie/

Zasadniczo mówi, że oboje musicie skonfigurować właściwości źródła danych i źródło danych w następujący sposób:

@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();
}

Nie zapomnij usunąć @Primaryz innych źródeł danych.

enesaltinok
źródło