我有一个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文件中配置数据源,以使应用程序重新连接到数据库,如here和here所述。但这对于与数据源的启动连接不起作用。
如何让我的SpringBoot应用程序在给定的时间间隔内重启启动时与数据库的连接,直到它成功连接到数据库为止?
答案 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可用,则将启动后端:)