Verbindungspools konfigurieren

Mit einigen Cloud Bigtable-Clientbibliotheken können Sie die Anzahl der gRPC-Kanäle im Verbindungspool eines Clients konfigurieren. Dieser wird auch als Kanalpool bezeichnet. In den meisten Fällen ist die Standardkonfiguration korrekt und muss nicht geändert werden.

Die Größe der Verbindungspools wird automatisch nach Bedarf angepasst, wenn Sie die Cloud Bigtable-Clientbibliothek für Java ab Version 2.23.0 oder den Cloud Bigtable HBase-Client für Java ab Version 2.9.1 verwenden.

Auf dieser Seite wird beschrieben, wie Sie die optimale Größe des Verbindungspools für Ihre Anwendung ermitteln. Außerdem werden Code-Snippets vorgestellt, die zeigen, wie die Verbindungspools konfiguriert werden.

Bevor Sie diese Seite lesen, lesen Sie die Übersicht über Bigtable-Verbindungspools, um zu erfahren, wie sie funktionieren und ob Sie Ihren ändern sollten.

Die folgenden Clientbibliotheken bieten Verbindungs-Pooling und ermöglichen die Konfiguration der Anzahl der Pools:

Optimale Größe des Verbindungspools ermitteln

Im Idealfall hat ein Verbindungspool ungefähr doppelt so viele Verbindungen, wie für eine maximale Sättigung erforderlich ist, um Platz für Trafficschwankungen zu schaffen. Da eine Verbindung maximal 100 gleichzeitige Anfragen verarbeiten kann, sind zwischen 10 und 50 ausstehende Anfragen pro Verbindung optimal. Dieses Konzept wird unter Verbindungspools ausführlicher beschrieben.

Überwachen Sie den Traffic, nachdem Sie Änderungen vorgenommen haben, und passen Sie gegebenenfalls die Anzahl der Verbindungen in Ihrem Pool an.

Mit den folgenden Schritten können Sie die optimale Anzahl von Verbindungen in Ihrem Kanalpool mit clientseitigen Messwerten wie jenen von OpenCensus berechnen.

  1. Ermitteln Sie aus Ihren clientseitigen Messwerten die folgenden Informationen:
    1. Die maximale Anzahl von Abfragen pro Sekunde (QPS) pro Client, wenn Ihre Anwendung eine typische Arbeitslast ausführt.
    2. Die durchschnittliche Latenz (die Antwortzeit für eine einzelne Anfrage) in ms.
  2. Bestimmen Sie die Anzahl der Anfragen, die Sie nacheinander pro Sekunde senden können, indem Sie 1.000 durch den durchschnittlichen Latenzwert teilen.
  3. Teilen Sie die Abfragen pro Sekunde durch die Anzahl der seriellen Anfragen pro Sekunde.
  4. Teilen Sie das Ergebnis durch 50 Anfragen pro Kanal, um die minimale optimale Kanalpoolgröße zu ermitteln. Wenn Ihre Berechnung weniger als 2 ergibt, verwenden Sie trotzdem mindestens zwei Kanäle, um Redundanz zu gewährleisten.
  5. Teilen Sie dasselbe Ergebnis durch 10 Anfragen pro Kanal, um die maximale optimale Kanalpoolgröße zu ermitteln.

Diese Schritte werden in der folgenden Gleichung ausgedrückt:

  • (QPS Sek. ÷ (1.000 ÷ Latenz ms)) ÷ 50 Streams = Minimale optimale Anzahl von Verbindungen

  • (QPS Sek. ÷ (1.000 ÷ Latenz ms)) ÷ 10 Streams = Maximale optimale Anzahl von Verbindungen

Beispiel

Ihre Anwendung sendet normalerweise 50.000 Anfragen pro Sekunde. Die durchschnittliche Latenz beträgt 10 ms. Teilen Sie 1.000 durch 10 ms, um zu ermitteln, dass Sie 100 Anfragen nacheinander pro Sekunde senden können. Teilen Sie 50.000 durch diese Zahl, um die Parallelität zu erhalten, die zum Senden von 50.000 QPS erforderlich ist: 500. Jeder Kanal kann höchstens 100 Anfragen gleichzeitig ausführen und Ihre Zielkanalauslastung liegt zwischen 10 und 50 gleichzeitigen Streams. Zur Berechnung des Minimums teilen Sie daher 500 durch 50 und erhalten 10. Um den Maximalwert zu ermitteln, teilen Sie 500 durch 10 und erhalten 50. Das bedeutet, dass die Größe des Kanalpools in diesem Beispiel zwischen 10 und 50 Verbindungen liegen sollte.

Poolgröße festlegen

Die folgenden Codebeispiele zeigen, wie Sie die Anzahl der Pools in den Clientbibliotheken konfigurieren, mit denen Sie die Poolgröße festlegen können.

Einfach loslegen (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

Dieses Beispiel gilt nur für Versionen der Clientbibliotheken vor 2.9.1, als die automatische Größenanpassung eingeführt wurde.



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

Dieses Beispiel gilt nur für Versionen der Clientbibliotheken vor 2.23.0, als die automatische Größenanpassung eingeführt wurde.


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