Auf dieser Seite wird das erweiterte Konzept von Sitzungen in Spanner beschrieben, einschließlich Best Practices für Sitzungen beim Erstellen einer Clientbibliothek, bei der Verwendung der REST oder RPC APIs oder bei der Verwendung der Google-Clientbibliotheken.
Eine Sitzung bietet einen Kontext für Datenbankvorgänge mit dem Spanner-Datenbankdienst. Eine Sitzung wird verwendet, um Transaktionen auszuführen, die Daten in einer Spanner-Datenbank lesen, schreiben oder ändern. Jede Sitzung gilt für eine einzige Datenbank.
In Sitzungen können eine oder mehrere Transaktionen gleichzeitig ausgeführt werden. Wenn mehrere Transaktionen ausgeführt werden, wird die Sitzung als gemultiplexte Sitzung bezeichnet. Eigenständige Lese-, Schreib- und Abfragevorgänge verwenden intern eine Transaktion.
Sitzungsleistung verwalten
Sitzungen sind der Kontext für einen Datenbankvorgang. Die Art und Weise, wie Sie sie verwalten, wirkt sich direkt auf die Latenz und die Ressourcennutzung Ihrer Anwendung aus. Sie können die Sitzungsleistung auf die folgenden drei Arten verwalten:
Sitzungspool verwenden
Das Erstellen einer Sitzung erhöht die Latenz, da für jede neue Sitzung ein Roundtrip zum Spanner-Datenbankdienst erforderlich ist. Um diese Latenz zu reduzieren, verwenden Sie einen Sitzungspool: eine Sammlung verfügbarer Sitzungen, die einsatzbereit sind. Anstatt für jeden Vorgang eine Sitzung zu erstellen, gibt der Pool eine vorhandene Sitzung zurück und fordert sie anschließend zur Wiederverwendung zurück. Dadurch wird die Latenz bei der Sitzungserstellung auf viele Vorgänge verteilt, anstatt sie vollständig zu eliminieren. Der Pool speichert vorhandene Sitzungen, gibt bei Bedarf den entsprechenden Sitzungstyp zurück und bereinigt nicht verwendete Sitzungen.
Sitzungen sind langlebig. Nachdem eine Sitzung für einen Datenbankvorgang verwendet wurde, sollte der Client die Sitzung zur Wiederverwendung an den Pool zurückgeben.
Multiplex-Sitzungen verwenden
Mit gemultiplexten Sitzungen können Sie mehrere gleichzeitige Anfragen in einer einzigen Sitzung stellen. Dadurch werden der Backend-Overhead und der Ressourcenverbrauch reduziert. Weitere Informationen finden Sie unter Multiplex-Sitzungen.
gRPC-Kanalkonfiguration optimieren
Reduzieren Sie die hohe Extremwertlatenz (p95/p99), die durch eine Überlastung des gRPC-Kanals bei hohem Traffic verursacht wird, indem Sie den gRPC-Kanalpool optimieren. In unterstützten Clientbibliotheken wird die Größe des Kanalpools beim dynamischen Kanal-Pooling automatisch an die Laständerungen angepasst. Dadurch wird die durch Überlastung verursachte Tail-Latenz reduziert und eine Unter- oder Überdimensionierung von Kanälen vermieden.
Übersicht über gRPC-Kanäle
gRPC-Kanäle werden vom Spanner-Client für die Kommunikation verwendet. Ein gRPC-Kanal entspricht in etwa einer TCP-Verbindung. Ein gRPC-Kanal kann bis zu 100 gleichzeitige Anfragen verarbeiten. Das bedeutet, dass eine Anwendung mindestens so viele gRPC-Kanäle benötigt, wie die Anzahl der gleichzeitigen Anfragen, die die Anwendung ausführt, geteilt durch 100.
Der Spanner-Client erstellt einen Pool von gRPC-Kanälen, wenn Sie ihn erstellen.
Best Practices für die Verwendung von Google-Clientbibliotheken
Im Folgenden werden Best Practices für die Verwendung der Google-Clientbibliotheken für Spanner beschrieben.
Anzahl der Sitzungen und gRPC-Kanäle in den Pools konfigurieren
Wie Sie Sitzungen und gRPC-Kanäle verwalten, hängt von der Clientbibliothek ab. Bei Clientbibliotheken, die gemultiplexte Sitzungen unterstützen, z. B. die Go- und Java-Clientbibliotheken, müssen Sie keinen Sitzungspool konfigurieren. Der gRPC-Kanalpool kann für Sie über dynamisches Kanal-Pooling verwaltet werden. Die anderen Clientbibliotheken verwenden einen Sitzungspool mit einer standardmäßigen Mindest- und Höchstanzahl von Sitzungen und einer Standardanzahl von gRPC-Kanälen. Die Standardeinstellungen sind für die meisten Fälle ausreichend. In den folgenden Abschnitten werden die Standardeinstellungen und Konfigurationsoptionen für die einzelnen Programmiersprachen beschrieben.
C++
MinSessions: 100
MaxSessions: 400
NumChannels: 4
C#
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Go
Multiplex-Sitzungen sind standardmäßig aktiviert und erfordern keine Konfiguration.
Das dynamische Channel-Pooling ist eine Opt-in-Funktion. Wenn Sie sie nicht aktivieren, verwendet der Client vier gRPC-Kanäle. Wenn Sie eine andere feste Anzahl von gRPC-Kanälen verwenden möchten, verwenden Sie beim Erstellen des Clients die Option option.WithGRPCConnectionPool:
// Use 16 gRPC channels instead of the default of four.
client, err := spanner.NewClient(ctx,
"projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID",
option.WithGRPCConnectionPool(16),
)
Für dieses Beispiel ist das Paket google.golang.org/api/option erforderlich.
Wenn Sie das dynamische Kanal-Pooling aktivieren möchten, setzen Sie die Option DCPEnabled in DynamicChannelPoolConfig auf true:
client, err := spanner.NewClientWithConfig(ctx,
"projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID",
spanner.ClientConfig{
DynamicChannelPoolConfig: spanner.DynamicChannelPoolConfig{
DCPEnabled: true,
},
})
Wenn Sie das dynamische Channel-Pooling aktivieren, ohne benutzerdefinierte Optionen festzulegen, wendet die Go-Clientbibliothek die folgenden Standardeinstellungen an:
- Anfängliche Poolgröße: 4 Kanäle
- Mindestgröße des Pools: 2 Kanäle
- Maximale Poolgröße: 10 Kanäle
- Schwellenwert für die Hochskalierung: 25 gleichzeitige RPCs pro Kanal
- Schwellenwert für die Herunterskalierung: 15 gleichzeitige RPCs pro Kanal
- Prüfintervall für die Herunterskalierung: 3 Minuten
Wenn Sie den Pool anpassen möchten, legen Sie die Felder der DynamicChannelPoolConfig-Struktur fest, z. B. DCPInitialChannels, DCPMinChannels, DCPMaxChannels, DCPMaxRPCPerChannel und DCPMinRPCPerChannel.
Java
Multiplex-Sitzungen sind in Version 6.98.0 oder höher der Java-Clientbibliothek standardmäßig aktiviert und erfordern keine Konfiguration. Weitere Informationen finden Sie unter Multiplex-Sitzungen.
Das dynamische Channel-Pooling ist für die Java-Clientbibliothek standardmäßig deaktiviert und muss mit SpannerOptions aktiviert werden. Wenn das dynamische Channel-Pooling nicht aktiviert ist, verwendet die Java-Clientbibliothek 4 gRPC-Channels (8 Channels, wenn die gRPC-GCP-Erweiterung aktiviert ist). Wenn das dynamische Channel-Pooling aktiviert ist, passt die Clientbibliothek die Größe des gRPC-Channel-Pools an, um sich an wechselnde Arbeitslasten anzupassen. Dadurch werden Leistungsprobleme durch unter- oder überdimensionierte Channels vermieden.
Wenn Sie das dynamische Kanal-Pooling aktivieren möchten, fügen Sie enableDynamicChannelPool in SpannerOptions ein:
SpannerOptions options =
SpannerOptions.newBuilder()
.setProjectId("PROJECT_ID")
.enableDynamicChannelPool()
.build();
Wenn Sie die Anzahl der Kanäle mit setNumChannels konfigurieren, deaktiviert Spanner das dynamische Kanal-Pooling und verwendet eine statische Anzahl von Kanälen.
Wenn Sie das dynamische Channel-Pooling aktivieren, ohne benutzerdefinierte Optionen über setGcpChannelPoolOptions festzulegen, wendet die Java-Clientbibliothek die folgenden Standardeinstellungen an, die für typische Arbeitslasten optimiert sind:
- Anfängliche Poolgröße: 4 Kanäle
- Mindestgröße des Pools: 2 Kanäle
- Maximale Poolgröße: 10 Kanäle (harte Obergrenze: 256 Kanäle)
- Schwellenwert für die Hochskalierung: 25 gleichzeitige RPCs pro Kanal
- Schwellenwert für die Herunterskalierung: 15 gleichzeitige RPCs pro Kanal
- Intervall für die Herunterskalierung: 3 Minuten
Verwenden Sie setGcpChannelPoolOptions, um das dynamische Channel-Pooling anzupassen. Beispiel:
SpannerOptions options =
SpannerOptions.newBuilder()
.setProjectId("PROJECT_ID")
.enableDynamicChannelPool()
.setGcpChannelPoolOptions(
GcpChannelPoolOptions.newBuilder()
.setMaxSize(15)
.setMinSize(3)
.setInitSize(5)
// setDynamicScaling(minRpcPerChannel, maxRpcPerChannel,
// scaleDownInterval): scale up as soon as a channel's load
// exceeds 30 concurrent RPCs. Scale-up is event-driven, so
// the pool grows immediately as load rises. Scale-down is
// periodic: a channel is removed only after it stays under
// 10 concurrent RPCs across the check that runs every 5
// minutes.
.setDynamicScaling(10, 30, Duration.ofMinutes(5))
.build())
.build();
Berücksichtigen Sie die folgenden Vor- und Nachteile des dynamischen Kanal-Poolings:
- Skalierungsaufwand: Die Skalierung des Pools ist mit Aufwand für das Erstellen und Löschen von gRPC-Kanälen und TCP-Verbindungen verbunden. Bei latenzempfindlichen Arbeitslasten mit starken Spitzen ist ein großer statischer Pool möglicherweise die bessere Wahl, um Skalierungslatenz zu vermeiden.
- Konfigurationsüberschreibungen: Wenn Sie die Basisanzahl der Kanäle festlegen, wird das dynamische Kanal-Pooling deaktiviert. Weitere Informationen finden Sie unter
setNumChannels. - Ressourcennutzung: Ein statischer Channel-Pool verwendet eine feste Menge an Arbeitsspeicher und Verbindungen, während die Ressourcennutzung eines dynamischen Pools je nach Last variiert.
Node.js
Reguläre Sitzungen
Multiplex-Sitzungen sind ab Version 8.3.0 standardmäßig aktiviert und erfordern keine Konfiguration. In früheren Versionen werden standardmäßig reguläre Sitzungen mit den folgenden Einstellungen verwendet:
MinSessions: 25
MaxSessions: 100
Kanal-Pooling
Das dynamische Channel-Pooling ist standardmäßig mit den folgenden Einstellungen aktiviert:
MaxChannels: 10
ConcurrentRequestsPerChannel: 25
Sie können Konfigurationen programmatisch überschreiben, wenn Sie eine Spanner-Clientinstanz erstellen.
Wenn Sie gemultiplexte Sitzungen verwenden (Standardeinstellung)
Kopieren Sie die channelPool-Konfiguration aus der Spanner-gRPC-Konfiguration in Ihre Anwendung. Sie müssen keine Methodendefinitionen und Affinitätseinstellungen kopieren, da für gemultiplexte Sitzungen keine Bindung von Sitzung zu Kanal erforderlich ist.
Beispiel:
const {Spanner} = require('@google-cloud/spanner');
// Note: Ensure grpcGcp is initialized
const customGcpApiConfig = {
channelPool: {
maxSize: 20, // Overriding default 10
maxConcurrentStreamsLowWatermark: 50 // Overriding default 25
}
};
const spanner = new Spanner({
'grpc.gcpApiConfig': grpcGcp.createGcpApiConfig(customGcpApiConfig)
});
Wenn Sie reguläre Sitzungen verwenden
Kopieren Sie die vollständige Konfiguration (sowohl channelPool als auch Methodenaffinitäten) aus der Spanner-gRPC-Konfiguration in die Anwendung. Wenn Sie die Methodenaffinitäten weglassen, kann dies die Leistung beeinträchtigen, da Anfragen ihre Sitzungs-zu-Kanal-Bindung verlieren.
PHP
Der PHP-Client unterstützt keine konfigurierbare Anzahl von gRPC-Kanälen.
MinSessions: 1
MaxSessions: 500
Python
Python unterstützt vier verschiedene Sitzungspooltypen, mit denen Sie Sitzungen verwalten können.
Ruby
Der Ruby-Client unterstützt nicht mehrere gRPC-Kanäle. Es wird daher empfohlen, mehrere Clients zu erstellen, anstatt die Größe des Sitzungspools für einen einzelnen Client auf mehr als 100 Sitzungen zu erhöhen.
MinSessions: 10
MaxSessions: 100
Verwenden Sie gemultiplexte Sitzungen, wenn die Clientbibliothek für Ihre Programmiersprache diese unterstützt. Multiplex-Sitzungen erfordern keine Konfiguration und eine einzelne Multiplex-Sitzung kann eine beliebige Anzahl gleichzeitiger Transaktionen ausführen.
Die Anzahl der Sitzungen, die Ihre Anwendung verwendet, entspricht der Anzahl der gleichzeitigen Transaktionen, die Ihre Anwendung ausführt. Sie sollten die Standardeinstellungen für den Sitzungspool nur ändern, wenn Sie erwarten, dass eine einzelne Anwendungsinstanz mehr gleichzeitige Transaktionen ausführt, als der Standardsitzungspool verarbeiten kann.
Für Anwendungen mit hoher Nebenläufigkeit wird Folgendes empfohlen:
- Legen Sie für
MinSessionsdie erwartete Anzahl gleichzeitiger Transaktionen fest, die ein einzelner Client ausführt. - Legen Sie für
MaxSessionsdie maximale Anzahl gleichzeitiger Transaktionen fest, die ein einzelner Client ausführen kann. - Legen Sie
MinSessions=MaxSessionsfest, wenn sich die erwartete Nebenläufigkeit während der Lebensdauer der Anwendung nicht wesentlich ändert. Dadurch wird verhindert, dass der Sitzungspool hoch- oder herunterskaliert wird. Das Hoch- oder Herunterskalieren des Sitzungspools verbraucht ebenfalls einige Ressourcen. - Setzen Sie
NumChannelsaufMaxSessions / 100. Ein gRPC-Kanal kann bis zu 100 Anfragen gleichzeitig verarbeiten. Erhöhen Sie diesen Wert, wenn Sie eine hohe Tail-Latenz (p95/p99-Latenz) feststellen, da dies auf eine Überlastung des gRPC-Kanals hindeuten könnte.
Wenn Sie die Anzahl der aktiven Sitzungen erhöhen, werden zusätzliche Ressourcen im Spanner-Datenbankdienst und in der Clientbibliothek verwendet. Wenn Sie die Anzahl der Sitzungen über den tatsächlichen Bedarf der Anwendung hinaus erhöhen, kann dies die Leistung Ihres Systems beeinträchtigen.
Sitzungspool vergrößern statt Anzahl der Clients erhöhen
Die Größe des Sitzungspools für eine Anwendung bestimmt, wie viele gleichzeitige Transaktionen eine einzelne Anwendungsinstanz ausführen kann. Es wird nicht empfohlen, die Größe des Sitzungspools über die maximale Nebenläufigkeit hinaus zu erhöhen, die eine einzelne Anwendungsinstanz verarbeiten kann. Wenn die Anwendung eine große Anzahl von Anfragen erhält, die die Anzahl der Sitzungen im Pool überschreitet, werden die Anfragen in die Warteschlange gestellt, bis eine Sitzung verfügbar ist.
Die von der Clientbibliothek verbrauchten Ressourcen sind:
- Jeder gRPC-Kanal verwendet eine TCP-Verbindung.
- Für jeden gRPC-Aufruf ist ein Thread erforderlich. Die maximale Anzahl von Threads, die von der Clientbibliothek verwendet wird, entspricht der maximalen Anzahl gleichzeitiger Abfragen, die die Anwendung ausführt. Diese Threads kommen zu den Threads hinzu, die die Anwendung für ihre eigene Geschäftslogik verwendet.
Es wird nicht empfohlen, die Größe des Sitzungspools über die maximale Anzahl von Threads hinaus zu erhöhen, die eine einzelne Anwendungsinstanz verarbeiten kann. Erhöhen Sie stattdessen die Anzahl der Anwendungsinstanzen.
Anteil der Schreibsitzungen verwalten
Bei einigen Clientbibliotheken reserviert Spanner einen Teil der Sitzungen für Lese-/Schreibtransaktionen, den sogenannten Anteil der Schreibsitzungen. Wenn Ihre Anwendung alle Lesesitzungen aufgebraucht hat, verwendet Spanner die Lese-/Schreibsitzungen, auch für Transaktionen mit Lesezugriff. Für Lese-/Schreibvorgänge ist spanner.databases.beginOrRollbackReadWriteTransaction erforderlich. Wenn der Nutzer die IAM-Rolle spanner.databaseReader hat, schlägt der Aufruf fehl und Spanner gibt die folgende Fehlermeldung zurück:
generic::permission_denied: Resource %resource% is missing IAM permission:
spanner.databases.beginOrRollbackReadWriteTransaction
Bei Clientbibliotheken, die einen Anteil an Schreibsitzungen haben, können Sie diesen festlegen.
C++
Alle C ++-Sitzungen sind identisch. Es gibt keine schreibgeschützten bzw. nicht schreibgeschützten Sitzungen.
C#
Der Standardwert für den Anteil der Schreibsitzungen für C# ist 0,2. Sie können den Anteil mit dem Feld „WriteSessionsFraction“ von SessionPoolOptions ändern.
Go
Alle Go-Sitzungen sind gleich. Es gibt weder schreibgeschützte noch nicht schreibgeschützte Sitzungen.
Java
Alle Java-Sitzungen sind gleich. Es gibt keine schreibgeschützten bzw. nicht schreibgeschützten Sitzungen.
Node.js
Alle Node.js-Sitzungen sind gleich. Es gibt keine schreibgeschützten bzw. nicht schreibgeschützten Sitzungen.
PHP
Alle PHP-Sitzungen sind gleich. Es gibt keine schreibgeschützten bzw. nicht schreibgeschützten Sitzungen.
Python
Python unterstützt vier verschiedene Sitzungspooltypen, die Sie zum Verwalten von schreibgeschützten und nicht schreibgeschützten Sitzungen verwenden können.
Ruby
Der Standardanteil der Schreibsitzungen bei Ruby ist 0,3. Sie können ihn mit der client initialize-Methode ändern.
Best Practices beim Erstellen einer Clientbibliothek oder bei Verwendung von REST/RPC
Im Folgenden werden Best Practices für die Implementierung von Sitzungen in einer Clientbibliothek für Spanner oder für die Verwendung von Sitzungen mit der REST oder RPC API beschrieben.
Diese Best Practices gelten nur, wenn Sie eine Clientbibliothek entwickeln oder wenn Sie REST/RPC-APIs verwenden. Wenn Sie eine der Google-Clientbibliotheken für Cloud Spanner verwenden, lesen Sie die Best Practices für die Verwendung von Google-Clientbibliotheken.
Sitzungspool erstellen und Größe festlegen
Um die optimale Größe des Sitzungspools für einen Clientprozess zu ermitteln, legen Sie die Untergrenze auf die Anzahl der erwarteten gleichzeitigen Transaktionen und die Obergrenze auf eine anfängliche Testanzahl fest, z. B. 100. Wenn die obere Grenze nicht ausreicht, setzen Sie sie herauf. Wenn Sie die Anzahl der aktiven Sitzungen erhöhen, werden zusätzliche Ressourcen im Spanner-Datenbankdienst verwendet. Wenn Sie nicht verwendete Sitzungen nicht bereinigen, kann dies die Leistung beeinträchtigen. Für Nutzer, die mit der RPC API arbeiten, empfehlen wir, nicht mehr als 100 Sitzungen pro gRPC-Kanal zu haben.
Gelöschte Sitzungen
Es gibt drei Möglichkeiten, eine Sitzung zu löschen:
- Ein Client kann eine Sitzung löschen.
- Der Spanner-Datenbankdienst kann eine Sitzung löschen, wenn sie länger als eine Stunde inaktiv ist.
- Der Spanner-Datenbankdienst kann eine Sitzung löschen, wenn sie älter als 28 Tage ist.
Versuche, eine gelöschte Sitzung zu verwenden, führen zu NOT_FOUND. Wenn dieser Fehler auftritt, erstellen und verwenden Sie eine neue Sitzung, fügen Sie die neue Sitzung dem Pool hinzu und entfernen Sie die gelöschte Sitzung aus dem Pool.
Inaktive Sitzung offen halten
Der Cloud Spanner-Datenbankdienst behält sich das Recht vor, eine nicht verwendete Sitzung zu löschen. Wenn Sie eine inaktive Sitzung unbedingt offen halten müssen, wenn z. B. eine signifikante Erhöhung der Datenbanknutzung in naher Zukunft erwartet wird, können Sie verhindern, dass die Sitzung gelöscht wird. Führen Sie einen kostengünstigen Vorgang wie das Ausführen der SQL-Abfrage SELECT 1 durch, um die Sitzung aktiv zu halten. Wenn Sie eine inaktive Sitzung haben, die in naher Zukunft nicht benötigt wird, lassen Sie die Sitzung von Cloud Spanner löschen und erstellen Sie dann eine neue Sitzung, wenn eine Sitzung benötigt wird.
Ein Szenario, in dem Sitzungen offen gehalten werden, ist der Umgang mit regulärer Spitzennachfrage der Datenbank. Wenn eine starke Datenbanknutzung täglich von 9:00 Uhr bis 18:00 Uhr stattfindet, sollten Sie während dieser Zeit einige inaktive Sitzungen offen halten, da diese wahrscheinlich zu Spitzenzeiten erforderlich sind. Nach 18:00 Uhr können Sie Spanner erlauben, inaktive Sitzungen zu beenden. Erstellen Sie jeden Tag vor 9:00 Uhr einige neue Sitzungen, damit sie für die erwartete Nachfrage bereitstehen.
Ein weiteres Szenario ist, wenn Sie eine Anwendung haben, die Spanner verwendet, aber den Verbindungsaufwand vermeiden muss. Sie können eine Gruppe von Sitzungen offen halten, um den Verbindungsaufwand zu vermeiden.
Sitzungsdetails vom Clientbibliotheksbenutzer ausblenden
Wenn Sie eine Clientbibliothek erstellen, sollten Sie die Sitzungen nicht für den Nutzer der Clientbibliothek verfügbar machen. Stellen Sie die Möglichkeit für den Client bereit, Datenbankaufrufe ohne den Aufwand der Erstellung und Verwaltung von Sitzungen durchzuführen. Ein Beispiel für eine Clientbibliothek, die die Sitzungsdetails vor dem Nutzer der Clientbibliothek verbirgt, finden Sie in der Spanner-Clientbibliothek für Java.
Fehler bei Schreibtransaktionen bearbeiten, die nicht idempotent sind
Schreibtransaktionen ohne Wiederholungsschutz können Mutationen mehr als einmal anwenden.
Wenn eine Mutation nicht idempotent ist, kann eine Mutation, die mehrmals angewendet wird, zu einem Fehler führen. Beispiel: Eine Einfügung (Insert) kann den Fehler ALREADY_EXISTS verursachen, obwohl die Zeile vor dem Schreibversuch nicht vorhanden war. Dies kann auftreten, wenn der Backend-Server die Mutation festgeschrieben hat, dies aber dem Client nicht mitteilen konnte. In diesem Fall könnte die Mutation wiederholt werden, was aber zu dem Fehler ALREADY_EXISTS führen würde.
Im Folgenden sind einige Möglichkeiten aufgelistet, wie Sie mit diesem Szenario bei der Bereitstellung Ihrer eigenen Clientbibliothek oder bei der Verwendung der REST API verfahren können:
- Strukturieren Sie Ihre Schreibvorgänge so, dass sie idempotent sind.
- Verwenden Sie Schreibvorgänge mit Wiederholungsschutz.
- Implementieren Sie eine Methode mit der Logik "upsert": einfügen, wenn neu, oder aktualisieren, wenn bereits vorhanden.
- Bearbeiten Sie den Fehler für den Client.
Für stabile Verbindungen sorgen
Für eine optimale Leistung sollte die Verbindung, die Sie zum Hosten einer Sitzung verwenden, stabil sein. Wenn sich die Verbindung ändert, die eine Sitzung hostet, bricht Cloud Spanner möglicherweise die aktive Transaktion in der Sitzung ab. Dies führt zu einer geringen zusätzlichen Last für Ihre Datenbank, während die Sitzungsmetadaten aktualisiert werden. Wenn sich einige Verbindungen gelegentlich ändern, ist das kein Problem, aber Sie sollten Situationen vermeiden, in denen sich eine große Anzahl von Verbindungen gleichzeitig ändert. Wenn Sie einen Proxy zwischen dem Client und Spanner verwenden, sollten Sie die Verbindungsstabilität für jede Sitzung aufrechterhalten.
Aktive Sitzungen überwachen
Mit dem Befehl ListSessions können Sie aktive Sitzungen in Ihrer Datenbank über die Befehlszeile, mit der REST API oder mit der RPC API überwachen. ListSessions zeigt die aktiven Sitzungen für eine bestimmte Datenbank an. Dies ist nützlich, wenn Sie die Ursache eines Sitzungslecks finden müssen. (Ein Sitzungsleck ist ein Vorfall, bei dem Sitzungen erstellt, aber nicht zur Wiederverwendung an einen Sitzungspool zurückgegeben werden.)
Mit ListSessions können Sie Metadaten zu Ihren aktiven Sitzungen aufrufen, z. B. wann eine Sitzung erstellt und wann sie zuletzt verwendet wurde. Die Analyse dieser Daten hilft Ihnen bei der Fehlerbehebung in Sitzungen. Wenn die meisten aktiven Sitzungen keine aktuelle approximate_last_use_time haben, kann dies darauf hindeuten, dass Sitzungen von Ihrer Anwendung nicht ordnungsgemäß wiederverwendet werden. Weitere Informationen zum Feld approximate_last_use_time finden Sie in der RPC API-Referenz.
Weitere Informationen zur Verwendung von ListSessions finden Sie in der REST API-Referenz, der RPC API-Referenz oder der gcloud-Befehlszeilentool-Referenz.
Automatische Bereinigung von Sitzungslecks
Wenn Sie alle Sitzungen in Ihrem Sitzungspool verwenden, wartet jede neue Transaktion, bis eine Sitzung an den Pool zurückgegeben wird. Wenn Sitzungen erstellt, aber nicht zur Wiederverwendung an den Sitzungspool zurückgegeben werden, wird dies als Sitzungsleck bezeichnet. Wenn ein Sitzungsleck auftritt, bleiben Transaktionen, die auf eine offene Sitzung warten, auf unbestimmte Zeit hängen und blockieren die Anwendung. Sitzungslecks werden häufig durch problematische Transaktionen verursacht, die extrem lange ausgeführt und nicht festgeschrieben werden.
Sie können Ihren Sitzungspool so einrichten, dass diese inaktiven Transaktionen automatisch aufgelöst werden. Wenn Sie die Clientbibliothek so konfigurieren, dass inaktive Transaktionen automatisch aufgelöst werden, werden problematische Transaktionen, die zu einem Sitzungsleck führen könnten, identifiziert, aus dem Sitzungspool entfernt und durch eine neue Sitzung ersetzt.
Das Logging kann auch dabei helfen, diese problematischen Transaktionen zu identifizieren. Wenn das Logging aktiviert ist, werden standardmäßig Warnungslogs freigegeben, wenn mehr als 95 % Ihres Sitzungspools verwendet werden. Wenn Ihre Sitzungsnutzung mehr als 95 % beträgt, müssen Sie entweder die maximal zulässige Anzahl von Sitzungen in Ihrem Sitzungspool erhöhen oder es liegt möglicherweise ein Sitzungsleck vor. Warnungsprotokolle enthalten Stacktraces von Transaktionen, die länger als erwartet dauern, und können helfen, die Ursache für eine hohe Sitzungspoolauslastung zu ermitteln. Warnungslogs werden je nach Konfiguration des Log-Exporters übertragen.
Clientbibliothek aktivieren, um inaktive Transaktionen automatisch aufzulösen
Sie können die Clientbibliothek entweder so aktivieren, dass Warnungslogs gesendet und inaktive Transaktionen automatisch aufgelöst werden, oder so, dass nur Warnungslogs empfangen werden.
Java
Wenn Sie Warnungsprotokolle erhalten und inaktive Transaktionen entfernen möchten, verwenden Sie setWarnAndCloseIfInactiveTransactions.
final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnAndCloseIfInactiveTransactions().build()
final Spanner spanner =
SpannerOptions.newBuilder()
.setSessionPoolOption(sessionPoolOptions)
.build()
.getService();
final DatabaseClient client = spanner.getDatabaseClient(databaseId);
Wenn Sie nur Warnungslogs erhalten möchten, verwenden Sie setWarnIfInactiveTransactions.
final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnIfInactiveTransactions().build()
final Spanner spanner =
SpannerOptions.newBuilder()
.setSessionPoolOption(sessionPoolOptions)
.build()
.getService();
final DatabaseClient client = spanner.getDatabaseClient(databaseId);
Go
Wenn Sie Warnungsprotokolle erhalten und inaktive Transaktionen entfernen möchten, verwenden Sie SessionPoolConfig mit InactiveTransactionRemovalOptions.
client, err := spanner.NewClientWithConfig(
ctx, database, spanner.ClientConfig{SessionPoolConfig: spanner.SessionPoolConfig{
InactiveTransactionRemovalOptions: spanner.InactiveTransactionRemovalOptions{
ActionOnInactiveTransaction: spanner.WarnAndClose,
}
}},
)
if err != nil {
return err
}
defer client.Close()
Wenn Sie nur Warnungsprotokolle erhalten möchten, verwenden Sie customLogger.
customLogger := log.New(os.Stdout, "spanner-client: ", log.Lshortfile)
// Create a logger instance using the golang log package
cfg := spanner.ClientConfig{
Logger: customLogger,
}
client, err := spanner.NewClientWithConfig(ctx, db, cfg)
Multiplex-Sitzungen
Mit gemultiplexten Sitzungen können Sie eine große Anzahl gleichzeitiger Anfragen in einer einzelnen Sitzung erstellen. Eine gemultiplexte Sitzung ist eine Kennung, die Sie für mehrere gRPC-Kanäle verwenden. Es entstehen keine zusätzlichen Engpässe. Multiplex-Sitzungen bieten folgende Vorteile:
- Geringerer Ressourcenverbrauch im Backend aufgrund eines einfacheren Protokolls für die Sitzungsverwaltung. Beispielsweise werden Aktivitäten zur Sitzungswartung im Zusammenhang mit der Sitzungsinhaberschaft und der automatischen Speicherbereinigung vermieden.
- Langlebige Sitzung, die im inaktiven Zustand keine Keep-Alive-Anfragen erfordert.
Multiplex-Sitzungen werden in folgenden Fällen unterstützt:
- Die Clientbibliotheken für C++, Go, Java, Node.js, PHP, Python, Ruby und Rust.
Spanner-Ökosystemtools, die von den genannten Clientbibliotheken abhängen, z. B. PGAdapter, JDBC, Hibernate, database/sql-Treiber, dbAPI-Treiber und GORM.
Spanner-Ökosystemtools, die von den Java- und Go-Clientbibliotheken abhängen, z. B. PGAdapter, JDBC, Hibernate, Datenbank- oder SQL-Treiber und GORM. Mit OpenTelemetry-Messwerten können Sie sehen, wie der Traffic zwischen dem vorhandenen Sitzungspool und der gemultiplexten Sitzung aufgeteilt wird. OpenTelemetry hat einen Messwertfilter,
is_multiplexed, der gemultiplexte Sitzungen anzeigt, wenn er auftruegesetzt ist.
Multiplex-Sitzungen werden für alle Arten von Transaktionen unterstützt.
Clientbibliotheken rotieren gemultiplexte Sitzungen alle 7 Tage, um zu verhindern, dass Transaktionen über veraltete Sitzungen gesendet werden.
Multiplex-Sitzungen sind in einigen Clientbibliotheken standardmäßig aktiviert. Für andere müssen Sie Umgebungsvariablen verwenden, um sie zu aktivieren. Weitere Informationen finden Sie unter Multiplex-Sitzungen aktivieren.
Hinweise
Wenn Sie versuchen, entweder einen leeren Lese- oder Schreibtransaktions-Body oder eine Transaktion zu committen, bei der jede Abfrage oder DML-Anweisung fehlgeschlagen ist, gibt es bei gemultiplexten Sitzungen einige Szenarien zu beachten. Für gemultiplexte Sitzungen müssen Sie in jeder Commit-Anfrage ein vom Server generiertes Pre-Commit-Token angeben. Bei Transaktionen, die Abfragen oder DML enthalten, muss mindestens eine vorherige erfolgreiche Abfrage- oder DML-Transaktion vorhanden sein, damit der Server ein gültiges Token an die Clientbibliothek zurücksendet. Wenn keine erfolgreichen Abfragen oder DML-Transaktionen vorhanden sind, fügt die Clientbibliothek vor einem Commit implizit SELECT 1 hinzu.
Wenn bei einer Lese- oder Schreibtransaktion in einer gemultiplexten Sitzung, die nur Mutationen enthält, eine der Mutationen für eine Tabelle oder eine Spalte gilt, die NICHT im Schema vorhanden ist, kann der Client einen INVALID_ARGUMENT-Fehler anstelle eines NOT_FOUND-Fehlers zurückgeben.
Multiplex-Sitzungen aktivieren
Multiplex-Sitzungen sind in den folgenden Clientbibliotheken standardmäßig aktiviert:
- C++ in Version 2.41.0 und höher.
- Go in Version 1.85.0 und höher.
- Java in Version 6.98.0 und höher.
- Node.js in Version 8.3.0 und höher.
- PHP in Version 2.0.0 und höher.
- Python in Version 3.57.0 und höher.
- Ruby in Version 2.30.0 und höher.
Wenn Sie gemultiplexte Sitzungen in früheren Versionen der Node.js-, Java- und Go-Clientbibliotheken verwenden möchten, müssen Sie zuerst eine Umgebungsvariable festlegen, um sie zu aktivieren.
Wenn Sie gemultiplexte Sitzungen aktivieren möchten, setzen Sie die Umgebungsvariable GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS auf TRUE. Dieses Flag aktiviert auch die Unterstützung für gemultiplexte Sitzungen für ReadOnly-Transaktionen.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE
Wenn Sie die Unterstützung für partitionierte Vorgänge für gemultiplexte Sitzungen aktivieren möchten, setzen Sie die Umgebungsvariable GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS auf TRUE.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS=TRUE
Wenn Sie die Unterstützung von Lese-/Schreibtransaktionen für gemultiplexte Sitzungen aktivieren möchten, setzen Sie die Umgebungsvariable GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW auf TRUE.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW=True
Sie müssen GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS auf TRUE setzen, um eine Transaktion in einer gemultiplexten Sitzung zu unterstützen.
Traffic für reguläre und gemultiplexte Sitzungen ansehen
OpenTelemetry enthält den Filter is_multiplexed, um Traffic für gemultiplexte Sitzungen anzuzeigen. Setzen Sie diesen Filter auf true, um gemultiplexte Sitzungen anzusehen, oder auf false, um reguläre Sitzungen anzusehen.
- Richten Sie OpenTelemetry für Spanner ein. Folgen Sie dazu der Anleitung im Abschnitt Vorbereitung für Spanner OpenTelemetry.
Rufen Sie den Metrics Explorer auf.
Filtern Sie im Drop-down-Menü Messwert nach
generic.Klicken Sie auf Generische Aufgabe und rufen Sie Spanner > Spanner/num_acquired_sessions auf.
Wählen Sie im Feld Filter eine der folgenden Optionen aus:
a.
is_multiplexed = false, um reguläre Sitzungen aufzurufen. b.is_multiplexed = true, um gemultiplexte Sitzungen anzusehen.Auf dem folgenden Bild ist die Option Filter mit ausgewählten gemultiplexten Sitzungen zu sehen.
Weitere Informationen zur Verwendung von OpenTelemetry mit Spanner finden Sie unter OpenTelemetry zur Demokratisierung der Spanner-Beobachtbarkeit nutzen und Latenz in einer Spanner-Komponente mit OpenTelemetry untersuchen.

Fehlerbehebung
Häufige sitzungsbezogene Fehler, die in Ihrer Anwendung auftreten können:
Session not foundRESOURCE_EXHAUSTED
Weitere Informationen finden Sie unter Sitzungsfehler.