使用 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 参数指定 username 和 password:

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

在开始使用 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 "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)

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