如何在JavaEE应用程序中为PostgreSQL Hot Standby设置配置连接故障转移?

时间:2016-11-30 17:54:44

标签: java postgresql hibernate jdbc tomee

我有两个安装了A数据库的Linux服务器(BPostgreSQL 9.5)。我按照documentation中的说明配置了热备用模式。在此设置中,A在热备用模式下配置为主设备B。这样做效果很好,并且表现得像预期的那样。

现在,我想通过Java EE / Hibernate通过JDBC数据源将独立的TomEE应用程序(在不同的计算机上运行)连接到此数据库设置。

PostgreSQL driver文档指出,可以在jdbc连接URL中指定多个主机:

jdbc:postgresql://host1:port1,host2:port2/database

所以我的问题是:

  1. 如果A关闭并且B被手动切换到正常操作模式,我的应用程序是否仍然可以使用jdbc连接URL继续进行数据库操作,如上所述?
  2. 我是否必须配置其他参数/​​库?
  3. 注意:从我学到的各种来源,PostgreSQL不支持自动故障转移(除非第三方软件参与了此过程 - 请参阅下面的评论)。因此,需要手动执行故障转移,这对于此特定用例是可以的。

    修改-1:

    我决定测试pgBouncer(如评论中所示)以获得解决方法。它适用于我的用例。我编写了一个监视程序脚本,它自动执行手动步骤:

    1. 如果A仍然存在,则继续检查并侦听传入的连接。
    2. 如果发生故障转移,请将B切换到正常运行模式,然后让它成为新主服务器并重新启动服务。
    3. pgBouncer设置更改为指向B而不是A,然后重新启动服务。
    4. 但是,如果有人没有第三方软件的经验,我仍然会感兴趣吗?

1 个答案:

答案 0 :(得分:10)

在这种情况下,最好进行测试和测量。

我没有亲自动手的'使用PostrgeSQL热备用模式的经验,但我已经为Java应用程序完成了数据库故障转移。

首先,在PostgreSQL driver文档页面上测试声明 关于?targetServerType=master参数(在页面底部提到)。
写一个小Java" PgHsm"使用main方法的类,该方法通过DriverManager.getConnection使用PostgreSQL JDBC驱动程序并运行简单的更新查询。
它应该使用服务器A来进行更新查询。在服务器A上停止PostgreSQL,运行PgHsm:它应该无法连接,因为服务器B不是主服务器。
使服务器B成为主服务器,运行PgHsm:它应该运行正常。

数据源由TomEE中的数据库连接池支持。 This page列出了TomEE中可用的内容。 但并不是所有的数据库连接池都是相同的,我现在更喜欢HikariCP,因为根据我的经验,它可以处理"数据库down"场景更可预测。 另请参阅HikariCP' handling database down页面上的结果测试。

不幸的是,HikariCP使用JDBC的get/setNetworkTimeout来表现可预测性 和PostgreSQL JDBC驱动程序does not implement this(*)。 因此,为了确保(JavaEE)应用程序线程不会永远挂起数据库操作,您需要设置connectTimeoutsocketTimeout JDBC驱动程序选项。设置socketTimeout是不稳定的,因为它会自动为数据库的所有查询设置时间限制。

(*)更新:由于版本42.2.x网络超时为implemented

要执行的第二项测试涉及更新Java" PgHsm"类使用您选择的数据库连接池实现 并且(至少)启动(至少)两个在循环中连续运行简单更新查询的线程(在循环中,从池中获取数据库连接并在提交/回滚后返回到池)。 当您关闭服务器A并将服务器B切换到" master"模式,监控" PgHsm"以及线程在执行数据库操作时等待/挂起的时间。
测试结果可用于更新JDBC驱动程序选项和池设置。专注于以下结果:

  • 尽快从池中删除无效连接,以便应用程序从池中获得大部分有效连接
  • 当数据库出现故障时,尽可能少的应用程序线程挂起(最短的时间)

第二个测试依赖于服务器A不可用,因此连接测试查询(由数据库连接池执行)失败。 在两个服务器仍然可用但主交换机和从交换机的情况下,连接测试查询将无济于事 并且数据库连接池将提供与应用程序的错误(现在只读)数据库连接。 在这种情况下,需要人工干预。 A"故障转移模式"对于HikariCP的描述here (仅适用于configuration页面上描述的选项allowPoolSuspension):

  • suspendPool()
  • softEvictConnections()
  • 等到activeConnections转到0。
  • resumePool()

第三个测试将使用JavaEE应用程序,到现在为止,您应该知道会遇到什么问题。 应用程序在这些测试之后进行更新以改善处理和数据库传输并不常见。场景 (例如设置(默认)query-timeouts)。 在您的情况下,"暂停,刷新和恢复数据库连接池"在手动故障转移期间使用的功能(上述模式)也是可取的。