启动 PGAdapter

本页面介绍了如何在 Spanner 中启动 PGAdapter。如需了解 PGAdapter,请参阅关于 PGAdapter。如需获取 PGAdapter 二进制文件,请参阅获取 PGAdapter

您可以通过以下方式启动 PGAdapter:

  • 作为独立进程
  • 在 Docker 容器内
  • 在 Cloud Run 上
  • 将 PGAdapter 用作边车代理(例如,在 Kubernetes 集群中)
  • 与 Java 应用一起启动

准备工作

在启动 PGAdapter 之前,请确保您已在运行 PGAdapter 的机器上通过用户账号或服务账号进行了身份验证。如果您使用的是服务账号,则必须知道 JSON 密钥文件(凭证文件)的位置。然后,您可以使用 PGAdapter -c 选项或通过设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量来指定凭证路径。

有关详情,请参阅:

选择运行 PGAdapter 的方法

您可以将 PGAdapter 作为独立进程启动、在 Docker 容器内启动、在 Cloud Run 上启动,或者是在 Java 应用的进程内启动。启动 PGAdapter 时,您需要指定要连接到的项目、Spanner 实例和数据库。 您还可以指定 JSON 格式的凭证文件(密钥文件)的路径。

独立

使用以下命令下载 PGAdapter。

    wget https://storage.googleapis.com/pgadapter-jar-releases/pgadapter.tar.gz \
    && tar -xzvf pgadapter.tar.gz
    

使用以下命令启动 PGAdapter。

    java -jar pgadapter.jar -p PROJECT_NAME -i INSTANCE_NAME -d DATABASE_NAME \
    -c CREDENTIALS_FILE_PATH \
    ADDITIONAL_OPTIONS
    

以下选项为必需:

-p project_name
Spanner 数据库在其中运行的项目的名称。
-i instance_name
Spanner 实例名称。
-d database_name
:要连接到的数据库名称。

以下选项为可选:

-r databaseRole=database_role
要用于会话的数据库角色。 如需了解详情,请参阅使用 PGAdapter 进行授权
-c credentials_file_path
包含 JSON 格式的服务账号凭证的密钥文件完整路径。如果未设置此选项,则系统会从 GOOGLE_APPLICATION_CREDENTIALS 环境变量指定的路径中读取凭证。

如需了解如何创建服务账号并下载 JSON 格式的密钥文件,请参阅 创建服务账号

请确保您向服务账号授予足够的凭证,以允许其访问数据库。

如果您先使用以下命令通过 Google Cloud CLI 进行身份验证,则可以省略此选项:

gcloud auth application-default login

如需了解详情,请参阅 设置身份验证和授权

-s port
PGAdapter 侦听的端口。默认为 5432(即默认的 PostgreSQL 端口)。
-v version_number

要在连接过程中公开给客户端的 PostgreSQL 的版本号。默认值为 14.1。

某些 PostgreSQL 应用和驱动程序会根据此版本号启用额外的功能。Spanner 可能并不支持这些功能。 如需查看支持的客户端的完整列表,请参阅 驱动程序和客户端

-x

启用 localhost 以外的主机发起的连接。在独立模式下启动 PGAdapter 时,请勿使用此项。只有在 Docker 容器内启动时才能使用。

默认情况下,出于安全考虑,PGAdapter 仅接受 localhost 发起的连接。

以下示例使用默认应用凭证在端口 5432 上以独立模式启动 PGAdapter。

java -jar pgadapter.jar \
-p my-project \
-i my-instance \
-d my-database \
-s 5432

Docker

使用以下命令启动 PGAdapter。

docker run -d -p HOST-PORT:DOCKER-PORT \
-v CREDENTIALS_FILE_PATH:/acct_credentials.json \
gcr.io/cloud-spanner-pg-adapter/pgadapter:latest \
-p PROJECT_NAME -i INSTANCE_NAME -d DATABASE_NAME  \
-c /acct_credentials.json -x OTHER_PGAdapter_OPTIONS

除了用于指定项目、实例、数据库和凭证的 PGAdapter 选项之外,还需要使用以下选项:

-p 127.0.0.1:HOST-PORT:DOCKER-PORT

此 Docker 选项会将 Docker 容器内部的端口 DOCKER-PORT 映射到容器外部的端口 HOST-PORTDOCKER-PORT 必须与 PGAdapter 在容器内部的配置方式相匹配。默认值为 5432。HOST-PORT 是 Docker 应在容器外部监听连接请求的端口。它必须始终是 localhost 上的可用端口。

如需了解详情,请参阅 Docker 文档中的发布或公开端口(-p、--expos)

-v CREDENTIALS_FILE_PATH:in_container_mount_point

此 Docker 选项绑定会装载一个共享卷。它将容器外部的主机路径映射到容器内的一个卷(装载点)。主机路径和容器路径之间使用英文冒号 (:) 分隔。

通过此选项,PGAdapter 可以访问容器之外的 JSON 凭证文件。在前面的示例中,-c 选项引用容器内的装载点。此示例将容器内装载点命名为 /acct_credentials.json。您可以随意为其命名。

如需了解详情,请参阅 Docker 文档中的卷(共享文件系统)

-x

启用 localhost 以外的主机发起的连接。之所以需要这样做,是因为映射到主机端口的容器内部端口不会对 PGAdapter 显示为 localhost。

以下选项为可选:

-r databaseRole=database_role
要用于会话的数据库角色。 如需了解详情,请参阅使用 PGAdapter 进行授权

在以下示例中,Docker 端口和主机端口均设置为 PostgreSQL 数据库服务默认端口 5432。

docker run -d -p 127.0.0.1:5432:5432 \
-v /tmp/credentials.json:/acct_credentials.json \
gcr.io/cloud-spanner-pg-adapter/pgadapter:latest \
-p my_project -i my_instance -d my_database \
-c /acct_credentials.json -x

Cloud Run

您无法在 Cloud Run 上将 PGAdapter 部署为独立服务,但可以将其部署为边车代理。

与将 PGAdapter 作为单独的服务运行相比,我们建议以边车模式运行它,原因如下:
  • 防止出现单点故障;每个应用对您的数据库的访问都独立于其他应用,从而提高其弹性。
  • PGAdapter 实例的数量会随着应用实例的数量自动线性扩缩。

PGAdapter GitHub 代码库包含多个 使用 Cloud Run 和 PGAdapter 作为边车代理的有效示例应用,这些应用采用各种编程语言。

以下配置文件展示了如何将 PGAdapter 添加为 Cloud Run 的边车代理:

  apiVersion: serving.knative.dev/v1
  kind: Service
  metadata:
  annotations:
    # This example uses an in-memory volume for Unix domain sockets.
    # This is a Cloud Run beta feature.
    run.googleapis.com/launch-stage: BETA
  name: pgadapter-sidecar-example
  spec:
  template:
    metadata:
      annotations:
        run.googleapis.com/execution-environment: gen1
        # This registers 'pgadapter' as a dependency of 'app' and ensures that pgadapter starts
        # before the app container.
        run.googleapis.com/container-dependencies: '{"app":["pgadapter"]}'
    spec:
      # Create an in-memory volume that can be used for Unix domain sockets.
      volumes:
        - name: sockets-dir
          emptyDir:
            # This directory contains the virtual socket files that are used to
            # communicate between your application and PGAdapter.
            sizeLimit: 50Mi
            medium: Memory
      containers:
        # This is the main application container.
        - name: app
          # Example: europe-north1-docker.pkg.dev/my-test-project/cloud-run-source-deploy/pgadapter-sidecar-example
          image: MY-REGION.pkg.dev/MY-PROJECT/cloud-run-source-deploy/pgadapter-sidecar-example
          # The PGADAPTER_HOST variable is set to point to /sockets, which is the shared in-memory
          # volume that is used for Unix domain sockets.
          env:
            - name: SPANNER_PROJECT
              value: my-project
            - name: SPANNER_INSTANCE
              value: my-instance
            - name: SPANNER_DATABASE
              value: my-database
            - name: PGADAPTER_HOST
              value: /sockets
            - name: PGADAPTER_PORT
              value: "5432"
          ports:
            - containerPort: 8080
          volumeMounts:
            - mountPath: /sockets
              name: sockets-dir
        # This is the PGAdapter sidecar container.
        - name: pgadapter
          image: gcr.io/cloud-spanner-pg-adapter/pgadapter
          volumeMounts:
            - mountPath: /sockets
              name: sockets-dir
          args:
            - -dir /sockets
            - -x
          # Add a startup probe that checks that PGAdapter is listening on port 5432.
          startupProbe:
            initialDelaySeconds: 10
            timeoutSeconds: 10
            periodSeconds: 10
            failureThreshold: 3
            tcpSocket:
              port: 5432
  

边车代理

您可以在 Kubernetes 集群等环境中将 PGAdapter 用作边车代理。Kubernetes 边车容器与 Pod 中的主容器并行运行。

与将 PGAdapter 作为单独的服务运行相比,我们建议以边车模式运行它,原因如下:

  • 防止出现单点故障;每个应用对您的数据库的访问都独立于其他应用,从而提高其弹性。
  • 由于 PGAdapter 会根据用量以线性方式使用资源,因此此模式可让您更准确地确定资源范围,并按应用扩缩情况请求资源。

以下配置文件展示了如何将 PGAdapter 添加为 Kubernetes 集群的边车代理:

containers:
- name: pgadapter
image: gcr.io/cloud-spanner-pg-adapter/pgadapter
ports:
  - containerPort: 5432
args:
  - "-p my-project"
  - "-i my-instance"
  - "-d my-database"
  - "-x"
resources:
  requests:
    # PGAdapter's memory use scales linearly with the number of active
    # connections. Fewer open connections will use less memory. Adjust
    # this value based on your application's requirements.
    memory: "512Mi"
    # PGAdapter's CPU use scales linearly with the amount of IO between
    # the database and the application. Adjust this value based on your
    # application's requirements.
    cpu: "1"

PGAdapter GitHub 代码库包含分步指南和示例应用。 此示例包含有关将 Workload Identity Federation for GKE 与 PGAdapter 搭配使用的说明。

Java 进程中

使用您的 Java 代码创建并启动 PGAdapter 实例。 这是建议用于 Java 应用的设置。

如果您使用的是服务账号进行身份验证,请确保 GOOGLE_APPLICATION_CREDENTIALS 环境变量设置为凭证文件的路径。

  1. google-cloud-spanner-pgadapter 作为依赖项添加到您的项目中。 如需了解详情,请参阅获取 PGAdapter
  2. 使用 com.google.cloud.spanner.pgadapter.ProxyServer 类构建一个服务器。
  3. /**
    * Starts PGAdapter in-process and returns a reference to the server. Use this reference to
    * gracefully shut down the server when your application shuts down.
    *
    * @param project the Google Cloud project that PGAdapter should connect to
    * @param instance the Spanner instance that PGAdapter should connect to
    * @param credentialsFile the full path of a credentials file that PGAdapter should use, or 
    *     null if PGAdapter should use the application default credentials
    */
    static Server startPGAdapter(String project, String instance, String credentialsFile) {
    OptionsMetadata.Builder builder =
        OptionsMetadata.newBuilder()
            .setProject(project)
            .setInstance(instance)
            // Start PGAdapter on any available port.
            .setPort(0);
    if (credentialsFile != null) {
      builder.setCredentialsFile(credentialsFile);
    }
    ProxyServer server = new ProxyServer(builder.build());
    server.startServer();
    server.awaitRunning();
    
    return new PGAdapter(server);
    }

PGAdapter GitHub 代码库包含一个完整的示例应用

PGAdapter 边车代理的资源分配指南

以下准则可帮助您为 PGAdapter 边车代理配置 CPU 和内存资源。最佳值因具体工作负载而异。

内存

由于 PGAdapter 不会缓存太多数据,因此需要内存来将查询结果从 Spanner gRPC 格式转换为 PostgreSQL 有线协议格式。对于具有大型二进制列的工作负载,这一点尤其重要,因为 Spanner 和 PostgreSQL 处理这些数据类型的方式不同。

如需确定要分配的内存量,请使用以下内存分配公式,其中 <var>number of concurrent connections</var> 是应用处理的并发连接数:

384 MB + (2 MB * number of concurrent connections)

例如,如果您的应用处理 200 个并发连接,请分配大约 784 MB 的内存:

384 MB + (2 MB * 200) = 784 MB

从这个基准内存分配开始。在实际负载下监控其使用情况,以根据您的具体需求微调该值。

CPU

PGAdapter 不会占用大量 CPU。这是因为其主要作用是充当直通代理。不过,CPU 使用率会随着发送和接收的数据量而增加。

分配 CPU 时,请考虑以下因素:

  • 工作负载:执行返回大量数据的查询的应用,与仅返回少量行和列的应用相比,每个连接需要更多的 CPU 功率。
  • 应用访问模式:如果应用以同步方式访问 Spanner,则在等待来自代理的数据时处于空闲状态。在这种情况下,应用和代理不太可能争用 CPU 资源。

从基准 CPU 分配开始。在实际负载下监控其使用情况,以便根据您的具体需求微调该值。

后续步骤