Sessioni

Questa pagina descrive il concetto avanzato di sessioni in Spanner, tra cui best practice per le sessioni durante la creazione di una libreria client, utilizzando le API REST o RPC oppure le librerie client di Google.

Panoramica delle sessioni

Una sessione rappresenta un canale di comunicazione con il database Spanner completamente gestito di Google Cloud. Una sessione viene utilizzata per eseguire transazioni di lettura, scrittura o modifica in un database Spanner. Ogni sessione si applica a un singolo database.

Le sessioni possono eseguire una o più transazioni alla volta. Quando eseguendo più transazioni, la sessione è chiamata sessione multiplex.

Letture, scritture e query autonome utilizzano un'unica transazione internamente.

Vantaggi delle prestazioni di un pool di sessioni

Creare una sessione è costoso. Per evitare il costo delle prestazioni ogni volta viene eseguita un'operazione sul database, i client devono mantenere un pool di sessioni, ovvero di sessioni disponibili pronte all'uso. Il pool deve archiviare le sessioni esistenti e restituire il tipo di sessione appropriato quando richiesto, oltre a gestire la pulizia di sessioni inutilizzate. Per un esempio di come implementare un pool di sessioni, consulta il codice sorgente di una delle librerie client di Spanner, ad esempio La libreria client Go o la libreria client Java.

Le sessioni sono pensate per essere di lunga durata, quindi dopo che una sessione è usata nell'operazione di database, il client deve restituire la sessione al pool per poterla riutilizzare.

Panoramica dei canali gRPC

I canali gRPC vengono utilizzati dal client Spanner per le comunicazioni. Un gRPC è più o meno equivalente a una connessione TCP. Un canale gRPC può gestire fino a 100 richieste in parallelo. Ciò significa che un'applicazione dovrà avere un numero di canali gRPC pari al numero di richieste in parallelo che l'applicazione viene eseguito, diviso per 100.

Il client Spanner crea un pool di canali gRPC quando a crearlo.

Best practice per l'utilizzo delle librerie client di Google

Di seguito vengono descritte le best practice relative all'utilizzo del client Google librerie per Spanner.

Configura il numero di sessioni e canali gRPC nei pool

Le librerie client hanno un numero predefinito di sessioni nel pool di sessioni e un numero predefinito di canali gRPC nel pool di canali. Entrambi i valori predefiniti sono adeguati nella maggior parte dei casi. Di seguito sono riportate le sessioni minima e massima predefinite e il numero predefinito di canali gRPC per ciascun linguaggio di programmazione.

C++

MinSessions: 100
MaxSessions: 400
NumChannels: 4

C#

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Vai

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Java

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Node.js

Il client Node.js non supporta più canali gRPC. Di conseguenza, di creare più clienti invece di aumentare la dimensione del più di 100 sessioni per un singolo client.

MinSessions: 25
MaxSessions: 100

PHP

Il client PHP non supporta un numero configurabile di canali gRPC.

MinSessions: 1
MaxSessions: 500

Python

Python supporta quattro diversi tipi di pool di sessioni che puoi utilizzare per gestire le sessioni.

Ruby

Il client Ruby non supporta più canali gRPC. Di conseguenza, di creare più clienti invece di aumentare la dimensione del più di 100 sessioni per un singolo client.

MinSessions: 10
MaxSessions: 100

Il numero di sessioni utilizzate dalla tua applicazione è uguale al numero di sessioni e le transazioni simultanee eseguite dalla tua applicazione. Devi modificare il valore impostazioni predefinite del pool di sessioni solo se prevedi una singola istanza di applicazione per eseguire più transazioni simultanee rispetto a quelle che il pool di sessioni predefinito può gestire.

Per le applicazioni ad alta contemporaneità, si consiglia di:

  1. Imposta MinSessions sul numero previsto di transazioni simultanee che un il singolo client.
  2. Imposta MaxSessions sul numero massimo di transazioni simultanee che un che un singolo client possa eseguire.
  3. Imposta MinSessions=MaxSessions se la contemporaneità prevista non cambia per tutta la durata dell'applicazione. Questo impedisce al pool di sessioni lo scale up o lo scale down. Anche lo scale up o lo scale down del pool di sessioni comporta Google Cloud.
  4. Imposta NumChannels su MaxSessions / 100. Un canale gRPC può gestire fino a 100 richieste in contemporanea. Aumenta questo valore se noti una coda alta (latenza p95/p99), perché potrebbe indicare un valore di gRPC la congestione dei canali.

L'aumento del numero di sessioni attive comporta l'utilizzo di risorse aggiuntive sulla servizio di database Spanner e nella libreria client. L'aumento del di sessioni che vanno oltre l'effettiva necessità dell'applicazione potrebbe le prestazioni del tuo sistema.

Aumentare il pool di sessioni rispetto all'aumento del numero di clienti

La dimensione del pool di sessioni per un'applicazione determina il numero di sessioni transazioni che una singola istanza dell'applicazione può eseguire. Aumento della sessione dimensioni del pool oltre la contemporaneità massima che può essere eseguita da una singola istanza di applicazione è sconsigliato. Se l'applicazione riceve una serie di richieste che va oltre il numero di sessioni nel pool, le richieste vengono messe in coda mentre attendi che una sessione diventi disponibile.

Le risorse utilizzate dalla libreria client sono le seguenti:

  1. Ogni canale gRPC utilizza una connessione TCP.
  2. Ogni chiamata a gRPC richiede un thread. Il numero massimo di thread utilizzati dalla libreria client è uguale al numero massimo di le query in parallelo eseguite dall'applicazione. Questi thread vengono in cima di qualsiasi thread utilizzato dall'applicazione per la propria logica di business.

Aumento delle dimensioni del pool di sessioni oltre il numero massimo di thread che una singola istanza di applicazione può gestire non è consigliabile. Invece, aumenta il numero di istanze dell'applicazione.

Gestisci la frazione delle sessioni di scrittura

Per alcune librerie client, Spanner riserva una parte delle sessioni per le transazioni di lettura/scrittura, chiamata frazione delle sessioni di scrittura. Se la tua app utilizza tutte le sessioni di lettura, quindi Spanner usa la funzione di lettura/scrittura anche per le transazioni di sola lettura. Le sessioni di lettura/scrittura richiedono spanner.databases.beginOrRollbackReadWriteTransaction. Se l'utente si trova nel spanner.databaseReader, la chiamata non va a buon fine. e Spanner restituisce questo messaggio di errore:

generic::permission_denied: Resource %resource% is missing IAM permission:
spanner.databases.beginOrRollbackReadWriteTransaction

Per le librerie client che mantengono una frazione di sessioni di scrittura, puoi impostare la frazione delle sessioni di scrittura.

C++

Tutte le sessioni C++ sono uguali. Non sono presenti sessioni di lettura o di sola lettura/scrittura.

C#

La frazione predefinita di sessioni di scrittura per C# è 0,2. Puoi modificare utilizzando il campo writeSessionsFraction di SessionPoolOptions.

Vai

Tutte le sessioni Go sono uguali. Non sono presenti sessioni di lettura o di sola lettura/scrittura.

Java

Tutte le sessioni Java sono uguali. Non sono presenti sessioni di lettura o di sola lettura/scrittura.

Node.js

Tutte le sessioni Node.js sono uguali. Non sono presenti sessioni di lettura o di sola lettura/scrittura.

PHP

Tutte le sessioni PHP sono uguali. Non esistono modelli di sola lettura o lettura/scrittura sessioni.

Python

Python supporta quattro diversi tipi di pool di sessioni che puoi utilizzare per gestire le sessioni di lettura e lettura/scrittura.

Ruby

La frazione predefinita di sessioni di scrittura per Ruby è 0,3. Puoi modificare frazione utilizzando il client di inizializzazione.

Best practice per la creazione di una libreria client o l'utilizzo di REST/RPC

Di seguito vengono descritte le best practice per l'implementazione delle sessioni in un client libreria per Spanner o per l'utilizzo di sessioni con il comando REST o API RPC.

Queste best practice si applicano solo se stai sviluppando una libreria client o se utilizzi le API REST/RPC. Se utilizzi uno dei client Google librerie per Spanner, consulta Best practice per l'utilizzo delle librerie client di Google.

crea e dimensiona il pool di sessioni

Per determinare una dimensione ottimale del pool di sessioni per un processo client, imposta la dimensione limite inferiore al numero di transazioni simultanee previste e imposta il limite superiore associate a un numero di test iniziale, ad esempio 100. Se il limite superiore non è adeguato, aumentarlo. L'aumento del numero di sessioni attive comporta l'utilizzo di risorse aggiuntive sul servizio di database Spanner, pertanto non riesci a eseguire la pulizia delle sessioni inutilizzate. può peggiorare le prestazioni. Per gli utenti che utilizzano l'API RPC, consigliamo di avere non più di 100 sessioni per canale gRPC.

Gestire le sessioni eliminate

Esistono tre modi per eliminare una sessione:

  • Un cliente può eliminare una sessione.
  • Il servizio di database Spanner può eliminare una sessione quando questa inattivo per più di un'ora.
  • Il servizio di database Spanner può eliminare una sessione se quest'ultima è più di 28 giorni fa.

I tentativi di utilizzare una sessione eliminata restituiscono NOT_FOUND. Se riscontri creare e utilizzare una nuova sessione, aggiungere la nuova sessione al pool e per rimuovere la sessione eliminata dal pool.

Mantieni attiva una sessione inattiva

Il servizio di database Spanner si riserva il diritto di eliminare un database inutilizzato durante la sessione. Se hai sicuramente bisogno di mantenere attiva una sessione di inattività, ad esempio, previsto un aumento significativo a breve termine nell'uso del database, quindi puoi evitare la sessione non venga abbandonata. Eseguire un'operazione poco costosa, ad esempio eseguendo la query SQL SELECT 1 per mantenere attiva la sessione. Se disponi di un sessione inattiva che non è necessaria per l'uso a breve termine, lascia che Spanner abbandoni e poi crearne una nuova la volta successiva che è necessaria una sessione.

Uno scenario per mantenere attive le sessioni è gestire il picco della domanda regolare sul per configurare un database. Se l'utilizzo intensivo del database avviene ogni giorno dalle 9:00 alle 18:00, mantenere attive alcune sessioni inattive durante quel periodo, dato che è probabile richiesta per il picco di utilizzo. Dopo le 18:00, puoi lasciare che Spanner si limiti sessioni inattive. Prima delle 09:00 di ogni giorno, crea alcune nuove sessioni in modo che sia pronto per la domanda prevista.

Un altro scenario è se un'applicazione utilizza Spanner, devono evitare l'overhead della connessione quando succede. Puoi conservare un insieme di sessioni per evitare l'overhead della connessione.

Nascondi i dettagli della sessione all'utente della libreria client

Se stai creando una libreria client, non esporre le sessioni al client consumer delle biblioteche. Consentire al client di effettuare chiamate al database senza la complessità di creare e gestire le sessioni. Ad esempio, libreria client che nasconde i dettagli della sessione al consumer della libreria client, consulta la libreria client Spanner per Java.

Gestire gli errori per le transazioni di scrittura non idempotenti

Le transazioni di scrittura senza protezione dalla replica potrebbero applicare le mutazioni più di una volta. Se una mutazione non è idempotente, una mutazione applicata più di una volta potrebbe causare un errore. Ad esempio, un inserimento potrebbe non riuscire con ALREADY_EXISTS anche se la riga non esisteva prima del tentativo di scrittura. Questo può accadere se il server di backend ha eseguito il commit della mutazione, ma non è stato in grado di comunicare l'esito positivo al cliente. In questo caso, la mutazione potrebbe essere riprovato, causando l'errore ALREADY_EXISTS.

Di seguito sono riportati alcuni modi per risolvere questo scenario quando implementi i tuoi libreria client o utilizza l'API REST:

  • Struttura le tue scritture in modo che sia idempotente.
  • Utilizza operazioni di scrittura con protezione dalla riproduzione.
  • Implementare un metodo che esegue "upert" logica: inserisci se è nuova o aggiorna se esiste.
  • Gestire l'errore per conto del client.

Mantieni connessioni stabili

Per ottenere le migliori prestazioni, la connessione che utilizzi per ospitare una sessione rimangono stabili. Quando la connessione che ospita una sessione cambia, Spanner potrebbe interrompere la transazione attiva sulla sessione e causare carico aggiuntivo sul database durante l'aggiornamento dei metadati della sessione. Va bene se connessioni cambiano sporadicamente, ma è bene evitare situazioni che modificherebbe un numero elevato di connessioni contemporaneamente. Se utilizzi un proxy tra il client e Spanner, devi mantenere la stabilità della connessione per ogni sessione.

Monitora le sessioni attive

Puoi utilizzare il comando ListSessions per monitorare le sessioni attive nel database dalla riga di comando, con l'API REST o con l'API RPC. ListSessions mostra le sessioni attive per un determinato database. Questo è utile se devi a trovare la causa di una fuga di sessione. (una fuga di sessione è un incidente in cui vengono creati, ma non restituiti a un pool di sessioni per il riutilizzo).

ListSessions ti consente di visualizzare i metadati relativi alle tue sessioni attive, tra cui quando è stata creata una sessione e quando è stata utilizzata l'ultima volta. Analisi di questi dati ti indicheranno la direzione giusta durante la risoluzione dei problemi relativi alle sessioni. Se la maggior parte sessioni attive non hanno un approximate_last_use_time recente, questo potrebbe indicano che le sessioni non vengono riutilizzate correttamente dall'applicazione. Consulta le Riferimento API RPC per ulteriori informazioni sul campo approximate_last_use_time.

Consulta il riferimento per l'API REST, il riferimento per l'API RPC o lo strumento gcloud riferimento dello strumento a riga di comando per ulteriori informazioni sull'utilizzo di ListSessions.

Pulizia automatica delle perdite di sessioni

Quando utilizzi tutte le sessioni nel tuo pool di sessioni, ogni nuova transazione attende che venga restituita una sessione al pool. Quando vengono create le sessioni ma non restituiti al pool di sessioni per essere riutilizzati, si parla di perdita di sessioni. In caso di perdita di una sessione, le transazioni in attesa di una sessione aperta si bloccano a tempo indeterminato e bloccare l'applicazione. Le perdite di sessioni sono spesso causate transazioni problematiche eseguite per un periodo di tempo estremamente lungo non si sono impegnati.

Puoi configurare il pool di sessioni per risolvere automaticamente questi transazioni non attive. Quando attivi la libreria client per eseguire risolvere transizioni inattive, identifica le transazioni problematiche potrebbe causare una fuga di sessioni, quest'ultima verrà rimossa dal pool di sessioni e le sostituisce con una nuova sessione.

Il logging può anche aiutare a identificare queste transazioni problematiche. Se il logging è abilitato, i log degli avvisi vengono condivisi per impostazione predefinita quando più di Il 95% del pool di sessioni è in uso. Se l'utilizzo della sessione è superiore al 95%, devi aumentare il numero massimo di sessioni consentite nel pool di sessioni, o si è verificata una fuga di dati di una sessione. I log degli avvisi contengono stack di transazioni eseguite più a lungo del previsto e che possono per identificare la causa dell'utilizzo elevato del pool di sessioni. Il push dei log degli avvisi dipende dalla configurazione dell'esportatore di log.

Attiva la libreria client per risolvere automaticamente le transazioni inattive

Puoi abilitare la libreria client per l'invio di log degli avvisi e, risolvere le transazioni inattive o abilitare la libreria client per ricevere solo avvisi logaritmi.

Java

Per ricevere i log degli avvisi e rimuovere le transazioni non attive, utilizza setWarnAndCloseIfInactiveTransactions.

 final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnAndCloseIfInactiveTransactions().build()

 final Spanner spanner =
         SpannerOptions.newBuilder()
             .setSessionPoolOption(sessionPoolOptions)
             .build()
             .getService();
 final DatabaseClient client = spanner.getDatabaseClient(databaseId);

Per ricevere solo i log degli avvisi, utilizza setWarnIfInactiveTransactions.

 final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnIfInactiveTransactions().build()

 final Spanner spanner =
         SpannerOptions.newBuilder()
             .setSessionPoolOption(sessionPoolOptions)
             .build()
             .getService();
 final DatabaseClient client = spanner.getDatabaseClient(databaseId);

Vai

Per ricevere i log degli avvisi e rimuovere le transazioni inattive, utilizza SessionPoolConfig con 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()

Per ricevere solo i log degli avvisi, utilizza 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)

Sessioni multiplex

Le sessioni multiplex ti consentono di creare un numero illimitato di richieste simultanee contemporaneamente. Le sessioni multiplex presentano i seguenti vantaggi:

  • Requisiti delle risorse di backend ridotti. Ad esempio, evitano le attività associate al mantenimento della proprietà della sessione e garbage collection.
  • Sessione di lunga durata che non richiede richieste keep-alive in caso di inattività.
  • Le librerie client tipiche possono utilizzare una sessione multiplex per ogni client. La di sessioni regolari in uso è inferiore per i client che usano multiplex per alcune operazioni rispetto ai client che utilizzano solo sessioni.
  • Non è necessario avere affinità con un solo canale gRPC. I client possono inviare richieste su più canali per la stessa sessione multiplex.

Le sessioni multiplex supportano quanto segue:

  • Libreria client Java
  • gli strumenti dell'ecosistema Spanner che dipendono dalla libreria client Java, come PGAdapter, JDBC e Hibernate
  • API Spanner per le transazioni di sola lettura

Puoi utilizzare le metriche di OpenTelemetry per vedere come viene suddiviso il traffico. tra il pool di sessioni esistente e la sessione multiplex. OpenTelemetry ha un filtro per le metriche, is_multiplexed, che mostra le sessioni multiplex se impostato su true.

Le sessioni multiplex sono abilitate per impostazione predefinita per gli adattatori JDBC e PG. Per Java librerie client, è disabilitata per impostazione predefinita. Puoi utilizzare Libreria client Java da attivare sessioni multiplex. Per attivare una sessione multiplex utilizzando Java, consulta Abilita le sessioni multiplex.

Attiva sessioni multiplex

Per abilitare le sessioni multiplex utilizzando il client Java, imposta Da GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS a true.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE

Visualizza il traffico per sessioni standard e multiplex

Opentelemetry ha il filtro is_multiplexed per mostrare il traffico per sessioni multiplex. Imposti questo filtro su true to view multiplexed sessions andfalse per visualizzare le sessioni regolari.

  1. Configurare Opentelemetry per Spanner utilizzando le procedure in Spanner Opentelemetry Prima di iniziare .
  2. Vai a Esplora metriche.

    Vai a Esplora metriche

  3. Nel menu a discesa Metrica, filtra in base a generic.

  4. Fai clic su Attività generica e vai a Spanner > Spanner/num_acquired_sessions.

  5. Nel campo Filtro, seleziona una delle seguenti opzioni:

    a. is_multiplexed = false per visualizzare sessioni regolari. b. is_multiplexed = true per visualizzare le sessioni multiplex.

    Nell'immagine seguente viene mostrata l'opzione Filtro con sessioni multiplex selezionato.

Per saperne di più sull'uso di OpenTelemetry con Spanner, vedi Sfruttare OpenTelemetry per democratizzare Spanner Observability e Esaminare la latenza in un componente Spanner con OpenTelemetry.

Apri la dashboard di telemetria che mostra il filtro è multiplex.