在 Java 应用程序中使用 jdbc 字符串错误的 PostgreSQL 连接故障转移

PostgreSQL Connection Failover using jdbc string error in Java Application

我有一个小型测试应用程序,它正在对具有主服务器 (10.200.0.50) 和备用服务器 (10.200.0.51) 的 Postgresql 集群进行查询。当应用程序与主服务器的连接不可用时,我希望应用程序重新指向备用服务器。

我从这里开始关注文档的最后一部分: https://jdbc.postgresql.org/documentation/head/connect.html

到目前为止我有这个:

public static void main(String[] args) {

    Scanner s = new Scanner(System.in);
    Statement stmt = null;
    Connection c = null;
    try {
        Class.forName("org.postgresql.Driver");
        c = DriverManager
        .getConnection("jdbc:postgresql://10.200.0.50,10.200.0.51:5432/replicationtest",
            "postgres", "password");            

        stmt = c.createStatement();

        ResultSet rs = stmt.executeQuery( "SELECT * FROM testtable;" );
        while( rs.next() ) {
            String  name = rs.getString("name");
            System.out.println(name);
        }
        rs.close();

        int choice = s.nextInt();

        ResultSet rs2 = stmt.executeQuery("SELECT * FROM testtable");
        while( rs2.next() ) {
            String  name = rs2.getString("name");
            System.out.println(name);
        }
        rs2.close();
        c.close();

    } catch (Exception e) {
        e.printStackTrace();
        System.err.println(e.getClass().getName()+": "+e.getMessage());
        System.exit(0);
    }
    s.close();
}

场景 A) 主服务器 10.200.0.50 停机并备用服务器 10.200.0.51 已启动。

这很好用,一开始有一点延迟,但随后应用程序使用 jdbc 字符串

中指定的第二个服务器

场景 B) 当我 运行 应用程序时,主服务器和备用服务器都已启动。但是在第一次查询之后,应用程序正在等待 nextInt(),我阻止了与 10.200.0.50 的连接;在成功建立连接后模拟主要故障。

当我 运行 场景 B 然后调用第二个查询时,我收到错误:

org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:317)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:432)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:358)
at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:305)
at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:291)
at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:269)
at org.postgresql.jdbc.PgStatement.executeQuery(PgStatement.java:236)
at com.rakuten.pgRecovery.Main.main(Main.java:59)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)

明白了,我需要将查询包装在 try catch 中,并在读取失败时捕获错误。之后我需要打开一个新连接,它将在传递的节点上进行循环,从而获得良好的连接,就像场景 A