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 di 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 esegue più transazioni, la sessione viene chiamata sessione multiplexata. Le letture, le scritture e le query autonome utilizzano una transazione internamente.

Gestisci il rendimento delle sessioni

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

Utilizza 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 riutilizzarla in un secondo momento. In questo modo, la latenza di creazione delle sessioni viene distribuita su molte operazioni anziché essere eliminata completamente. Il pool archivia le sessioni esistenti, restituisce il tipo di sessione appropriato quando richiesto e pulisce le sessioni inutilizzate.

Le sessioni sono progettate per essere di lunga durata, quindi dopo che una sessione viene utilizzata per un'operazione sul database, il client deve restituirla al pool per il riutilizzo.

Utilizza sessioni multiplexate

Le sessioni multiplexate consentono di effettuare più richieste in parallelo su 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

Riduci la latenza di coda elevata (p95/p99) causata dalla congestione del canale gRPC durante il traffico elevato ottimizzando 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. In questo modo, si riduce la latenza di coda correlata alla congestione e si evita il provisioning insufficiente o eccessivo dei canali.

Panoramica dei canali gRPC

I canali gRPC vengono utilizzati dal client Spanner per la comunicazione. Un canale gRPC equivale all'incirca a una connessione TCP. Un canale gRPC può gestire fino a 100 richieste in parallelo. Ciò significa che un'applicazione avrà bisogno di un numero di canali gRPC pari almeno al numero di richieste in parallelo 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 di Google

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

Configura il numero di sessioni e canali gRPC nei pool

La modalità di gestione delle sessioni e dei canali gRPC dipende dalla libreria client. Le librerie client che supportano le sessioni multiplex, 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 impostazioni predefinite e le opzioni di configurazione per ogni linguaggio di programmazione.

C++

MinSessions: 100
MaxSessions: 400
NumChannels: 4

C#

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Vai

Le sessioni multiplexate sono attivate per impostazione predefinita e non richiedono alcuna configurazione.

Il pooling dinamico dei canali è una funzionalità attivabile. Se non lo attivi, 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 pooling 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 attivi il pooling dinamico dei canali senza impostare opzioni personalizzate, la libreria client Go applica le seguenti impostazioni predefinite:

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

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

Java

Le sessioni multiplexate sono abilitate per impostazione predefinita nella versione 6.98.0 o successive della libreria client Java e non richiedono alcuna configurazione. Per saperne di più, consulta Sessioni multiplexate.

Il pooling dinamico dei canali è disattivato per impostazione predefinita per la libreria client Java e deve essere attivato utilizzando SpannerOptions. Se il pooling 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 è abilitato, la libreria client ridimensiona il pool di canali gRPC per adattarsi ai workload 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 i seguenti valori predefiniti, ottimizzati per i workload 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 scale up: 25 RPC simultanee per canale
  • Soglia di scale down: 15 RPC simultanee per canale
  • Intervallo di scale down: 3 minuti

Per personalizzare il pooling 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 presente i seguenti compromessi del pooling dinamico dei canali:

  • Overhead di scalabilità: la scalabilità del pool comporta un overhead dovuto alla creazione e alla distruzione di canali gRPC e connessioni TCP. Per i workload 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 canali di base disattiva il pooling 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

Sessioni regolari

Le sessioni multiplexate sono attivate per impostazione predefinita nella versione 8.3.0 o successive e non richiedono alcuna configurazione. Le versioni precedenti utilizzano sessioni regolari per impostazione predefinita, con le seguenti impostazioni:

MinSessions: 25
MaxSessions: 100

Pooling dei canali

Il pooling dinamico dei canali è abilitato per impostazione predefinita con le seguenti impostazioni:

MaxChannels: 10
ConcurrentRequestsPerChannel: 25

Puoi eseguire l'override delle configurazioni in modo programmatico quando crei un'istanza client di Spanner.

Se si utilizzano sessioni multiplex (impostazione predefinita)

Copia la configurazione channelPool dalla configurazione gRPC di Spanner nella tua applicazione. Non è necessario copiare le definizioni dei metodi e le impostazioni di affinità perché le sessioni multiplexate non richiedono l'associazione sessione-canale.

Ad esempio:

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

Se utilizzi sessioni regolari

Copia la configurazione completa (sia channelPool che le affinità dei metodi) dalla configurazione gRPC di Spanner all'applicazione. L'omissione delle affinità dei metodi può peggiorare le prestazioni perché le richieste perdono l'associazione sessione-canale.

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 le 100 sessioni per un singolo client.

MinSessions: 10
MaxSessions: 100

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

Il numero di sessioni utilizzate dalla tua applicazione è uguale al numero di transazioni simultanee eseguite dalla tua applicazione. Devi modificare le impostazioni predefinite del pool di sessioni 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 elevata contemporaneità, 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 contemporaneità prevista non cambia molto durante il ciclo di vita dell'applicazione. In questo modo, il pool di sessioni non viene sottoposto a scale up o scale down. Anche lo scale up o lo scale 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. L'aumento del numero di sessioni oltre l'effettiva necessità dell'applicazione potrebbe ridurre le prestazioni del sistema.

Aumentare il pool di sessioni anziché il numero di client

Le dimensioni del pool di sessioni per un'applicazione determinano il numero di transazioni simultanee che una singola istanza dell'applicazione può eseguire. Non è consigliabile aumentare le dimensioni del pool di sessioni oltre la contemporaneità massima che una singola istanza dell'applicazione può gestire. Se l'applicazione riceve un picco 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 utilizzati dalla libreria client è uguale al numero massimo di query simultanee eseguite dall'applicazione. Questi thread si aggiungono a quelli utilizzati dall'applicazione 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.

Gestisci 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 l'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 ha il 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 esistono sessioni di sola lettura o di sola lettura/scrittura.

C#

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

Vai

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

Java

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

Node.js

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

PHP

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

Python

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

Ruby

La frazione di sessioni di scrittura predefinita 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 riportate 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 di Google per Spanner, consulta le 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 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 sul servizio di database Spanner, pertanto la mancata pulizia delle sessioni inutilizzate può peggiorare le prestazioni. Per gli utenti che utilizzano l'API RPC, consigliamo di non avere più di 100 sessioni per canale gRPC.

Gestisci 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 è inattiva per più di un'ora.
  • Il servizio di database Spanner potrebbe eliminare una sessione se questa ha più di 28 giorni.

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

Mantieni attiva una sessione inattiva

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

Uno scenario per mantenere attive le sessioni è gestire la normale domanda di picco sul database. Se il database viene utilizzato intensamente ogni giorno dalle 09:00 alle 18:00, devi mantenere attive alcune sessioni inattive durante questo periodo, poiché è probabile che siano necessarie per l'utilizzo di picco. Dopo le 18:00, puoi consentire a Spanner di eliminare le sessioni inattive. Ogni giorno, prima delle 09:00, crea alcune nuove sessioni in modo che siano pronte per la domanda prevista.

Un altro scenario è se 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.

Nascondi i dettagli della sessione all'utente della libreria client

Se stai creando una libreria client, non esporre le sessioni al consumer della libreria client. Offrire al client la possibilità di effettuare chiamate al database senza la complessità della creazione e della gestione delle sessioni. Per un esempio di libreria client che nasconde i dettagli della sessione al consumer della libreria client, consulta la libreria client di Spanner per Java.

Gestisci gli errori per le transazioni di scrittura non idempotenti

Le transazioni di scrittura senza protezione di riproduzione possono 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. Ciò potrebbe verificarsi se il server di backend ha eseguito il commit della mutazione, ma non è riuscito a comunicare l'esito positivo al client. In questo caso, la mutazione potrebbe essere ripetuta, causando l'errore ALREADY_EXISTS.

Ecco i possibili modi per gestire 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 dai replay.
  • Implementa un metodo che esegua la logica "upsert": inserisci se è nuovo o aggiorna se esiste.
  • Gestisci l'errore per conto del client.

Mantieni connessioni stabili

Per 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 dovresti evitare situazioni che modifichino 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 tuo 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 trovare la causa di un leak 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 di attività attive, tra cui la data di creazione e l'ultimo utilizzo di una sessione. L'analisi di questi dati ti aiuterà a risolvere i problemi delle 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 API RPC.

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

Pulizia automatica delle sessioni non chiuse

Quando utilizzi tutte le sessioni nel pool di sessioni, ogni nuova transazione attende finché una sessione non viene 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 un leak di sessione, le transazioni in attesa di una sessione aperta si bloccano a tempo indeterminato e bloccano l'applicazione. Le fughe di sessioni sono spesso causate da transazioni problematiche che vengono eseguite per un periodo di tempo estremamente lungo e non vengono sottoposte a commit.

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 un leak della sessione, le rimuove dal pool di sessioni e le sostituisce con una nuova sessione.

Anche il logging può aiutare a identificare queste transazioni problematiche. Se il logging è abilitato, i log di avviso vengono condivisi per impostazione predefinita quando viene utilizzato 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 oppure potrebbe esserci un leak di sessioni. I log di avviso contengono analisi dello stack delle transazioni che vengono eseguite per un periodo di tempo più lungo del previsto e possono aiutare a identificare la causa di un utilizzo elevato del pool di sessioni. I log di avviso vengono inviati in base alla configurazione dell'esportatore dei log.

Abilita la libreria client per risolvere automaticamente le transazioni inattive

Puoi abilitare la libreria client per l'invio di log di avviso e la risoluzione automatica delle transazioni inattive oppure abilitarla solo per la ricezione di log di avviso.

Java

Per ricevere i log di avviso 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 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 i log di avviso e rimuovere le transazioni non attive, 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 in parallelo su una singola sessione. Una sessione multiplexata è un identificatore che utilizzi su più canali gRPC. Non introduce ulteriori colli di bottiglia. 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 delle sessioni associate alla manutenzione della proprietà delle sessioni e alla garbage collection.
  • Sessione di lunga durata che non richiede richieste keep-alive quando è inattiva.

Le sessioni multiplexate sono supportate nei seguenti casi:

  • Le librerie client C++, Go, Java, Node.js, PHP, Python, Ruby e Rust.
  • 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 se 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 multiplexate sono abilitate per impostazione predefinita in alcune librerie client. Per altri, devi utilizzare le variabili di ambiente per attivarli. Per maggiori dettagli, consulta Attiva 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, esistono un paio di scenari da considerare con le sessioni multiplexate. Le sessioni multiplexate richiedono l'inclusione di un token di pre-commit generato dal server in ogni richiesta di commit. Per le transazioni che contengono query o DML, deve essere presente almeno una transazione di query o DML precedente riuscita affinché il server invii un token valido alla libreria client. Se non sono state eseguite query o transazioni DML riuscite, 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 le sessioni multiplexate

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

  • C++ nella versione 2.41.0 e successive.
  • Go versione 1.85.0 e successive.
  • 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 nella versione 3.57.0 e successive.
  • Ruby nella versione 2.30.0 e successive.

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

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 multiplex, 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 multiplex, 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.

Visualizza il traffico per le sessioni normali e multiplexate

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

  1. Configura OpenTelemetry per Spanner seguendo le procedure descritte nella sezione Prima di iniziare di OpenTelemetry per Spanner.
  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 Filtro con le sessioni multiplexate selezionate.

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

Dashboard di OpenTelemetry che mostra il filtro is-multiplexed.

Risoluzione dei problemi

Gli errori comuni relativi alle sessioni che la tua applicazione potrebbe riscontrare includono:

  • Session not found
  • RESOURCE_EXHAUSTED

Per saperne di più, consulta Errori di sessione.