Sessioni

Questa pagina descrive il concetto avanzato di sessioni in Spanner, incluse le best practice per le sessioni durante la creazione di una libreria client, l'utilizzo delle API REST o RPC o l'utilizzo delle librerie client Google.

Una sessione fornisce un contesto per le operazioni di database con il servizio di database Spanner. Una sessione viene utilizzata per eseguire transazioni che leggono, scrivono o modificano i dati in un database Spanner. Ogni sessione si applica a un singolo database.

Le sessioni possono eseguire una o più transazioni alla volta. Quando vengono eseguite più transazioni, la sessione viene chiamata sessione multiplexata. Le letture, le scritture e le query autonome utilizzano internamente una transazione.

Gestire il rendimento delle sessioni

Le sessioni sono il contesto per un'operazione di database, quindi il modo in cui le gestisci influisce direttamente sulla latenza e sull'utilizzo delle risorse della tua applicazione. Puoi gestire il rendimento delle sessioni nei tre modi seguenti:

Utilizzare un pool di sessioni

La creazione di una sessione aggiunge latenza perché ogni nuova sessione richiede un round trip al servizio di database Spanner. Per ridurre questa latenza, utilizza un pool di sessioni: una raccolta di sessioni disponibili pronte per l'uso. Anziché creare una sessione per ogni operazione, il pool restituisce una sessione esistente e la recupera per il riutilizzo successivo. In questo modo, la latenza di creazione della sessione viene distribuita su molte operazioni anziché essere eliminata completamente. Il pool memorizza le sessioni esistenti, restituisce il tipo di sessione appropriato quando richiesto e pulisce le sessioni inutilizzate.

Le sessioni sono pensate per durare a lungo, quindi dopo che una sessione viene utilizzata per un'operazione di database, il client deve restituirla al pool per il riutilizzo.

Utilizzare sessioni multiplex

Le sessioni multiplexate consentono di effettuare più richieste simultanee in una singola sessione, riducendo l'overhead del backend e il consumo di risorse. Per saperne di più, consulta Sessioni multiplexate.

Ottimizza la configurazione del canale gRPC

Ridurre la latenza di coda elevata (p95/p99) causata dalla congestione del canale gRPC durante il traffico elevato modificando il pool di canali gRPC. Nelle librerie client supportate, il pooling dinamico dei canali ridimensiona automaticamente il pool di canali in base alle variazioni del carico. Ciò contribuisce a ridurre la latenza finale correlata alla congestione e a evitare il sottoprovisioning o l'overprovisioning dei canali.

Panoramica dei canali gRPC

I canali gRPC vengono utilizzati dal client Spanner per la comunicazione. Un canale gRPC equivale approssimativamente a una connessione TCP. Un canale gRPC può gestire fino a 100 richieste simultanee. Ciò significa che un'applicazione avrà bisogno di almeno un numero di canali gRPC pari al numero di richieste simultanee che l'applicazione eseguirà, diviso per 100.

Il client Spanner crea un pool di canali gRPC quando lo crei.

Best practice per l'utilizzo delle librerie client Google

Di seguito sono descritte le best practice per l'utilizzo delle librerie client Google per Spanner.

Configura il numero di sessioni e canali gRPC nei pool

Il modo in cui gestisci le sessioni e i canali gRPC dipende dalla libreria client. Le librerie client che supportano sessioni multiplexate, come le librerie client Go e Java, non richiedono la configurazione di un pool di sessioni e possono gestire il pool di canali gRPC per te tramite il pooling dinamico dei canali. Le altre librerie client utilizzano un pool di sessioni con un numero minimo e massimo predefinito di sessioni e un numero predefinito di canali gRPC. I valori predefiniti sono adeguati per la maggior parte dei casi. Le sezioni seguenti descrivono le opzioni di configurazione e i valori predefiniti per ogni linguaggio di programmazione.

C++

MinSessions: 100
MaxSessions: 400
NumChannels: 4

C#

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Vai

Le sessioni multiplex sono attive per impostazione predefinita e non richiedono alcuna configurazione.

Il raggruppamento dinamico dei canali è una funzionalità attivabile. Se non lo abiliti, il client utilizza quattro canali gRPC. Per utilizzare un numero fisso diverso di canali gRPC, utilizza l'opzione option.WithGRPCConnectionPool quando crei il client:

// 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),
)

Questo esempio richiede il pacchetto google.golang.org/api/option.

Per attivare il raggruppamento dinamico dei canali, imposta l'opzione DCPEnabled su true in DynamicChannelPoolConfig:

client, err := spanner.NewClientWithConfig(ctx,
    "projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID",
    spanner.ClientConfig{
        DynamicChannelPoolConfig: spanner.DynamicChannelPoolConfig{
            DCPEnabled: true,
        },
    })

Quando abiliti il pooling dinamico dei canali senza impostare opzioni personalizzate, la libreria client Go applica i seguenti valori predefiniti:

  • Dimensioni iniziali del pool: 4 canali
  • Dimensioni minime del pool: 2 canali
  • Dimensioni massime del pool: 10 canali
  • Soglia di scalabilità: 25 RPC simultanee per canale
  • Soglia di riduzione: 15 RPC simultanee per canale
  • Intervallo di controllo dello scale down: 3 minuti

Per personalizzare il pool, imposta i campi della struttura DynamicChannelPoolConfig, come DCPInitialChannels, DCPMinChannels, DCPMaxChannels, DCPMaxRPCPerChannel e DCPMinRPCPerChannel.

Java

Le sessioni multiplex sono abilitate per impostazione predefinita nella versione 6.98.0 o successive della libreria client Java e non richiedono alcuna configurazione. Per ulteriori informazioni, consulta la sezione Sessioni multiplexate.

Il pooling dinamico dei canali è disattivato per impostazione predefinita per la libreria client Java e deve essere attivato utilizzando SpannerOptions. Se il raggruppamento dinamico dei canali non è abilitato, la libreria client Java utilizza 4 canali gRPC (8 canali quando l'estensione gRPC-GCP è abilitata). Quando il pooling dinamico dei canali è attivato, la libreria client ridimensiona il pool di canali gRPC per adattarsi ai carichi di lavoro in evoluzione, il che aiuta a prevenire problemi di prestazioni dovuti a canali con provisioning insufficiente o eccessivo.

Per attivare il pooling dinamico dei canali, includi enableDynamicChannelPool in SpannerOptions:

SpannerOptions options =
    SpannerOptions.newBuilder()
        .setProjectId("PROJECT_ID")
        .enableDynamicChannelPool()
        .build();

Se configuri il numero di canali utilizzando setNumChannels, Spanner disattiva il pooling dinamico dei canali e utilizza un numero statico di canali.

Quando attivi il pooling dinamico dei canali senza impostare opzioni personalizzate tramite setGcpChannelPoolOptions, la libreria client Java applica le seguenti impostazioni predefinite, ottimizzate per i carichi di lavoro tipici:

  • Dimensioni iniziali del pool: 4 canali
  • Dimensioni minime del pool: 2 canali
  • Dimensioni massime del pool: 10 canali (limite massimo: 256 canali)
  • Soglia di scalabilità: 25 RPC simultanee per canale
  • Soglia di riduzione: 15 RPC simultanee per canale
  • Intervallo di riduzione della scalabilità: 3 minuti

Per personalizzare il raggruppamento dinamico dei canali, utilizza setGcpChannelPoolOptions. Ad esempio:

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();

Tieni in considerazione i seguenti compromessi del raggruppamento dinamico dei canali:

  • Overhead di scalabilità: lo scaling del pool comporta un overhead dovuto alla creazione e all'eliminazione di canali gRPC e connessioni TCP. Per i carichi di lavoro sensibili alla latenza con picchi improvvisi, un pool statico di grandi dimensioni potrebbe essere una scelta migliore per evitare la latenza di scalabilità.
  • Override della configurazione: l'impostazione del numero di base di canali disattiva il raggruppamento dinamico dei canali. Per saperne di più, consulta setNumChannels
  • Utilizzo delle risorse: un pool di canali statico utilizza una quantità fissa di memoria e connessioni, mentre l'utilizzo delle risorse di un pool dinamico varia in base al carico.

Node.js

Il client Node.js non supporta più canali gRPC. Pertanto, è consigliabile creare più client anziché aumentare le dimensioni del pool di sessioni oltre 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. Pertanto, è consigliabile creare più client anziché aumentare le dimensioni del pool di sessioni oltre 100 sessioni per un singolo client.

MinSessions: 10
MaxSessions: 100

Utilizza sessioni multiplexate se la libreria client per il tuo linguaggio di programmazione le supporta. Le sessioni multiplex non richiedono alcuna configurazione e una singola sessione multiplex può eseguire un numero qualsiasi di transazioni simultanee.

Il numero di sessioni utilizzate dall'applicazione è uguale al numero di transazioni simultanee eseguite dall'applicazione. Devi modificare le impostazioni del pool di sessioni predefinito solo se prevedi che una singola istanza dell'applicazione esegua più transazioni simultanee di quelle che il pool di sessioni predefinito può gestire.

Per le applicazioni con concorrenza elevata, si consiglia quanto segue:

  1. Imposta MinSessions sul numero previsto di transazioni simultanee che un singolo client eseguirà.
  2. Imposta MaxSessions sul numero massimo di transazioni simultanee che un singolo client può eseguire.
  3. Imposta MinSessions=MaxSessions se la concorrenza prevista non cambia molto durante il ciclo di vita dell'applicazione. In questo modo, il pool di sessioni non viene scalato verso l'alto o verso il basso. Anche lo scale up o down del pool di sessioni consuma alcune risorse.
  4. Imposta NumChannels su MaxSessions / 100. Un canale gRPC può gestire fino a 100 richieste contemporaneamente. Aumenta questo valore se osservi una latenza di coda elevata (latenza p95/p99), perché potrebbe essere un'indicazione di congestione del canale gRPC.

L'aumento del numero di sessioni attive utilizza risorse aggiuntive nel servizio di database Spanner e nella libreria client. Aumentare il numero di sessioni oltre le esigenze effettive dell'applicazione potrebbe ridurre le prestazioni del sistema.

Aumentare il pool di sessioni anziché il numero di client

La dimensione del pool di sessioni per un'applicazione determina il numero di transazioni simultanee che una singola istanza dell'applicazione può eseguire. Non è consigliabile aumentare le dimensioni del pool di sessioni oltre la concorrenza massima che una singola istanza dell'applicazione può gestire. Se l'applicazione riceve un burst di richieste che supera il numero di sessioni nel pool, le richieste vengono messe in coda in attesa 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 gRPC richiede un thread. Il numero massimo di thread utilizzato dalla libreria client è uguale al numero massimo di query simultanee eseguite dall'applicazione. Questi thread si aggiungono a quelli che l'applicazione utilizza per la propria logica di business.

Non è consigliabile aumentare le dimensioni del pool di sessioni oltre il numero massimo di thread che una singola istanza dell'applicazione può gestire. Aumenta invece il numero di istanze dell'applicazione.

Gestire la frazione di sessioni di scrittura

Per alcune librerie client, Spanner riserva una parte delle sessioni per le transazioni di lettura/scrittura, chiamata frazione di sessioni di scrittura. Se la tua app utilizza tutte le sessioni di lettura, Spanner utilizza le sessioni di lettura/scrittura, anche per le transazioni di sola lettura. Le sessioni di lettura/scrittura richiedono spanner.databases.beginOrRollbackReadWriteTransaction. Se l'utente dispone del ruolo IAM 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 di sessioni di scrittura.

C++

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

C#

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

Vai

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

Java

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

Node.js

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

PHP

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

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 la frazione utilizzando il metodo di inizializzazione del client.

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

Di seguito sono descritte le best practice per l'implementazione delle sessioni in una libreria client per Spanner o per l'utilizzo delle sessioni con le API REST o RPC.

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

Creare e dimensionare il pool di sessioni

Per determinare una dimensione ottimale del pool di sessioni per un processo client, imposta il limite inferiore sul numero di transazioni simultanee previste e il limite superiore su un numero di test iniziale, ad esempio 100. Se il limite superiore non è adeguato, aumentalo. L'aumento del numero di sessioni attive utilizza risorse aggiuntive nel servizio di database Spanner, pertanto la mancata pulizia delle sessioni inutilizzate può peggiorare le prestazioni. Per gli utenti che lavorano con l'API RPC, consigliamo di non superare le 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 è inattiva per più di un'ora.
  • Il servizio di database Spanner potrebbe eliminare una sessione se ha più di 28 giorni.

I tentativi di utilizzare una sessione eliminata generano NOT_FOUND. Se si verifica questo errore, crea e utilizza una nuova sessione, aggiungila al pool e rimuovi la sessione eliminata dal pool.

Mantenere attiva una sessione inattiva

Il servizio di database Spanner si riserva il diritto di eliminare una sessione inutilizzata. Se devi assolutamente mantenere attiva una sessione inattiva, ad esempio se è previsto un aumento significativo e a breve termine dell'utilizzo del database, puoi impedire che la sessione venga interrotta. Esegui un'operazione economica come l'esecuzione della query SQL SELECT 1 per mantenere attiva la sessione. Se hai una sessione inattiva che non è necessaria per l'utilizzo a breve termine, lascia che Spanner la elimini e creane una nuova la volta successiva che ne avrai bisogno.

Uno scenario per mantenere attive le sessioni è gestire la domanda di picco regolare sul database. Se l'utilizzo intenso del database si verifica ogni giorno dalle 9:00 alle 18:00, devi mantenere attive alcune sessioni inattive durante questo periodo, poiché è probabile che siano necessarie per il picco di utilizzo. Dopo le 18:00, puoi consentire a Spanner di eliminare le sessioni inattive. Prima delle 9:00 di ogni giorno, crea alcune nuove sessioni in modo che siano pronte per la domanda prevista.

Un altro scenario è quello in cui hai un'applicazione che utilizza Spanner, ma deve evitare l'overhead di connessione quando lo fa. Puoi mantenere attivo un insieme di sessioni per evitare l'overhead di connessione.

Nascondere i dettagli della sessione all'utente della libreria client

Se stai creando una libreria client, non esporre le sessioni al consumatore della libreria client. Offre al client la possibilità di effettuare chiamate al database senza la complessità di creare e gestire le sessioni. Per un esempio di 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 di riproduzione potrebbero applicare le mutazioni più di una volta. Se una mutazione non è idempotente, una mutazione applicata più di una volta potrebbe comportare un errore. Ad esempio, un inserimento potrebbe non riuscire con ALREADY_EXISTS anche se la riga non esisteva prima del tentativo di scrittura. Ciò potrebbe verificarsi se il server di backend ha eseguito la mutazione, ma non è stato in grado di comunicare l'esito positivo al client. In questo caso, il tentativo di mutazione potrebbe essere ripetuto, causando l'errore ALREADY_EXISTS.

Ecco alcuni modi possibili per risolvere questo scenario quando implementi la tua libreria client o utilizzi l'API REST:

  • Struttura le scritture in modo che siano idempotenti.
  • Utilizza le scritture con protezione dalla riproduzione.
  • Implementa un metodo che esegue la logica "upsert": inserisci se nuovo o aggiorna se esiste.
  • Gestisci l'errore per conto del client.

Mantenere connessioni stabili

Per ottenere prestazioni ottimali, la connessione che utilizzi per ospitare una sessione deve rimanere stabile. Quando la connessione che ospita una sessione cambia, Spanner potrebbe interrompere la transazione attiva nella sessione e causare un piccolo carico aggiuntivo sul database durante l'aggiornamento dei metadati della sessione. È normale che alcune connessioni cambino sporadicamente, ma devi evitare situazioni che comportino la modifica di un numero elevato di connessioni contemporaneamente. Se utilizzi un proxy tra il client e Spanner, devi mantenere la stabilità della connessione per ogni sessione.

Monitorare le sessioni attive

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

ListSessions ti consente di visualizzare i metadati relativi alle tue sessioni attive, tra cui la data di creazione e l'ultimo utilizzo di una sessione. L'analisi di questi dati ti indicherà la direzione giusta per la risoluzione dei problemi relativi alle sessioni. Se la maggior parte delle sessioni attive non ha un approximate_last_use_time recente, ciò potrebbe indicare che le sessioni non vengono riutilizzate correttamente dalla tua applicazione. Per ulteriori informazioni sul campo approximate_last_use_time, consulta il riferimento all'API RPC.

Per ulteriori informazioni sull'utilizzo di ListSessions, consulta il riferimento API REST, il riferimento API RPC o il riferimento allo strumento a riga di comando gcloud.

Pulizia automatica delle perdite di sessione

Quando utilizzi tutte le sessioni nel pool di sessioni, ogni nuova transazione attende che una sessione venga restituita al pool. Quando le sessioni vengono create ma non vengono restituite al pool di sessioni per il riutilizzo, si parla di perdita di sessione. Quando si verifica una perdita di sessione, le transazioni in attesa di una sessione aperta rimangono bloccate indefinitamente e bloccano l'applicazione. Le perdite di sessione sono spesso causate da transazioni problematiche in esecuzione per un periodo di tempo estremamente lungo e non confermate.

Puoi configurare il pool di sessioni in modo che risolva automaticamente queste transazioni inattive. Quando abiliti la libreria client per risolvere automaticamente la transizione inattiva, identifica le transazioni problematiche che potrebbero causare una perdita di sessione, le rimuove dal pool di sessioni e le sostituisce con una nuova sessione.

La registrazione può anche aiutare a identificare queste transazioni problematiche. Se la registrazione è abilitata, i log di avviso vengono condivisi per impostazione predefinita quando è in uso più del 95% del pool di sessioni. Se l'utilizzo delle sessioni è superiore al 95%, devi aumentare il numero massimo di sessioni consentite nel pool di sessioni o potresti avere una perdita di sessioni. I log di avviso contengono stack trace delle transazioni che vengono eseguite più a lungo del previsto e possono aiutare a identificare la causa dell'utilizzo elevato del pool di sessioni. I log di avviso vengono inviati in base alla configurazione dell'esportatore di log.

Consentire alla libreria client di risolvere automaticamente le transazioni inattive

Puoi abilitare la libreria client per inviare log di avviso e risolvere automaticamente le transazioni inattive oppure abilitare la libreria client per ricevere solo log di avviso.

Java

Per ricevere log di avviso e rimuovere le transazioni inattive, 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 di avviso, 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 log di avviso 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 di avviso, 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 multiplexate

Le sessioni multiplexate consentono di creare un numero elevato di richieste simultanee in una singola sessione. Una sessione multiplexata è un identificatore che utilizzi in più canali gRPC. Non introduce colli di bottiglia aggiuntivi. Le sessioni multiplexate presentano i seguenti vantaggi:

  • Riduzione del consumo di risorse di backend grazie a un protocollo di gestione delle sessioni più semplice. Ad esempio, evitano le attività di manutenzione della sessione associate alla manutenzione della proprietà della sessione e alla garbage collection.
  • Sessione di lunga durata che non richiede richieste keep-alive quando è inattiva.

Le sessioni multiplex sono supportate in:

  • Le librerie client C++, Go, Java, Node.js, PHP, Python e Ruby.
  • Strumenti dell'ecosistema Spanner che dipendono dalle librerie client menzionate, come PGAdapter, JDBC, Hibernate, driver database/sql, driver dbAPI e GORM.

  • Strumenti dell'ecosistema Spanner che dipendono dalle librerie client Java e Go, come PGAdapter, JDBC, Hibernate, driver di database o SQL e GORM. Puoi utilizzare le metriche OpenTelemetry per vedere come viene suddiviso il traffico tra il pool di sessioni esistente e la sessione multiplexata. OpenTelemetry ha un filtro delle metriche, is_multiplexed, che mostra le sessioni multiplexate quando è impostato su true.

Le sessioni multiplexate sono supportate per tutti i tipi di transazioni.

Le librerie client ruotano le sessioni multiplexate ogni 7 giorni per evitare l'invio di transazioni su sessioni obsolete.

Le sessioni multiplex sono abilitate per impostazione predefinita in alcune librerie client. Per altri, devi utilizzare le variabili di ambiente per attivarli. Per maggiori dettagli, vedi Attivare le sessioni multiplexate.

Considerazioni

Se stai tentando di eseguire il commit di un corpo di transazione di lettura o scrittura vuoto o di una transazione in cui ogni query o istruzione DML non è riuscita, ci sono un paio di scenari da considerare con le sessioni multiplexate. Le sessioni multiplex richiedono che tu includa un token pre-commit generato dal server in ogni richiesta di commit. Per le transazioni che contengono query o DML, deve esistere almeno una query o una transazione DML precedente riuscita affinché il server invii un token valido alla libreria client. Se non sono state eseguite query o transazioni DML riusciti, la libreria client aggiunge implicitamente SELECT 1 prima di un commit.

Per una transazione di lettura o scrittura su una sessione multiplexata che contiene solo mutazioni, se una delle mutazioni riguarda una tabella o una colonna che NON esiste nello schema, il client potrebbe restituire un errore INVALID_ARGUMENT anziché un errore NOT_FOUND.

Abilita sessioni multiplex

Le sessioni multiplex sono abilitate per impostazione predefinita nelle seguenti librerie client:

  • C++ nella versione 2.41.0 e successive.
  • A partire dalla versione 1.85.0.
  • Java nella versione 6.98.0 e successive.
  • Node.js versione 8.3.0 e successive.
  • PHP nella versione 2.0.0 e successive.
  • Python versione 3.57.0 e successive.
  • Ruby versione 2.30.0 e successive.

Per utilizzare le sessioni multiplex nelle versioni precedenti delle librerie client Node.js, Java e Go, devi prima impostare una variabile di ambiente per abilitarle.

Per attivare le sessioni multiplex, imposta la variabile di ambiente GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS su TRUE. Questo flag attiva anche il supporto delle sessioni multiplexate per le transazioni ReadOnly.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE

Per abilitare il supporto delle operazioni partizionate per le sessioni multiplexate, imposta la variabile di ambiente GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS su TRUE.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS=TRUE

Per abilitare il supporto delle transazioni di lettura/scrittura per le sessioni multiplexate, imposta la variabile di ambiente GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW su TRUE.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW=True

Devi impostare GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS su TRUE come prerequisito per supportare una transazione in una sessione multiplexata.

Visualizzare il traffico per sessioni regolari e multiplex

OpenTelemetry include il filtro is_multiplexed per mostrare il traffico per le sessioni multiplexate. Imposta questo filtro su true per visualizzare le sessioni multiplex o su false per visualizzare le sessioni regolari.

  1. Configura OpenTelemetry per Spanner utilizzando le procedure descritte nella sezione Prima di iniziare di Spanner OpenTelemetry.
  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 le sessioni regolari. b. is_multiplexed = true per visualizzare le sessioni multiplexate.

    L'immagine seguente mostra l'opzione Filtra con le sessioni multiplexate selezionate.

Per saperne di più sull'utilizzo di OpenTelemetry con Spanner, consulta Sfruttare OpenTelemetry per democratizzare l'osservabilità di Spanner e Esaminare la latenza in un componente Spanner con OpenTelemetry.

Dashboard di OpenTelemetry che mostra il filtro is-multiplexed.

Risoluzione dei problemi

Gli errori comuni relativi alla sessione che la tua applicazione potrebbe riscontrare includono:

  • Session not found
  • RESOURCE_EXHAUSTED

Per saperne di più, consulta la sezione Errori di sessione.