Spring重试连接,直到数据源可用

时间:2018-05-27 14:50:49

标签: mysql spring spring-boot docker-compose hikaricp

我有一个docker-compose设置来启动我的SpringBoot应用程序和一个MySQL数据库。如果数据库首先启动,那么我的应用程序可以成功连接。但是如果我的应用程序首先启动,则还没有数据库存在,因此应用程序抛出以下异常并退出:

app_1       | 2018-05-27 14:15:03.415  INFO 1 --- [           main]
com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
app_1       | 2018-05-27 14:15:06.770 ERROR 1 --- [           main]
com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Exception during pool initialization
app_1       | com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure

我可以编辑我的docker-compose文件以确保数据库在应用程序启动之前始终处于启动状态,但我希望应用程序能够自己处理这种情况,并且当它无法到达时无法立即退出数据库地址。

有些方法可以在application.properties文件中配置数据源,以使应用程序重新连接到数据库,如herehere所述。但这对于与数据源的启动连接不起作用。

如何让我的SpringBoot应用程序在给定的时间间隔内重启启动时与数据库的连接,直到它成功连接到数据库为止?

3 个答案:

答案 0 :(得分:4)

还有一种替代方法,不依赖于特定的连接池库或特定的数据库。请注意,您将需要使用PATH才能通过这种方法实现所需的行为

首先,您需要将spring-retry添加到您的依赖项中:

spring-retry

然后,您可以在<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>${spring-retry.version}</version> </dependency> 上创建一个装饰器,该装饰器将像波纹管一样扩展DataSource

AbstractDataSource

然后,您需要通过创建自定义@Slf4j @RequiredArgsConstructor public class RetryableDataSource extends AbstractDataSource { private final DataSource dataSource; @Override @Retryable(maxAttempts = 5, backoff = @Backoff(multiplier = 1.3, maxDelay = 10000)) public Connection getConnection() throws SQLException { log.info("getting connection ..."); return dataSource.getConnection(); } @Override @Retryable(maxAttempts = 5, backoff = @Backoff(multiplier = 2.3, maxDelay = 10000)) public Connection getConnection(String username, String password) throws SQLException { log.info("getting connection by username and password ..."); return dataSource.getConnection(username, password); } } 将这个自定义DataSource装饰器注入Spring上下文:

BeanPostProcessor

最后但并非最不重要的一点是,您需要通过在Spring主类中添加@Slf4j @Order(value = Ordered.HIGHEST_PRECEDENCE) @Component public class RetryableDatabasePostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof DataSource) { log.info("-----> configuring a retryable datasource for beanName = {}", beanName); return new RetryableDataSource((DataSource) bean); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } } 注释来启用Spring重试,例如:

@EnableRetry

答案 1 :(得分:1)

将HikariCP的initializationFailTimeout属性设置为0(零)或负数。记录在案here

答案 2 :(得分:0)

您还可以在docker-compose.yaml中的服务上设置depends_on

这看起来像: (我知道它不是HikariDataSource,但也许还是有帮助的)

version: '3.7'

services:
  mongodbservice:
      image: mongo:latest

  backend:
    depends_on:
      - mongodbservice

在此示例中,如果服务mongodbservice可用,则将启动后端:)