将 gRPC 与 Java 客户端库搭配使用

Datastore 模式的 Java 客户端提供 gRPC 作为传输层选项。使用 gRPC 连接池可在多个连接之间分配 RPC,从而提高性能。

准备工作

安装最新版本的 google-cloud-datastore 库。

如何启用 gRPC 传输行为

如需启用 gRPC 传输行为,请在客户端实例化中添加 setTransportOptions

Java
DatastoreOptions datastoreOptions =
       DatastoreOptions.newBuilder()
               .setProjectId("my-project")
               .setDatabaseId("my-database")
               .setTransportOptions(GrpcTransportOptions.newBuilder().build())
               .build();

将传输选项显式设置为 GrpcTransportOptions 会将客户端配置为在调用服务器时使用 gRPC 而不是 HTTP。

停用 gRPC 传输行为

您可以恢复为 HTTP 传输行为,以停用 gRPC 传输行为。为此,请移除 .setTransportOptions 代码行或将 GrpcTransportOptions 替换为 HttpTransportOptions。您还必须重新构建并重新启动应用。

Java
// Use this code to deactivate the gRPC transport behavior
// by reverting to the HTTP transport behavior.
DatastoreOptions datastoreOptions = DatastoreOptions.newBuilder()
            .setProjectId("my-project")
            .setDatabaseId("my-database")
            .build();

// You can also use this code to revert to the HTTP transport behavior
DatastoreOptions datastoreOptions =
            DatastoreOptions.newBuilder()
                    .setProjectId("my-project")
                    .setDatabaseId("my-database")
                    .setTransportOptions(HttpTransportOptions.newBuilder()
                            .setConnectTimeout(1000)
                            .build())
                    .build();

验证运输选项

如需验证客户端使用的 TransportOptions 类型,请检查传输选项类型:

Java
// Compares datastore transport options type

boolean isGRPC = datastore.getOptions().getTransportOptions() instanceof GrpcTransportOptions;

boolean isHTTP = datastore.getOptions().getTransportOptions() instanceof HTTPTransportOptions;

连接池配置

连接池(也称为通道池)是可共享和重复使用的数据库连接的缓存,可用于改善连接延迟和性能。如需提升应用性能,请配置连接池。

本部分将帮助您确定最佳连接池大小,并演示如何在 Java 客户端库中配置连接池。

确定最佳连接池大小

默认连接池大小适用于大多数应用,在大多数情况下无需更改。 不过,您可能需要因吞吐量高或缓冲请求而更改连接池大小。

理想情况下,要为流量波动留出余量,连接池的连接数应为达到最大饱和量所需连接数的两倍。由于一个连接最多可以处理 100 个并发请求,因此我们建议您每个连接有 10 到 50 个待处理请求。中间件层强制执行每个 gRPC 连接 100 个并发流的限制,并且此限制不可配置。如需使用估计的每客户端 QPS 和平均延迟时间来计算连接池中的最佳连接数,请执行以下操作:

从客户端指标中收集以下信息并进行以下计算:

  1. 确定应用运行工作负载时每个客户端的每秒查询次数 (QPS) 上限。
  2. 确定以毫秒为单位的平均延迟时间(单个请求的响应时间)。
  3. 用 1000 除以平均延迟时间值,确定每秒可连续发送的请求数。
  4. 用 QPS(以秒为单位)除以每秒串行请求数。
  5. 用结果除以每个通道 50 个请求,确定最佳连接池大小的下限。(如果计算结果小于 2,仍需至少使用 2 个通道,以确保冗余。)
  6. 用相同结果除以每个通道 10 个请求,确定最佳连接池大小的上限。

如需执行这些步骤,请使用以下等式:

(QPS sec ÷ (1,000 ÷ latency ms)) ÷ 50 streams = Minimum optimal number of
connections

(QPS sec ÷ (1,000 ÷ latency ms)) ÷ 10 streams = Maximum optimal number of
connections

例如,如果您的应用通常每秒发送 50,000 个请求,平均延迟时间为 10 毫秒。那么,用 1000 除以 10 毫秒便可以确定您每秒可连续发送 100 个请求。用 50000 除以该数字便可得到发送 50000 QPS 所需的并行处理数量:500。

每个通道最多可以并行发出 100 个请求,并且目标通道利用率在 10 到 50 个并发流之间。因此,如需计算连接池大小的下限值,用 500 除以 50,即为 10。如需得到连接池大小上限,用 500 除以 10,即为 50。

这意味着此示例中的连接池大小介于 10 到 50 个连接之间。此外,在进行这些更改后,请务必监控流量,并在必要时调整池中的连接数。

设置池大小

以下代码示例演示了如何使用 DatastoreOptions 在客户端库中配置连接池。

Java
InstantiatingGrpcChannelProvider channelProvider =
        DatastoreSettings.defaultGrpcTransportProviderBuilder()
                .setChannelPoolSettings(
                       ChannelPoolSettings.builder()
                                .setInitialChannelCount(MIN_VAL)
                                .setMaxChannelCount(MAX_VAL)
                                .build())
                .build();

DatastoreOptions options = DatastoreOptions.newBuilder()
         .setProjectId("my-project")
         .setChannelProvider(channelProvider)
         .setTransportOptions(GrpcTransportOptions.newBuilder().build())
         .build();

后续步骤

如需详细了解连接池和性能最佳实践,请参阅: