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 von Verbindungspools wird automatisch angepasst, wenn Sie die Cloud Bigtable-Clientbibliothek für Java Version 2.23.0 oder höher oder den Cloud Bigtable HBase-Client für Java Version 2.9.1 oder höher 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

Um Spielraum für Trafficschwankungen zu schaffen, wird für den Verbindungspool idealerweise etwa die doppelte Anzahl der Verbindungen benötigt, die für die maximale Sättigung erforderlich sind. 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 in der Regel 50.000 Anfragen pro Sekunde und die durchschnittliche Latenz beträgt 10 ms. Teilen Sie 1.000 durch 10 ms, um festzustellen, 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 Höchstwert zu ermitteln, teilen Sie 500 durch 10. Sie erhalten dann 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.

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 Clientbibliotheksversionen vor 2.9.1, als die automatische Größenänderung 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 Clientbibliotheksversionen vor 2.23.0, als die automatische Größenänderung 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";
}