Configurer des pools de connexions

Certaines bibliothèques clientes Cloud Bigtable vous permettent de configurer le nombre de canaux gRPC dans le pool de connexions d'un client, également appelé "pool de canaux". Dans la plupart des cas, la configuration par défaut est correcte. Il n'est donc pas nécessaire de la modifier.

Les pools de connexions sont automatiquement redimensionnés en fonction des besoins lorsque vous utilisez la bibliothèque cliente Cloud Bigtable pour Java version 2.23.0 ou ultérieure, et le client Cloud Bigtable HBase pour Java version 2.9.1 ou ultérieure.

Cette page explique comment déterminer la taille optimale du pool de connexions de votre application. Elle présente des extraits de code qui montrent comment configurer les pools de connexions.

Avant de lire cette page, consultez la présentation des pools de connexions Bigtable pour savoir comment ils fonctionnent et si vous devez modifier les vôtres.

Les bibliothèques clientes suivantes permettent de regrouper les connexions et de configurer le nombre de pools :

Déterminer la taille appropriée des pools de connexions

Idéalement, afin de laisser de la place aux fluctuations du trafic, un pool de connexions dispose d'environ deux fois le nombre de connexions nécessaire pour atteindre une saturation maximale. Étant donné qu'une connexion peut gérer jusqu'à 100 requêtes simultanées, il est optimal d'avoir environ entre 10 et 50 requêtes en attente par connexion. Ce concept est décrit plus en détail sur la page Pools de connexions.

Surveillez le trafic après avoir apporté des modifications et ajustez le nombre de connexions dans votre pool si nécessaire.

La procédure suivante vous aide à calculer le nombre optimal de connexions dans votre pool de canaux à l'aide de métriques côté client, telles que celles disponibles dans OpenCensus.

  1. À l'aide des métriques côté client, collectez les informations suivantes :
    1. Nombre maximal de requêtes par seconde (RPS) par client lorsque votre application exécute une charge de travail type.
    2. Latence moyenne (temps de réponse d'une seule requête) en ms.
  2. Déterminez le nombre de requêtes que vous pouvez envoyer en série par seconde en divisant 1 000 par la valeur de latence moyenne.
  3. Divisez le RPS en secondes par le nombre de requêtes en série par seconde.
  4. Divisez le résultat par 50 requêtes par canal pour déterminer la taille minimale optimale du pool de canaux. (Si votre calcul est inférieur à 2, utilisez au moins deux canaux pour assurer la redondance.)
  5. Divisez le même résultat par 10 requêtes par canal pour déterminer la taille maximale optimale du pool de canaux.

Ces étapes sont exprimées dans les équations suivantes :

  • (RPS en secondes ÷ (1 000 ÷ latence en ms)) ÷ 50 flux = nombre minimal de connexions optimal

  • (RPS en secondes ÷ (1 000 ÷ latence en ms)) ÷ 10 flux = nombre maximal de connexions optimal

Exemple

Votre application envoie généralement 50 000 requêtes par seconde, et la latence moyenne est de 10 ms. Divisez 1 000 par 10 ms pour déterminer que vous pouvez envoyer 100 requêtes en série par seconde. Divisez ce nombre par 50 000 pour obtenir le parallélisme nécessaire pour envoyer 50 000 RPS : 500. Chaque canal peut envoyer au maximum 100 requêtes simultanément, et votre utilisation du canal cible est comprise entre 10 et 50 flux simultanés. Par conséquent, pour calculer le minimum, divisez 500 par 50 pour obtenir 10. Pour trouver le maximum, divisez 500 par 10 pour obtenir 50. Cela signifie que la taille du pool de canaux pour cet exemple doit être comprise entre 10 et 50 connexions.

Définir la taille du pool

Les exemples de code suivants montrent comment configurer le nombre de pools dans les bibliothèques clientes qui vous permettent de définir la taille du pool.

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

Cet exemple ne s'applique qu'aux versions de bibliothèques clientes antérieures à la version 2.9.1, date à laquelle le redimensionnement automatique a été introduit.



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

Cet exemple ne s'applique qu'aux versions de bibliothèques clientes antérieures à la version 2.23.0, date à laquelle le redimensionnement automatique a été introduit.


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";
}