使用 PGAdapter 进行连接

本文档介绍了如何使用 PGAdapter 连接到 Spanner Omni。您可以配置 PGAdapter 以建立安全连接。 PGAdapter 支持纯文本、 传输层安全协议 (TLS)、 和 双向 TLS (mTLS) 安全模式。这些模式通过提供不同级别的加密和身份验证来保护传输中的数据。每种安全模式都需要特定的客户端配置,以确保数据完整性和机密性。

您可以将 PGAdapter 作为独立进程运行,也可以将其直接集成到应用中。如需进行交互式管理和手动查询执行,请使用 psql 等标准 PostgreSQL 工具连接到数据库。如需构建自动化应用,请使用与 PostgreSQL 兼容的驱动程序,例如:

如需查看使用其中一些驱动程序的代码示例,请参阅本文档中的 示例代码。

安全模式

Spanner Omni PGAdapter 支持三种安全模式,这些模式定义了 PGAdapter 与数据库之间的通信加密和身份验证方式。如需使用这些模式,请按照下表中的说明配置客户端选项:

安全模式 说明
纯文本 通信未加密。
TLS 通信使用传输层安全协议 (TLS) 加密。此 模式要求您将 Spanner Omni CA 证书添加到 默认 Java 信任库。
mTLS 通信使用双向 TLS (mTLS) 加密。此模式要求您提供客户端证书和客户端私钥。

作为独立进程运行

对于非 Java 应用和标准 PostgreSQL 工具(例如 psql),当您需要手动数据库交互时,请将 PGAdapter 作为独立进程运行。这种方法将代理与应用生命周期分离,让您可以独立管理和更新代理。如需将 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 应用的进程中以 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 连接,请使用此配置:

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)

您可以使用 psycopg2psycopg3 连接到 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();