如何允许Tomcat连接到多个数据库?

时间:2014-07-01 12:09:57

标签: java database oracle tomcat datasource

我们有两个具有相同数据的生产数据库,并且tomcat服务器当前将连接到其中一个以提供Web服务。

生产数据库将一次更新(需要相当长的时间才能完成)。因此,为了最大限度地减少停机时间,我们必须在运行更新时手动切换到其他数据库。这是一个相当繁琐的过程。

所以问题是DataSource层中是否存在任何负载平衡/容错,以允许这种情况自动发生?即,当一个数据库关闭时,另一个数据库将自动使用。

我们正在使用Oracle数据库,也想知道它是否可以在数据库连接层中完成。

为了澄清,我们只需要对数据库的读访问权限,因此不涉及任何事务。

3 个答案:

答案 0 :(得分:2)

强烈建议 反对 在Java实现和数据源之间引入耦合的任何解决方案分离关注点的原则。

具体来说,我设置了一个TCP代理(如HAProxy)来对两个Oracle数据库进行负载平衡,并配置Tomcat连接到代理。这样,如果您在HAProxy中启用两个数据库,并且需要单独升级它们,您将获得负载平衡,您只需在代理中一次一个地清除它们,而Tomcat不会注意到任何内容。

如果您不需要负载平衡,代理仍然可以用于指向一个数据库或另一个数据库的连接。

当然,根据您的问题,主 - 主复制也可能值得研究。但是,这并不会使用代理进行诋毁。 HTH


备注:如果您在Tomcat中使用连接池,则需要注意细节。即,配置池以定期执行空闲连接的保持活动ping,并确保频率低于代理的频率。否则,代理可能会在池注意到之前以静默方式销毁连接。那个小伙子,是调试的噩梦。


FWIW ,看一下这个walkthrough,用两台MySQL服务器设置HAProxy。使用Oracle不应该与它相去甚远。

答案 1 :(得分:0)

更安全的方法是在Oracle数据库端启用故障转移支持,因为您可以从Oracle数据库中获得更好的连接/会话管理,而不必在Jdbc DataSource级别处理它。

有一个很好的blog post

答案 2 :(得分:0)

据我了解,这并不容易,你应该非常小心这样做。 我会解释一个想法,我们使用的东西让我想起你的问题。

因此,如果您不想使用某些特定于数据库的解决方案(我确定,Oracle可以在这里提供一些东西),您可能希望在java层实现它。 基本上你应该实现自己的数据源,它比开箱即用的数据源更加智能。

基本上,数据源背后的主要思想是根据请求提供连接。 因此,当第一个数据库进行维护时,应该通知数据源(可能是手动或某些事情,您需要开发一些功能),然后对数据源的所有后续请求将被重定向到新数据库。

class MyDatasource implements javax.sql.DataSource {

    private DataSource firstDatasource = ...;
    private DataSource secondDatasource = ...;

    private boolean isMainDbAccessible = true; 

    public Connection getConnection() {
           if(isMainDbAccessible) {

              return firstDatasource.getConnection();
           }
           else {
              return secondDatasource.getConnection();
           }
    }

    public void startMainDbMaintenance() {
         isMainDbAccessible = false;
         // maybe you should passivate somehow the first DS, like close its connections and so forth
    }

    public void endMainDbMaintenance() {
        isMainDbAccessible = true;
        // again, check the connections state here
    }
}

技术实现实际上取决于您实际使用数据源的方式,您是否定义了特定于tomcat的资源并从JNDI获取数据源?或许你可能不会在这里使用tomcat,而是使用Spring来提供对数据源的访问? 有很多可能的配置,所以我不能在这里更具体。

但我想,你已经明白了。

顺便说一下,类似的解决方案也可以在Java Driver级别实现(维护2个驱动程序实例)

希望这有帮助