使用 PGAdapter 进行连接

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

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

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

准备工作

如需将 PGAdapter 与 Spanner Omni 搭配使用,请使用 PGAdapter 0.55.2 版或更高版本。

如果您使用的是不含物料清单 (BOM) 的 Maven,请将以下代码添加到 pom.xml 文件依赖项中:

<dependency>
  <groupId>com.google.cloud</groupId>
  <artifactId>google-cloud-spanner-pgadapter</artifactId>
  <version>0.55.2</version>
</dependency>

安全配置

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

安全配置 说明
纯文本 通信未加密。
TLS 通信使用传输层安全协议 (TLS) 进行加密。此 配置要求您将 Spanner Omni CA 证书添加到 Java 信任库,如 配置 Java 信任库中所述。
带凭据的 TLS 通信使用 TLS 进行加密,身份验证使用用户名和密码执行 。
mTLS 通信使用双向 TLS (mTLS) 进行加密。此配置 要求您同时提供客户端证书和客户端私钥。

作为独立进程运行

对于非 Java 应用和标准 PostgreSQL 工具(例如 psql),当您需要手动数据库交互时,请将 PGAdapter 作为独立进程运行。这种方法将代理与应用生命周期分离,让您可以独立管理和更新代理。如需将 PGAdapter 作为独立进程启动,请根据所选的安全配置使用以下配置方法:

纯文本

如需使用纯文本通信启动 PGAdapter,请运行以下命令:

java -jar pgadapter.jar \
     -d DATABASE_ID \
     -e ENDPOINT \
     -r "type=omni;usePlainText=true"

替换以下内容:

  • DATABASE_ID:Spanner Omni 数据库的 ID,例如 test-db

  • ENDPOINT:Spanner Omni 实例的端点,例如 localhost:15000

TLS

如需使用 TLS 配置 PGAdapter 连接,您必须将 Spanner Omni CA 证书添加到 Java 信任库,如 配置 Java 信任库中所述。

如需使用 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 "type=omni"

带凭据的 TLS

如需使用用户名和密码身份验证建立 TLS 连接,请使用 -r 参数指定 usernamepassword

java -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
     -Djavax.net.ssl.trustStoreType=JKS \
     -jar pgadapter.jar \
     -d DATABASE_ID \
     -e ENDPOINT \
     -r "type=omni;username=USERNAME;password=PASSWORD"

替换以下内容:

  • USERNAME:Spanner Omni 用户的用户名。

  • PASSWORD:Spanner Omni 用户的密码。

mTLS

您必须先确保客户端密钥采用 PKCS#8 格式,然后才能使用 mTLS 启动 PGAdapter。如需将现有密钥转换为 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 "type=omni;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")
        .setType("omni")
        .setUsePlainText();

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

TLS

如需建立 TLS 连接,请按照 配置 Java 信任库中的说明将 CA 证书添加到 Java 信任库,并使用 以下配置:

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
        .setEndpoint("ENDPOINT")
        .setType("omni");

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

带凭据的 TLS

如需使用用户名和密码身份验证建立 TLS 连接,请使用 setProperties() 指定用户名和密码:

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
        .setEndpoint("ENDPOINT")
        .setType("omni")
        .setProperties(
            Map.of(
                "username", "USERNAME",
                "password", "PASSWORD"));

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

mTLS

如需使用 mTLS 在 Java 应用的进程中启动 PGAdapter,您的客户端密钥必须使用 PKCS#8 格式。

如需在进程中建立 mTLS 连接,请使用以下配置:

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
        .setEndpoint("ENDPOINT")
        .setType("omni")
        .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();