Spring Boot应用启动时二级数据源不可用如何继续运行?
问题
我们有一个配置了两个数据源(SQL Server、Postgres)的Spring Boot 2.6.6应用,希望启动时即使二级Postgres数据源无法访问也能正常运行。之前尝试配置spring.datasource.continue-on-error=true和spring.sql.init.continue-on-error=true,但没有效果。当前的YAML配置如下:
spring: datasource: primary: type: com.zaxxer.hikari.HikariDataSource url: jdbc:sqlserver://localhost:58459;database=abcd;encrypt=false username: sa password: 1234 liquibase: change-log: classpath:config/liquibase/master.xml hikari: poolName: Hikari auto-commit: false data-source-properties: cachePrepStmts: true prepStmtCacheSize: 250 prepStmtCacheSqlLimit: 2048 useServerPrepStmts: true secondary: url: jdbc:postgresql://localhost:5432/abcd username: sa password: 1234 driver: org.postgresql.Driver dialect: org.hibernate.dialect.PostgreSQLDialect physical_naming_strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy liquibase: change-log: classpath:config/liquibase/master-postgre.xml
问题原因
spring.datasource.continue-on-error和spring.sql.init.continue-on-error仅对Spring Boot自动配置的单一默认数据源生效,自定义多数据源场景下不会自动作用到二级数据源。- 二级数据源配置了Liquibase,启动时Spring Boot会自动触发变更集执行,若数据源不可达,Liquibase会直接抛出异常导致启动失败。
- Hikari连接池默认初始化时会强制建立连接,连接失败则直接报错阻塞启动。
解决办法
1. 配置二级Hikari数据源的连接容错参数
在二级数据源中添加Hikari专属配置,让连接池初始化时不强制校验连接,允许后台重试:
spring: datasource: # 主数据源配置保持不变 secondary: # 保留原有配置,新增以下内容 type: com.zaxxer.hikari.HikariDataSource # 若未显式指定,需添加该类型声明 hikari: initialization-fail-timeout: -1 # 初始化失败不超时,后台自动重试,不阻塞应用启动 connection-test-query: SELECT 1 # PostgreSQL连接校验SQL,建议配置 validation-timeout: 3000
2. 处理二级数据源的Liquibase逻辑
如果二级数据源不可用时无需执行Liquibase变更,直接禁用其自动执行:
spring: liquibase: secondary: enabled: false
如果需要在数据源可用时才执行Liquibase,可给二级数据源的Liquibase添加容错配置:
spring: datasource: secondary: liquibase: continue-on-error: true enabled: true
3. JPA容错配置(若使用JPA)
如果二级数据源关联了JPA实体管理器,需配置JPA初始化时不强制校验连接:
spring: jpa: secondary: defer-datasource-initialization: true # 延迟数据源初始化 hibernate: ddl-auto: none # 禁用自动DDL,避免启动时触发连接校验 properties: hibernate.temp.use_jdbc_metadata_defaults: false # 禁止Hibernate读取JDBC元数据,避免连接失败报错
4. 自定义数据源配置类(可选,更灵活)
若上述配置仍不生效,可手动编写配置类控制二级数据源的初始化逻辑:
@Configuration public class SecondaryDataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.secondary") public DataSourceProperties secondaryDataSourceProperties() { return new DataSourceProperties(); } @Bean public DataSource secondaryDataSource(DataSourceProperties properties) { HikariDataSource dataSource = properties.initializeDataSourceBuilder() .type(HikariDataSource.class) .build(); // 设置Hikari容错参数 dataSource.setInitializationFailTimeout(-1); dataSource.setConnectionTestQuery("SELECT 1"); return dataSource; } // 手动配置Liquibase并添加容错逻辑 @Bean @ConditionalOnProperty(prefix = "spring.datasource.secondary.liquibase", name = "enabled", havingValue = "true") public SpringLiquibase secondaryLiquibase(DataSource secondaryDataSource, @Value("${spring.datasource.secondary.liquibase.change-log}") String changeLog) { SpringLiquibase liquibase = new SpringLiquibase(); liquibase.setDataSource(secondaryDataSource); liquibase.setChangeLog(changeLog); liquibase.setContinueOnError(true); // 先尝试连接数据源,失败则跳过Liquibase执行 try (Connection conn = secondaryDataSource.getConnection()) { // 连接成功,正常执行变更 } catch (SQLException e) { liquibase.setEnabled(false); } return liquibase; } }
内容的提问来源于stack exchange,提问作者Bhavesh Shah
相关产品推荐
相关产品推荐

