本文說明如何使用 PGAdapter 連線至 Spanner Omni。設定 PGAdapter 以建立安全連線。 PGAdapter 支援純文字、傳輸層安全標準 (TLS) 和相互 TLS (mTLS) 安全模式。這些模式提供不同程度的加密和驗證,可在傳輸期間保護資料。每種安全模式都需要特定的用戶端設定,才能確保資料完整性和機密性。
您可以將 PGAdapter 當做獨立程序執行,也可以直接整合到應用程式中。如要進行互動式管理及手動執行查詢,請使用標準 PostgreSQL 工具 (例如 psql) 連線至資料庫。如要建構自動化應用程式,請使用與 PostgreSQL 相容的驅動程式,例如:
pgxfor Gopsycopg3for Pythonnode-postgresfor Node.js
如需使用部分驅動程式的程式碼範例,請參閱本文中的程式碼範例。
安全模式
Spanner Omni PGAdapter 支援三種安全模式,可定義 PGAdapter 與資料庫之間的通訊加密和驗證方式。如要使用這些模式,請按照下表說明設定用戶端選項:
| 安全模式 | 說明 |
|---|---|
| 純文字 | 通訊內容未加密。 |
| TLS | 通訊內容會使用傳輸層安全標準 (TLS) 加密。這個模式需要將 Spanner Omni CA 憑證新增至預設的 Java 信任存放區。 |
| mTLS | 通訊會使用相互傳輸層安全標準 (mTLS) 加密。這個模式需要您提供用戶端憑證和用戶端私鑰。 |
以獨立程序執行
如要手動與資料庫互動,請為非 Java 應用程式和標準 PostgreSQL 工具 (例如 psql) 執行 PGAdapter 做為獨立程序。這種做法可將 Proxy 與應用程式生命週期分離,讓您獨立管理及更新 Proxy。如要以獨立程序啟動 PGAdapter,請根據所選安全模式使用下列設定方法。
使用純文字模式
如要在純文字通訊模式下啟動 PGAdapter,請執行下列指令:
java -jar pgadapter.jar \
-d DATABASE_ID \
-e ENDPOINT \
-r "isExperimentalHost=true;usePlainText=true"
更改下列內容:
DATABASE_ID:Spanner Omni 資料庫的 ID,例如test-db。ENDPOINT:Spanner Omni 執行個體的端點,例如localhost:15000。
使用 TLS 模式
如要透過 Java 應用程式以傳輸層安全標準:TLS 模式啟動程序內 PGAdapter,必須先將 Spanner Omni CA 憑證新增至預設 Java 信任儲存庫。如要將現有 CA 憑證新增至 Java 信任儲存區,請執行下列指令:
sudo keytool -import -trustcacerts -file ~/.spanner/certs/ca.crt -alias spanner-ca -keystore $JAVA_HOME/lib/security/cacerts
如要在 TLS 模式下啟動 PGAdapter,請執行下列指令:
java -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
-Djavax.net.ssl.trustStoreType=JKS \
-jar pgadapter.jar \
-d DATABASE_ID \
-e ENDPOINT \
-r "isExperimentalHost=true"
使用 mTLS 模式
如要在 mTLS 模式下啟動 PGAdapter,請務必確認用戶端金鑰採用 PKCS#8 格式。如要將金鑰儲存區中的現有金鑰轉換為 PKCS#8 格式,請執行下列指令:
openssl pkcs8 -topk8 -in ~/.spanner/certs/client.key -out ~/.spanner/certs/java-client.key -nocrypt
或者,使用 Spanner Omni CLI 建立用戶端憑證和金鑰時,請提供 --generate-pkcs8-key 參數,以 PKCS#8 格式產生金鑰。
如要在 mTLS 模式下啟動 PGAdapter,請執行下列指令:
java -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
-Djavax.net.ssl.trustStoreType=JKS \
-jar pgadapter.jar \
-d DATABASE_ID \
-e ENDPOINT \
-r "isExperimentalHost=true;clientCertificate=PATH_TO_CLIENT_CERT;clientKey=PATH_TO_CLIENT_KEY"
更改下列內容:
PATH_TO_CLIENT_CERT:用戶端憑證檔案的路徑。PATH_TO_CLIENT_KEY:用戶端金鑰檔案的路徑。
與「psql」聯絡
使用上述任一方法建立連線後,請執行 psql 管理資料庫及執行查詢。如要連線至 psql,請使用下列指令:
psql -h PG_HOST -p PG_PORT -U USERNAME -d DATABASE_ID
更改下列內容:
PG_HOST:執行 PGAdapter 的電腦主機名稱或 IP 位址。如要在本機執行,請使用localhost。PG_PORT:PGAdapter 執行的通訊埠編號。如果您未指定自訂通訊埠,PGAdapter 預設會使用通訊埠5432。USERNAME:您的 PostgreSQL 使用者名稱。
在應用程式中以程序內執行
您也可以在應用程式中啟動 PGAdapter。如要建立安全性,請設定 OptionsMetadata 物件。
使用純文字模式
如要進行純文字通訊,例如在本機開發或在安全環境中測試,且不需要加密額外負荷,請使用下列設定:
OptionsMetadata.Builder builder =
OptionsMetadata.newBuilder()
.setEndpoint("ENDPOINT")
.setUsePlainText();
ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();
使用 TLS 模式
如要在本機開發或測試等環境中使用純文字通訊,請使用下列設定:
sudo keytool -import -trustcacerts -file /.spanner/certs/ca.crt -alias spanner-ca -keystore $JAVA_HOME/lib/security/cacerts
如要在程序中建立 TLS 連線,請使用下列設定:
OptionsMetadata.Builder builder =
OptionsMetadata.newBuilder()
.setEndpoint("ENDPOINT");
ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();
使用 mTLS 模式
如要使用 Java 應用程式以程序內模式啟動 PGAdapter,請務必確認用戶端金鑰為 PKCS#8 格式。如要將金鑰儲存區中的現有金鑰轉換為 PKCS#8 格式,請執行下列指令:
openssl pkcs8 -topk8 -in ~/.spanner/certs/client.key -out ~/.spanner/certs/java-client.key -nocrypt
或者,使用 Spanner Omni CLI 建立用戶端憑證和金鑰時,請提供 --generate-pkcs8-key 參數,以 PKCS#8 格式產生金鑰。
如要在程序中建立 mTLS 連線,請使用下列設定:
OptionsMetadata.Builder builder =
OptionsMetadata.newBuilder()
.setEndpoint("ENDPOINT")
.useClientCert("PATH_TO_CLIENT_CERT", "PATH_TO_CLIENT_KEY");
ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();
程式碼範例
本節提供程式碼範例,說明如何使用下列與 PostgreSQL 相容的驅動程式,連線至 Spanner Omni 資料庫:
在連線字串中替換下列預留位置:
- PASSWORD:PostgreSQL 使用者的密碼。
JDBC
您可以使用 PostgreSQL JDBC 驅動程式連線至 PGAdapter,就像連線至 PostgreSQL 資料庫一樣。如要連線及查詢 Spanner Omni 資料庫中的資料表,請使用下列程式碼範例:
String jdbcUrl =
"jdbc:postgresql://PG_HOST:PG_PORT/DATABASE_ID";
try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
// Example: Query data
try (Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM Singers")) {
System.out.println("Query Results:");
while (resultSet.next()) {
long id = resultSet.getLong("id");
String name = resultSet.getString("name");
System.out.printf("ID: %d, Name: %s\n", id, name);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
Go (pgx)
您可以透過 pgx 連線至 PGAdapter,就像連線至 PostgreSQL 資料庫一樣。請使用下列程式碼範例:
// Database connection string
connString := "postgres://USERNAME:PASSWORD@PG_HOST:PG_PORT/DATABASE_ID?sslmode=disable"
ctx := context.Background()
// Connect to PGAdapter
conn, err := pgx.Connect(ctx, connString)
if err != nil {
log.Fatalf("Connection error: %s", err.Error())
}
defer conn.Close(ctx)
// Query all rows from the Singers table
rows, err := conn.Query(ctx, "SELECT id, name FROM Singers")
if err != nil {
log.Fatalf("Query error: %s", err.Error())
}
defer rows.Close()
// Iterate over the result set
fmt.Println("Singers Table Data:")
for rows.Next() {
var id int
var name string
if err := rows.Scan(&id, &name); err != nil {
log.Fatalf("Scan error: %s", err.Error())
}
fmt.Printf("ID: %d, Name: %s\n", id, name)
}
Python (psycopg2 或 psycopg3)
您可以透過 psycopg2 或 psycopg3 連線至 PGAdapter,就像連線至 PostgreSQL 資料庫一樣。如要連線及查詢 Spanner Omni 資料庫中的資料表,請使用下列程式碼範例:
# psycopg2
import psycopg2
connection = psycopg2.connect(database="DATABASE_ID",
host="PG_HOST",
port=PG_PORT)
cursor = connection.cursor()
cursor.execute('SELECT * FROM Singers')
for row in cursor:
print(row)
cursor.close()
connection.close()
# psycopg3
import psycopg
with psycopg.connect("host=PG_HOST port=PG_PORT dbname=DATABASE_ID sslmode=disable") as conn:
conn.autocommit = True
with conn.cursor() as cur:
cur.execute("SELECT * FROM Singers")
for row in cur:
print(row)
Node.js (node-postgres)
您可以透過 node-postgres 連線至 PGAdapter,就像連線至 PostgreSQL 資料庫一樣。如要連線及查詢 Spanner Omni 資料庫中的資料表,請使用下列程式碼範例:
const { Client } = require('pg');
const client = new Client({
host: 'PG_HOST',
port: PG_PORT,
database: 'DATABASE_ID',
});
await client.connect();
const res = await client.query("SELECT * FROM Singers");
console.log(res.rows);
await client.end();