Configurar grupos de conexiones

Algunas bibliotecas cliente de Cloud Bigtable te permiten configurar la cantidad de canales de gRPC en el grupo de conexiones de un cliente, también conocido como grupo de canales. En la mayoría de los casos, la configuración predeterminada es correcta y no es necesario cambiarla.

El tamaño de los grupos de conexiones cambia de forma automática según sea necesario cuando usas la biblioteca cliente de Cloud Bigtable para Java 2.23.0 o posterior y el cliente de HBase de Cloud Bigtable para Java versión 2.9.1 o posterior.

En esta página, se describe cómo determinar el tamaño óptimo del grupo de conexiones de tu aplicación y se presentan fragmentos de código que muestran cómo configurar los grupos de conexiones.

Antes de leer esta página, lee la descripción general de los grupos de conexiones de Bigtable a fin de obtener información sobre cómo funcionan y si debes cambiar el tuyo.

Las siguientes bibliotecas cliente ofrecen la agrupación de conexiones y te permiten configurar la cantidad de grupos:

Determina el mejor tamaño del grupo de conexiones

Idealmente, a fin de dejar margen para las fluctuaciones de tráfico, un grupo de conexiones tiene alrededor del doble de conexiones que requiere para una saturación máxima. Debido a que una conexión puede manejar un máximo de 100 solicitudes simultáneas, entre 10 y 50 solicitudes pendientes por conexión son óptimas. Este concepto se describe con más detalle en Grupos de conexión.

Supervisa el tráfico después de realizar cambios y ajusta la cantidad de conexiones en tu grupo si es necesario.

Los siguientes pasos te ayudan a calcular la cantidad óptima de conexiones en el grupo de canales mediante métricas del cliente, como las que están disponibles en OpenCensus.

  1. Desde las métricas del cliente, recopila la siguiente información:
    1. La cantidad máxima de consultas por segundo (QPS) por cliente cuando la aplicación ejecuta una carga de trabajo típica.
    2. La latencia promedio (el tiempo de respuesta de una sola solicitud) en ms.
  2. Determina la cantidad de solicitudes que puedes enviar en serie por segundo: divide 1,000 por el valor de latencia promedio.
  3. Divide las QPS en segundos por la cantidad de solicitudes en serie por segundo.
  4. Divide el resultado por 50 solicitudes por canal para determinar el tamaño mínimo de grupo de canales óptimo. (Si el cálculo es menor que 2, usa al menos 2 canales de todos modos para garantizar la redundancia).
  5. Divide el mismo resultado por 10 solicitudes por canal para determinar el tamaño máximo de grupo de canales.

Estos pasos se expresan en las siguientes ecuaciones:

  • (QPS s ÷ (1,000 ÷ latencia ms)) ÷ 50 transmisiones = Cantidad óptima de conexiones.

  • (QPS s ÷ (1,000 ÷ latencia ms)) ÷ 10 transmisiones = cantidad máxima óptima de conexiones.

Ejemplo

Por lo general,tu aplicación envía 50, 000 solicitudes por segundo y la latencia promedio es de 10 ms. Divide 1,000 por 10 ms para determinar si puedes enviar 100 solicitudes en serie por segundo. Divide ese número en 50,000 para obtener el paralelismo necesario a fin de enviar 50,000 QPS: 500. Cada canal puede tener 100 solicitudes simultáneas como máximo y el uso de tu canal objetivo está entre 10 y 50 transmisiones simultáneas. Por lo tanto, para calcular el mínimo, divide 500 por 50 a fin de obtener 10. Para calcular el máximo, divide 500 por 10 para obtener 50. Esto significa que el tamaño de tu grupo de canales para este ejemplo debe estar entre 10 y 50 conexiones.

Configura el tamaño del grupo

En las siguientes muestras de código, se indica cómo configurar la cantidad de grupos en las bibliotecas cliente que te permiten configurar el tamaño del grupo.

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

Este ejemplo se aplica solo a las versiones de la biblioteca cliente anteriores a la 2.9.1, cuando se introdujo el cambio de tamaño automático.



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

Este ejemplo se aplica solo a las versiones de la biblioteca cliente anteriores a la 2.23.0, cuando se introdujo el cambio de tamaño automático.


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