Spring 启动验证数据源连接

Spring Boot verify Datasource connection

在Spring Boot 中,有没有办法验证DataSourceAutoConfiguration 创建的Datasource 是否有效以及是否可以创建连接?

我们正在使用 Spring Boot 2.1.2 以及 Hikari 3.2.0 和 Flyway 5.2.4。

我 运行 遇到的问题是我想在无法访问我们的数据源时发出警报。这可能是由于数据库未正确命名或应用程序仍在初始化时 RDS 服务器已关闭。

我对启动顺序的理解是:

  1. Spring 启动初始化数据源
  2. 迁移 运行 次迁徙
  3. 数据库连接池已初始化
  4. Hibernate 初始化

我想做的是在 Flyway 运行s 之前验证在步骤 1 中创建的数据源。 Flyway 确实有一个回调系统,但它只在迁移 运行 时有效,而不是在无法从数据库获得连接时有效。我知道 SpringBoot 提供的 DataSourceHealthIndicator,但据我所知,只有在调用 Actuator 端点时才会得到 运行。有没有办法验证数据源(创建新连接)或强制在 Flyway 自动配置之前调用 DataSourceHealthIndicator?

也许您可以配置连接测试。

c3p0 可以配置为测试它以各种方式汇集的连接。 idleConnectionTestPeriodtestConnectionOnCheckouttestConnectionOnCheckin 控制何时测试连接。 automaticTestTableconnectionTesterClassNamepreferredTestQuery 控制它们的测试方式。这是一个 link 以获取更多信息: https://www.mchange.com/projects/c3p0/#configuring_connection_testing

尽管容易出错,但另一种可能性是对使用 JdbcTemplate 的组件进行注释:

@DependsOn({"flyway", "flywayInitializer"})

这将在 Flyway 和您的配置之间建立依赖关系 class。

我能够在 Flyay 通过添加自定义 DB HealthCheck 初始化之前成功测试 DataSource。当 bean 初始化时,我立即检查数据库的健康状况。如果数据库检查失败,我的实现将提醒外部来源。

@Configuration
public class NotifiyingDataSourceHealthCheckConfig extends DataSourceHealthIndicatorAutoConfiguration {

    @Value("${aws.accessKeyId}")
    private String awsAccessKeyId;

    @Value("${aws.secretKey}")
    private String awsSecret;

    @Value("${aws.alertQueueName}")
    private String alertQueueName;

    @Value("${aws.region}")
    private String awsRegion;

    public NotifiyingDataSourceHealthCheckConfig( ObjectProvider<Map<String, DataSource>> dataSources, ObjectProvider<DataSourcePoolMetadataProvider> metadataProviders ) {
        super( dataSources, metadataProviders );
    }

    @Bean(name = "dbHealthIndicator")
    public HealthIndicator dbHealthIndicator() {
        BasicAWSCredentials credentials = new BasicAWSCredentials( awsAccessKeyId, awsSecret );
        AmazonSQSAsync amazonSQS = AmazonSQSAsyncClientBuilder.standard().withCredentials( new AWSStaticCredentialsProvider( credentials ) ).withRegion( awsRegion ).build();

        HealthIndicator healthIndicator =  new NotifiyingHealthIndicatorWrapper( super.dbHealthIndicator(), amazonSQS, alertQueueName, "frequent-flyer-api", "db" );
        healthIndicator.health();
        return  healthIndicator;
    }
}