接続プールの構成

一部の Cloud Bigtable クライアント ライブラリでは、クライアントの接続プール(チャネルプールとも呼ばれます)内の gRPC チャネルの数を構成できます。ほとんどの場合、デフォルトの構成は適切であり、変更する必要はありません。

Java バージョン 2.23.0 以降用の Cloud Bigtable クライアント ライブラリを使用する場合、および Java バージョン 2.9.1 以降用の Cloud Bigtable HBase クライアントを使用する場合、接続プールは必要に応じて自動的にサイズ変更されます。

このページでは、アプリケーションに最適な接続プールサイズを決定する方法について説明し、接続プールの構成方法を表すコード スニペットも示します。

このページを読む前に、Bigtable 接続プールの概要をご覧になり、プールの仕組みと変更する必要があるかどうかを確認してください。

次のクライアント ライブラリでは、接続プールが提供され、プールの数を構成できます。

最適な接続プールサイズを決定する

理想としては、トラフィック変動のために余裕を持たせ、接続プールを最大の飽和状態に必要な接続数のおよそ 2 倍にします。接続は最大 100 件の同時リクエストを処理できるため、接続あたり 10~50 件のリクエストが最適です。このコンセプトの詳細については、接続プールをご覧ください。

変更後にトラフィックをモニタリングし、必要に応じてプール内の接続数を調整します。

以下の手順は、OpenCensus から入手できるクライアント側の指標を使用して、チャネルプール内の最適な接続数を計算するのに役立ちます。

  1. クライアント側の指標から、次の情報を収集します。
    1. アプリケーションが一般的なワークロードを実行しているときのクライアントごとの秒間クエリ(QPS)の最大数。
    2. ミリ秒での平均レイテンシ(単一のリクエストのレスポンス時間)。
  2. 1,000 を平均レイテンシ値で割って、1 秒あたりに順次送信できるリクエスト数を確認します。
  3. 秒単位の QPS を 1 秒あたりの連続リクエスト数で割ります。
  4. その結果をチャネルあたり 50 リクエストで割り、最小の最適なチャネルプール サイズを決定します(計算結果が 2 未満の場合は、冗長性を確保するために少なくとも 2 つのチャネルを使用してください)。
  5. 同じ結果をチャネルごとに 10 リクエストで割り、最大の最適なチャネルプール サイズを決定します。

これらの手順は、次の式で表されます。

  • (QPS 秒 ÷ (1,000 ÷ ミリ秒単位のレイテンシ)) ÷ 50 ストリーム = 最適な最小接続数

  • (QPS 秒 ÷ (1,000 ÷ ミリ秒単位のレイテンシ)) ÷ 10 ストリーム = 最適な最大接続数

アプリケーションが通常 1 秒あたり 50,000 件のリクエストを送信し、平均レイテンシが 10 ミリ秒です。1,000 を 10 ミリ秒で割り、1 秒あたり 100 件のリクエストを順次送信できることを確認します。その数を 50,000 で割り、50,000 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";
}