如何在 JavaEE 应用程序中为 PostgreSQL 热备设置配置连接故障转移?
How to configure connection failover for a PostgreSQL Hot Standby setup in a JavaEE application?
我有两台安装了 PostgreSQL 9.5
数据库的 Linux 服务器(A
和 B
)。我按照documentation中的描述配置了热备模式。在此设置中,A
配置为主,B
配置为热备模式。这运行良好并且表现符合预期。
现在,我想通过 TomEE
数据源通过 Hibernate
/ JDBC
连接一个独立的 Java EE
应用程序(运行 在另一台机器上)到这个数据库设置。
PostgreSQL driver 文档指出,可以在 jdbc 连接中指定多个主机 url:
jdbc:postgresql://host1:port1,host2:port2/database
所以我的问题是:
- 如果
A
关闭并且 B
手动切换到正常操作模式,我的应用程序是否仍然能够使用 jdbc 连接 url 继续进行数据库操作如上所述?
- 我是否必须配置其他参数/库?
注意:我从各种来源了解到,PostgreSQL
不支持自动故障转移(除非该过程涉及第三方软件 - 请参阅下面的评论)。因此,需要手动执行故障转移,这对于这个特定的用例来说是可以的。
EDIT-1:
我决定测试 pgBouncer
(如评论中所建议)以寻找解决方法。它适用于我的用例。我写了一个看门狗脚本,可以自动执行手动步骤:
- 不断检查
A
是否仍然存在并侦听传入连接。
- 如果发生故障转移,将
B
切换到正常运行模式,让它成为新的master并重启服务。
- 将
pgBouncer
设置更改为指向 B
而不是 A
并重新启动服务。
但是,如果有人没有第三方软件的经验,我还是很感兴趣的?
在这种情况下,最好进行测试和测量。
我没有 'hands-on' 使用 PostrgeSQL 热备模式的经验,但我已经为 Java 应用程序完成了数据库故障转移。
首先,测试 PostgreSQL driver 文档页面上的声明
关于 ?targetServerType=master
参数(在页面底部提到)。
写一个小的 Java "PgHsm" class 主方法通过 DriverManager.getConnection
和 运行 使用 PostgreSQL JDBC 驱动程序这是一个简单的更新查询。
应该使用服务器A做更新查询。在服务器 A 上停止 PostgreSQL,运行 PgHsm:它应该无法连接,因为服务器 B 不是主服务器。
让服务器 B 成为主服务器,运行 PgHsm:应该 运行 OK。
数据源由 TomEE 中的数据库连接池支持。 This page 列出了 TomEE 中可用的。
但并非所有数据库连接池都是平等的,我现在更喜欢 HikariCP,因为根据我的经验,它可以更可预测地处理 "database down" 场景。
另请参阅 HikariCP handling database down 页面上的测试结果。
不幸的是,HikariCP 使用 JDBC 的 get/setNetworkTimeout
来预测行为
和 PostgreSQL JDBC 驱动程序 does not implement this (*)。
因此,要确保 (JavaEE) 应用程序线程不会永远挂在数据库操作上,您需要设置 connectTimeout
和 socketTimeout
JDBC 驱动程序选项。设置 socketTimeout
是不稳定的,因为它会自动设置对数据库的所有查询的时间限制。
(*) 更新:由于版本 42.2.x
网络超时为 implemented.
要执行的第二个测试涉及更新 Java "PgHsm" class 以使用您选择的数据库连接池实现
并启动(至少)两个线程,在循环中不断地 运行 简单更新查询(在循环中,从池中获取数据库连接并在 commit/rollback 之后返回到池中)。
当您关闭服务器 A 并将服务器 B 切换到 "master" 模式时,监视 "PgHsm" 记录的异常以及线程 waits/hangs 执行数据库操作的时间。
测试结果可用于更新 JDBC 驱动程序选项和池设置。关注结果:
- 尽快从池中删除无效连接,以便应用程序从池中获取大部分有效连接
- 当数据库出现故障时,尽可能少的应用程序线程挂起(最短的时间)
第二个测试依赖于服务器 A 不可用,因此连接测试查询(由数据库连接池执行)失败。
在两台服务器都保持可用但主从切换的情况下,连接测试查询将无济于事
并且数据库连接池将向应用程序提供错误的(现在是只读的)数据库连接。
在这种情况下,需要人工干预。描述了 HikariCP 的 "fail-over pattern" here
(仅适用于 configuration 页面上描述的选项 allowPoolSuspension
):
- suspendPool()
- softEvictConnections()
- 等到 activeConnections 变为 0。
- resumePool()
第三个测试将与 JavaEE 应用程序一起进行,到现在为止,您应该很清楚会遇到什么问题。
在这些测试之后更新应用程序以改进处理 "database down" 场景的情况并不少见
(例如设置(默认)query-timeouts)。
在您的情况下,在手动故障转移期间使用的 "suspend, flush and resume database connection pool" 功能(上述模式)也是可取的。
我有两台安装了 PostgreSQL 9.5
数据库的 Linux 服务器(A
和 B
)。我按照documentation中的描述配置了热备模式。在此设置中,A
配置为主,B
配置为热备模式。这运行良好并且表现符合预期。
现在,我想通过 TomEE
数据源通过 Hibernate
/ JDBC
连接一个独立的 Java EE
应用程序(运行 在另一台机器上)到这个数据库设置。
PostgreSQL driver 文档指出,可以在 jdbc 连接中指定多个主机 url:
jdbc:postgresql://host1:port1,host2:port2/database
所以我的问题是:
- 如果
A
关闭并且B
手动切换到正常操作模式,我的应用程序是否仍然能够使用 jdbc 连接 url 继续进行数据库操作如上所述? - 我是否必须配置其他参数/库?
注意:我从各种来源了解到,PostgreSQL
不支持自动故障转移(除非该过程涉及第三方软件 - 请参阅下面的评论)。因此,需要手动执行故障转移,这对于这个特定的用例来说是可以的。
EDIT-1:
我决定测试 pgBouncer
(如评论中所建议)以寻找解决方法。它适用于我的用例。我写了一个看门狗脚本,可以自动执行手动步骤:
- 不断检查
A
是否仍然存在并侦听传入连接。 - 如果发生故障转移,将
B
切换到正常运行模式,让它成为新的master并重启服务。 - 将
pgBouncer
设置更改为指向B
而不是A
并重新启动服务。
但是,如果有人没有第三方软件的经验,我还是很感兴趣的?
在这种情况下,最好进行测试和测量。
我没有 'hands-on' 使用 PostrgeSQL 热备模式的经验,但我已经为 Java 应用程序完成了数据库故障转移。
首先,测试 PostgreSQL driver 文档页面上的声明
关于 ?targetServerType=master
参数(在页面底部提到)。
写一个小的 Java "PgHsm" class 主方法通过 DriverManager.getConnection
和 运行 使用 PostgreSQL JDBC 驱动程序这是一个简单的更新查询。
应该使用服务器A做更新查询。在服务器 A 上停止 PostgreSQL,运行 PgHsm:它应该无法连接,因为服务器 B 不是主服务器。
让服务器 B 成为主服务器,运行 PgHsm:应该 运行 OK。
数据源由 TomEE 中的数据库连接池支持。 This page 列出了 TomEE 中可用的。 但并非所有数据库连接池都是平等的,我现在更喜欢 HikariCP,因为根据我的经验,它可以更可预测地处理 "database down" 场景。 另请参阅 HikariCP handling database down 页面上的测试结果。
不幸的是,HikariCP 使用 JDBC 的 get/setNetworkTimeout
来预测行为
和 PostgreSQL JDBC 驱动程序 does not implement this (*)。
因此,要确保 (JavaEE) 应用程序线程不会永远挂在数据库操作上,您需要设置 connectTimeout
和 socketTimeout
JDBC 驱动程序选项。设置 socketTimeout
是不稳定的,因为它会自动设置对数据库的所有查询的时间限制。
(*) 更新:由于版本 42.2.x
网络超时为 implemented.
要执行的第二个测试涉及更新 Java "PgHsm" class 以使用您选择的数据库连接池实现
并启动(至少)两个线程,在循环中不断地 运行 简单更新查询(在循环中,从池中获取数据库连接并在 commit/rollback 之后返回到池中)。
当您关闭服务器 A 并将服务器 B 切换到 "master" 模式时,监视 "PgHsm" 记录的异常以及线程 waits/hangs 执行数据库操作的时间。
测试结果可用于更新 JDBC 驱动程序选项和池设置。关注结果:
- 尽快从池中删除无效连接,以便应用程序从池中获取大部分有效连接
- 当数据库出现故障时,尽可能少的应用程序线程挂起(最短的时间)
第二个测试依赖于服务器 A 不可用,因此连接测试查询(由数据库连接池执行)失败。
在两台服务器都保持可用但主从切换的情况下,连接测试查询将无济于事
并且数据库连接池将向应用程序提供错误的(现在是只读的)数据库连接。
在这种情况下,需要人工干预。描述了 HikariCP 的 "fail-over pattern" here
(仅适用于 configuration 页面上描述的选项 allowPoolSuspension
):
- suspendPool()
- softEvictConnections()
- 等到 activeConnections 变为 0。
- resumePool()
第三个测试将与 JavaEE 应用程序一起进行,到现在为止,您应该很清楚会遇到什么问题。 在这些测试之后更新应用程序以改进处理 "database down" 场景的情况并不少见 (例如设置(默认)query-timeouts)。 在您的情况下,在手动故障转移期间使用的 "suspend, flush and resume database connection pool" 功能(上述模式)也是可取的。