首页 > 解决方案 > Spring Boot - 当程序失去与数据库的连接时如何执行方法?

问题描述

这里的弹簧靴相当新。我一直在研究一个连接两个数据库的微服务,一个是 Cassandra,一个是 Oracle。它们包含相同的信息,因为 Cassandra 数据库正在取代 Oracle 数据库作为该项目的主数据库,但是,如果 Cassandra 数据库出现故障,我们将保留 oracle 数据库作为备用数据库。

当我遇到连接中断时,我不确定如何告诉我的应用程序“做某事”。我的控制台在失去与 Cassandra 的连接时输出以下内容-

2019-09-06 14:23:15.127 ERROR 2836 --- [-reconnection-0] c.d.driver.core.ControlConnection        : [Control connection] Cannot connect to any host, scheduling retry in 1000 milliseconds
2019-09-06 14:23:15.147 ERROR 2836 --- [-reconnection-0] c.d.driver.core.ControlConnection        : [Control connection] Cannot connect to any host, scheduling retry in 1000 milliseconds
2019-09-06 14:23:16.134 ERROR 2836 --- [-reconnection-0] c.d.driver.core.ControlConnection        : [Control connection] Cannot connect to any host, scheduling retry in 2000 milliseconds
2019-09-06 14:23:16.149 ERROR 2836 --- [-reconnection-0] c.d.driver.core.ControlConnection        : [Control connection] Cannot connect to any host, scheduling retry in 2000 milliseconds
2019-09-06 14:23:23.137 ERROR 2836 --- [-reconnection-1] c.d.driver.core.ControlConnection        : [Control connection] Cannot connect to any host, scheduling retry in 4000 milliseconds

它一直这样,超时加倍,直到它可以重新连接。

发生这种情况时是否可以触发方法?如果我可以在连接丢失时更改控制器中的变量值,一切都会正常工作,但我似乎无法找到有关该主题的任何信息。有没有不同的方法来处理这个我什至没有考虑过,比如可能会根据连接而变化的布尔值?对不起,如果这听起来被误导了,我真的只是在这里抓住稻草。

此外,是否可以在重新建立连接时触发事件?

谢谢你的帮助。我真的很感激任何建议。

作为 PS- 我不确定这段代码会有多大帮助,但我觉得我至少应该为我的情况提供一些背景信息。

这是我的 cassandra 配置

@ConfigurationProperties(prefix = "cassandra")
@Getter
@Setter
@Component
public class CassandraConfiguration {

    private String clusterName;
    private String hostNames;
    private String username;
    private String password;
    private String keyspace;
    private boolean sslEnabled;
    private int port;
    private int fetchSize;
    private String localDC;

    private static final Logger LOGGER = LoggerFactory.getLogger(CassandraConfiguration.class);

    @Bean
    public Session cassandraSession() {
        String[] hostname = hostNames.split(",");
        Cluster cluster = null;

        LoadBalancingPolicy loadBalancingPolicy = new TokenAwarePolicy(
                DCAwareRoundRobinPolicy.builder()
                        .withLocalDc(localDC)
                        .build()
        );

        PoolingOptions poolingOptions = new PoolingOptions();
        poolingOptions
                .setConnectionsPerHost(HostDistance.LOCAL,  4, 10)
                .setConnectionsPerHost(HostDistance.REMOTE, 2, 4)
                .setMaxRequestsPerConnection(HostDistance.LOCAL, 32768)
                .setMaxRequestsPerConnection(HostDistance.REMOTE, 2000);

        if (isSslEnabled()) {

            cluster = Cluster.builder().addContactPoints(hostname)
                    .withClusterName(clusterName)
                    .withCredentials(username, password)
                    .withPort(port)
                    .withoutJMXReporting()
                    .withSSL()
                    .withQueryOptions(new QueryOptions().setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM))
                    .withLoadBalancingPolicy(loadBalancingPolicy)
                    .withPoolingOptions(poolingOptions)
                    .build();

        } else {
            cluster = Cluster.builder().addContactPoints(hostname)
                    .withClusterName(clusterName)
                    .withCredentials(username, password)
                    .withPort(port)
                    .withoutJMXReporting()
                    .withQueryOptions(new QueryOptions().setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM))
                    .withLoadBalancingPolicy(loadBalancingPolicy)
                    .withPoolingOptions(poolingOptions)
                    .build();
        }

        cluster.getConfiguration().getCodecRegistry()
                .register(LocalDateCodec.instance)
                .register(InstantCodec.instance);
        Session session = cluster.connect(keyspace);

        return session;
    }

    @Bean
    public MappingManager mappingManager() {
        return new MappingManager(cassandraSession());
    }

}

这是我的 oracle 的 jdbc 配置

@ConfigurationProperties("jdbc")
@Configuration
@Getter
@Setter
@ConditionalOnProperty(name = "jdbc.accessService", havingValue = "enabled")
public class JDBCConfig {
    @Autowired
    SshTunnel sshTunnel;

    private String driver;
    private String url;
    private String user;
    private String password;

    @PostConstruct
    private void init() {
        try {
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Bean
    public Connection jdbcConnection() {
        Connection jdbcConnection = null;

        try {
            jdbcConnection = DriverManager.getConnection (url, user, password);
            System.out.println("Connection Established");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return jdbcConnection;
    }
}

标签: javaspringoraclespring-bootcassandra

解决方案


听起来您需要一个断路器,它是一个软件组件,用于监视某些包装服务的故障,尝试检测它何时再次可用,并可以重定向到其他一些实现或让异常在故障条件下逃脱。

当前明显的默认值(和我的建议)是弹性4j


推荐阅读