Spring Boot中的主/辅助故障转移DataSource

时间:2017-08-21 15:12:49

标签: spring spring-boot

我有一个Spring Boot应用程序,需要有一个主要&辅助数据源。当有连接问题时,我需要实现一些关于如何重新连接的逻辑。由于Spring为您提供连接,我似乎无法告诉它在出现问题时重新连接。

我知道如何制作2个数据源,但是哪个是处理逻辑的最佳位置何时使用哪一个。逻辑需要以这种方式工作:

  1. 连接到主要
  2. 如果存在连接问题,资源不可用或发生连接超时,请尝试重新连接到主服务器。
  3. 如果主节点无法连接,请尝试连接到辅助
  4. 如果辅助节点无法连接,请继续重试步骤2& 3 X 分钟。
  5. 最好/可能在Spring Service中处理这个问题吗?我应该有一个不同的服务,只处理这个逻辑,我的其他服务使用它吗?最好不要连接到数据库"弹簧方式"并使用"普通的旧java方式"?

    以下是我的服务仅连接到主服务器的示例。

    DatasourcesConfig

    package com.helloworld.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    
    import oracle.jdbc.pool.OracleDataSource;
    import org.springframework.jdbc.core.JdbcTemplate;
    
    import javax.sql.DataSource;
    import java.sql.SQLException;
    
    @Configuration
    public class DatasourcesConfig {
    
        @Primary
        @Bean(name = "primaryDataSource")
        DataSource primaryDataSource() throws SQLException {
    
            OracleDataSource dataSource = new OracleDataSource();
    
            dataSource.setUser("user");
            dataSource.setPassword("pass");
            dataSource.setURL("jdbc:oracle:thin:@(...primary connection...)");
    
            return dataSource;
        }
    
          @Bean(name = "secondaryDataSource")
          DataSource secondaryDataSource() throws SQLException {
    
              OracleDataSource dataSource = new OracleDataSource();
    
              dataSource.setUser("user");
              dataSource.setPassword("pass");
              dataSource.setURL("jdbc:oracle:thin:@(...secondary connection...)");
    
              return dataSource;
          }
    
        @Bean(name = "jdbcPrimary")
        @Autowired
        public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource ds) {
            return new JdbcTemplate(ds);
        }
    
        @Bean(name = "jdbcSecondary")
        @Autowired
        public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource ds) {
            return new JdbcTemplate(ds);
        }
    
    }
    

    ExampleService

    package com.helloworld.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.stereotype.Service;
    
    @Service
    public class ExampleService {
    
        @Autowired
        @Qualifier("jdbcPrimary")
        private JdbcTemplate jdbcTemplatePrimary;
    
        @Autowired
        @Qualifier("jdbcSecondary")
        private JdbcTemplate jdbcTemplateSecondary;
    
        public SampleDTO getData(String a, String b){
    
            final String sql = "select a, b from TABLE_A where a=? and b=?";
    
            // Only checking Primary
            return jdbcTemplatePrimary.queryForObject(sql,
                    new Object[]{a,b},
                    new SampleRowMapper());
    
            // Is this the best place to catch exceptions and connect to Secondary?
    
        }
    
    }
    

    SampleRowMapper SampleDTO 类已被排除在外,因为它们非常基础。

2 个答案:

答案 0 :(得分:6)

我能够使用DZone的这篇文章实现这种机制:https://dzone.com/articles/using-ha-jdbc-with-spring-boot使用enter link description here

HA-JDBC是可配置的,并且有几种不同的故障转移策略。

在我们的案例中,我们设置了与两个不同数据库的连接,我们的主数据库备份到辅助数据库,因此可能不是最新数据库。

我们将此数据库用作只读,因此无需担心事务,因此请按以下方式进行设置:

  1. Balancer Factory:简单 - 除非它不可用,否则它将始终尝试初级。
  2. 主数据库的权重设置为2,辅助设置的权重设置为1.将平衡器出厂设置为“简单”时,应该强制驱动程序转到主数据库,除非我们遇到问题。
  3. 默认同步策略:简单(我们无需担心这是因为它是只读的。
  4. 数据库元数据缓存工厂:简单
  5. 州经理工厂:简单
  6. 我无法在此时获得密码混淆,但有一天会重新审视。

    我最初也遇到了登录问题,但发现我确实需要在ha-jdbc驱动程序上使用用户名/密码。

    上面的示例是用Groovy编写的,而不是Java。

答案 1 :(得分:3)

我认为您可以使用断路器模式; 当主数据源发生故障时,断路器回退方法将运行,并使用辅助数据源。在后备方法中,您可以重试失败状态。 Hystrix是断路器模式的不错选择,您可以使用它。希望对您有帮助:)

弹簧断路器隐含; https://spring.io/guides/gs/circuit-breaker/