Hologres從 V1.3版本開始,支援在JDBC配置多個唯讀從執行個體以支援簡單的負載平衡。本文為您介紹如何基於JDBC實現負載平衡。
背景資訊
Hologres中一個主執行個體可以綁定多個唯讀從執行個體,執行個體與執行個體之間共用儲存,但是計算資源是互相隔離的,從而實現讀寫分離高可用部署,詳情請參見主從執行個體讀寫分離部署(共用儲存)。
Hologres支援使用JDBC配置多個唯讀從執行個體,實現簡單的負載平衡,如下圖所示:
您使用JDBC配置多個唯讀從執行個體可以實現以下功能:
將查詢請求隨機分配到您的唯讀從執行個體,避免單個唯讀從執行個體負載過高。
查詢請求按照順序串連唯讀從執行個體,極大程度避免因為唯讀從執行個體故障導致服務不可用,存在以下情況:
當唯讀從執行個體1串連失敗時,JDBC會自動嘗試串連唯讀從執行個體2。
當唯讀從執行個體1和唯讀從執行個體2串連失敗時,JDBC會自動嘗試串連唯讀從執行個體3。
只有當唯讀從執行個體1、唯讀從執行個體2和唯讀從執行個體3均串連失敗時,系統才會提示串連失敗。
從Hologres V2.0.10版本開始,targetServerType
參數支援更加豐富的取值,擴充負載平衡使用的情境。
使用說明
前提條件
已購買多個Hologres唯讀從執行個體並綁定至Hologres主執行個體,詳情請參見配置共用儲存的主從執行個體。
已下載42.3.2以上版本的Postgres JDBC驅動,詳情請參見JDBC。
命令格式
JDBC配置多個唯讀從執行個體需要在串連URL中將多個唯讀從執行個體的Endpoint:Port
資訊用半形逗號(,
)分隔,命令格式如下:
jdbc:postgresql://<Endpoint1>:<Port1>,<Endpoint2>:<Port2>,<Endpoint3>:<Port3>.../<DBNAME>?user=<AccessKey ID>&password=<AccessKey Secret>&targetServerType=any&loadBalanceHosts=<value>[&hostRecheckSeconds=<value>]
參數說明
參數 | 描述 |
Endpoint | Hologres執行個體的網路地址。 進入Hologres管理主控台的執行個體詳情頁擷取網路地址。 |
Port | Hologres執行個體的連接埠。 進入Hologres管理主控台的執行個體詳情頁擷取連接埠。 |
DBNAME | Hologres建立的資料庫名稱。 |
AccessKey ID | 當前阿里雲帳號的AccessKey ID。 您可以單擊AccessKey 管理,擷取AccessKey ID。 |
AccessKey Secret | 當前阿里雲帳號的AccessKey Secret。 您可以單擊AccessKey 管理,擷取AccessKey Secret。 |
targetServerType | 允許串連到指定狀態的唯讀從執行個體。取值為 僅Hologres V2.0.10及以上版本支援如下取值:
JDBC會根據GUC參數
|
loadBalanceHosts | 指定嘗試串連唯讀從執行個體的順序,取值如下:
|
hostRecheckSeconds | 可串連Endpoint列表的緩衝時間,預設為 若您希望調整該緩衝的時間,可以修改
|
關於更多JDBC配置說明,詳情請參見JDBC的手冊。
使用樣本
如下樣本會將查詢隨機分發到三個唯讀從執行個體上,並且當其中一個執行個體串連失敗時,JDBC會自動嘗試切換到另一個執行個體串連。
import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Properties; public class hatest { public static void main(String[] args) { // 設定Hologres執行個體的串連endpoint,唯讀從執行個體1 String endpoint1 = "hgpostcn-cn-wxxxxxxxx01-cn-shanghai.hologres.aliyuncs.com:80"; // 設定Hologres執行個體的串連endpoint,唯讀從執行個體2 String endpoint2 = "hgpostcn-cn-wxxxxxxxx02-cn-shanghai.hologres.aliyuncs.com:80"; // 設定Hologres執行個體的串連endpoint,唯讀從執行個體3 String endpoint3 = "hgpostcn-cn-wxxxxxxxx03-cn-shanghai.hologres.aliyuncs.com:80"; // 設定待串連的資料庫名 String dbname = "postgres"; String jdbcUrl = "jdbc:postgresql://" + endpoint1 + "," + endpoint2 + "," + endpoint3 + "/" + dbname; Properties properties = new Properties(); // 設定串連資料庫的使用者名稱 properties.setProperty("user", "xxxx"); //設定串連資料庫的密碼 properties.setProperty("password", "xxxx"); // 配置targetServerType,此處配置為any,表示可以對任意endpoint發送請求 properties.setProperty("targetServerType", "any"); // 配置LoadBalance策略,此處配置true,表示開啟LoadBalance properties.setProperty("loadBalanceHosts", "true"); // 配置hostRecheckSeconds時間,此處配置為10秒 properties.setProperty("hostRecheckSeconds", "10"); try { Class.forName("org.postgresql.Driver"); Connection connection = DriverManager.getConnection(jdbcUrl, properties); PreparedStatement preparedStatement = connection.prepareStatement("show hg_frontend_endpoints;" ); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { ResultSetMetaData rsmd = resultSet.getMetaData(); int columnCount = rsmd.getColumnCount(); Map map = new HashMap(); for (int i = 0; i < columnCount; i++) { map.put(rsmd.getColumnName(i + 1).toLowerCase(), resultSet.getObject(i + 1)); } System.out.println(map); } } catch (Exception exception) { exception.printStackTrace(); } } }
如下樣本可以將查詢輪詢100次分發到2個執行個體上。
import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Properties; public class hatest { public static void main(String[] args) { int x = 1; while( x <= 100 ){ // 設定Hologres執行個體的串連endpoint,主執行個體 String endpoint1 = "hgpostcn-cn-wxxxxxxxx04-cn-hangzhou.hologres.aliyuncs.com:80"; // 設定Hologres執行個體的串連endpoint,唯讀從執行個體 String endpoint2 = "hgpostcn-cn-wxxxxxxxx05-cn-hangzhou.hologres.aliyuncs.com:80"; // 設定待串連的資料庫名 String dbname = "postgres"; String jdbcUrl = "jdbc:postgresql://" + endpoint1 + "," + endpoint2 + "/" + dbname ; Properties properties = new Properties(); // 設定串連資料庫的使用者名稱 properties.setProperty("user", "xxx"); // 設定串連資料庫的密碼 properties.setProperty("password", "xxx"); // 配置targetServerType,此處配置為any,表示可以對任意endpoint發送請求 properties.setProperty("targetServerType", "any"); // 配置LoadBalance策略,此處配置true,表示開啟LoadBalance properties.setProperty("loadBalanceHosts", "true"); // 配置hostRecheckSeconds時間,此處配置為10秒 properties.setProperty("hostRecheckSeconds", "10"); try { Class.forName("org.postgresql.Driver"); Connection connection = DriverManager.getConnection(jdbcUrl, properties); PreparedStatement preparedStatement = connection.prepareStatement("show hg_frontend_endpoints;" ); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { ResultSetMetaData rsmd = resultSet.getMetaData(); int columnCount = rsmd.getColumnCount(); Map map = new HashMap(); for (int i = 0; i < columnCount; i++) { map.put(rsmd.getColumnName(i + 1).toLowerCase(), resultSet.getObject(i + 1)); } System.out.println(map); } } catch (Exception exception) { exception.printStackTrace(); } x++; } } }
此時觀察兩個執行個體的監控資訊,可以看到兩個執行個體的串連數基本一致,查看執行個體的監控資訊請參見查看監控指標。
執行個體hgpostcn-cn-wxxxxxxxx04的監控資訊。
執行個體hgpostcn-cn-wxxxxxxxx05的監控資訊。