配置连接池

某些 Cloud Bigtable 客户端库允许您配置客户端的连接池(也称为通道池)中 gRPC 通道的数量。在大多数情况下,默认配置是正确的,无需更改。

当您使用 Java 版 Cloud Bigtable 客户端库 2.23.0 或更高版本,以及使用 Java 版 Cloud Bigtable HBase 客户端 2.9.1 或更高版本时,系统会根据需要自动调整连接池的大小。

本页面介绍如何为应用确定最佳连接池大小,并提供了展示如何配置连接池的代码段。

在阅读本页之前,请阅读 Bigtable 连接池概览,了解连接池的工作原理以及是否应更改连接池。

以下客户端库提供连接池,允许您配置池数:

确定最佳连接池大小

理想情况下,要为流量波动留出余量,连接池的连接数应为达到最大饱和量所需连接数的两倍。由于一个连接最多可以处理 100 个并发请求,因此每个连接 10 到 50 个待处理请求是最佳情况。连接池中对此概念进行了更详细的说明。

进行更改后监控流量,并在必要时调整池中的连接数。

以下步骤可帮助您使用客户端指标(例如 OpenCensus 提供的指标)来计算通道池中的最佳连接数。

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

这些步骤可用以下公式表示:

  • (以秒为单位的 QPS ÷ (1000 ÷ 以毫秒为单位的延迟时间)) ÷ 50 个数据流 = 最佳连接数的下限

  • (以秒为单位的 QPS ÷ (1000 ÷ 以毫秒为单位的延迟时间)) ÷ 10 个数据流 = 最佳连接数的上限

示例

您的应用通常每秒发送 50,000 个请求,平均延迟时间为 10 毫秒。那么,用 1000 除以 10 毫秒便可以确定您每秒可连续发送 100 个请求。用 50000 除以该数字便可得到发送 50000 QPS 所需的并行处理数量:500。每个通道最多可以并行发出 100 个请求,并且目标通道利用率在 10 到 50 个并发流之间。因此,如需计算下限值,用 500 除以 50,即为 10。如需得到上限值,用 500 除以 10,即为 50。这意味着此示例中的通道池大小应介于 10 到 50 个连接之间。

设置池大小

以下代码示例演示了如何在客户端库中配置池数,使您可以设置池大小。

Go

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/bigtable"
	"google.golang.org/api/option"
)

func configureConnectionPool(w io.Writer, projectID, instanceID string) error {
	// projectID := "my-project-id"
	// instanceID := "my-instance-id"
	ctx := context.Background()

	// Set up Bigtable data operations client.
	poolSize := 10
	client, err := bigtable.NewClient(ctx, projectID, instanceID, option.WithGRPCConnectionPool(poolSize))
	defer client.Close()

	if err != nil {
		return fmt.Errorf("bigtable.NewClient: %w", err)
	}

	fmt.Fprintf(w, "Connected with pool size of %d", poolSize)

	return nil
}

HBase

此示例仅适用于自动调整大小功能引入之前的客户端库版本(2.9.1 之前)。



import static com.google.cloud.bigtable.hbase.BigtableOptionsFactory.BIGTABLE_DATA_CHANNEL_COUNT_KEY;

import com.google.cloud.bigtable.hbase.BigtableConfiguration;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Connection;

public class ConfigureConnectionPool {

  public static void configureConnectionPool(String projectId, String instanceId) {
    // String projectId = "my-project-id";
    // String instanceId = "my-instance-id";
    Configuration config = BigtableConfiguration.configure(projectId, instanceId);
    config.setInt(BIGTABLE_DATA_CHANNEL_COUNT_KEY, 10);
    try (Connection connection = BigtableConfiguration.connect(config)) {
      int poolSize = connection.getConfiguration().getInt(BIGTABLE_DATA_CHANNEL_COUNT_KEY, 0);

      System.out.println(String.format("Connected with pool size of %d", poolSize));
    } catch (Exception e) {
      System.out.println("Error during ConfigureConnectionPool: \n" + e.toString());
    }
  }
}

Java

此示例仅适用于 2.23.0 之前的客户端库版本(自动调整大小功能在此版本中引入)。


import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
import com.google.cloud.bigtable.data.v2.BigtableDataClient;
import com.google.cloud.bigtable.data.v2.BigtableDataSettings;
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings;
import java.io.IOException;

public class ConfigureConnectionPool {

  public static void configureConnectionPool(String projectId, String instanceId) {
    // String projectId = "my-project-id";
    // String instanceId = "my-instance-id";

    BigtableDataSettings.Builder settingsBuilder =
        BigtableDataSettings.newBuilder().setProjectId(projectId).setInstanceId(instanceId);

    settingsBuilder
        .stubSettings()
        .setTransportChannelProvider(
            EnhancedBigtableStubSettings.defaultGrpcTransportProviderBuilder()
                .setPoolSize(10)
                .build());

    BigtableDataSettings settings = settingsBuilder.build();
    try (BigtableDataClient dataClient = BigtableDataClient.create(settings)) {
      InstantiatingGrpcChannelProvider provider =
          (InstantiatingGrpcChannelProvider)
              settings.getStubSettings().getTransportChannelProvider();

      int poolSize = provider.toBuilder().getPoolSize();

      System.out.println(String.format("Connected with pool size of %d", poolSize));
    } catch (IOException e) {
      System.out.println("Error during ConfigureConnectionPool: \n" + e.toString());
    }
  }
}

C++

namespace cbt = ::google::cloud::bigtable;
namespace gc = ::google::cloud;
[](std::string const& project_id, std::string const& instance_id,
   std::string const& table_id) {
  auto constexpr kPoolSize = 10;
  auto options = gc::Options{}.set<gc::GrpcNumChannelsOption>(kPoolSize);
  cbt::Table table(cbt::MakeDataConnection(options),
                   cbt::TableResource(project_id, instance_id, table_id));
  std::cout << "Connected with channel pool size of " << kPoolSize << "\n";
}