Spring Boot中的主要/次要故障转移数据源 [英] Primary/Secondary failover DataSource in Spring Boot

查看:350
本文介绍了Spring Boot中的主要/次要故障转移数据源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Spring Boot应用,需要有一个主&辅助数据源.在存在连接问题时,我需要实现一些有关如何重新连接的逻辑.由于Spring为您建立了连接,因此在出现问题时,我似乎无法告诉它重新连接.

I have a Spring Boot app and need to have a primary & secondary DataSource. I need to implement some logic on how to reconnect when there are connection problems. Since Spring makes the connection for you, I can't seem to tell it to reconnect when there are issues.

我知道如何制作两个数据源,但是处理逻辑的最佳位置在哪里?逻辑需要这样工作:

I know how to make 2 data sources, but where is the best place to handle the logic on when it will use which one. The logic needs to work this way:

  1. 连接到主要
  2. 如果存在连接问题,资源不可用或发生连接超时,请尝试重新连接到主数据库.
  3. 如果主要节点无法连接,请尝试连接到辅助节点
  4. 如果辅助服务器无法连接,请继续重试步骤2& ;; 3分钟,持续 X 分钟.
  1. Connect to Primary
  2. If there is a connection problem, either resource is unavailable or connection timeout occurred, try to reconnect to primary.
  3. If Primary cannot connect, try to connect to Secondary
  4. If Secondary cannot connect, continue to retry steps 2 & 3 for X minutes.

在Spring Service中处理此问题最好/可行吗?我是否应该使用另一种服务来处理此逻辑,而我的其他服务使用该服务?最好不连接到DB的春季方式",而使用普通的Java旧方式"?

Would it be best/possible to handle this within the Spring Service? Should I have a different service that just deals with this logic and my other services use that? Would it be better to not connect to DB's the "spring way" and use the "plain old java way"?

这里是服务仅连接到主服务器的示例.

Here is an example of what I have where the Service only connects to the Primary.

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 类已被忽略,因为它们非常基础.

The SampleRowMapper and SampleDTO classes have been left out since they are pretty basic.

推荐答案

我能够使用DZone中的这篇文章来实现这种机制:

I was able to implement this sort of a mechanism using this article from DZone: https://dzone.com/articles/using-ha-jdbc-with-spring-boot using enter link description here

HA-JDBC的可配置性很强,并且具有几种不同的故障转移策略.

HA-JDBC is quite configurable and has several different failover strategies.

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

In our case, we setup connectivity to two different databases, our primary is backed up to the secondary so may not be current.

我们将此数据库用作只读数据库,因此不必担心事务,因此请按以下步骤进行设置:

We are using this database as read-only so do not need to worry about transactions so set it up as follows:

  1. Balancer Factory:简单-除非不可用,否则它将始终尝试使用主数据库.
  2. 将主数据库的权重设置为2,将辅助数据库的权重设置为1.将平衡器工厂设置为简单",这将迫使驱动程序转到主数据库,除非我们对此有问题.
  3. 默认同步策略:简单(我们不必担心,因为它是只读的.
  4. 数据库元数据缓存工厂:简单
  5. 状态管理器工厂:简单

我目前无法进行密码混淆,但有一天会再次访问.

I was unable to get password obfuscation working at this point but will revisit that someday.

最初,我也遇到登录问题,但是意识到我确实需要ha-jdbc驱动程序上的用户名/密码.

I also, initially, had problems getting logged in but recognized that I did need a username/password on the ha-jdbc driver.

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

The example above is written in Groovy, not Java.

这篇关于Spring Boot中的主要/次要故障转移数据源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆