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 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. Di conseguenza, di creare più clienti invece di aumentare la dimensione del oltre 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. Dovresti modificare il impostazioni predefinite del pool di sessioni solo se prevedi una singola istanza di applicazione per eseguire più transazioni simultanee rispetto a quelle che è in grado di gestire il pool di sessioni predefinito.
Per le applicazioni ad alta contemporaneità, si consiglia di:
- Imposta
MinSessions
sul numero previsto di transazioni simultanee che un il singolo client. - Imposta
MaxSessions
sul numero massimo di transazioni simultanee che un che un singolo client possa eseguire. - 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. - Imposta
NumChannels
suMaxSessions / 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 superano l'effettiva necessità dell'applicazione potrebbe ridurre 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 non è consigliabile. 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:
- Ogni canale gRPC utilizza una connessione TCP.
- Ogni chiamata gRPC richiede un thread. Il numero massimo di thread utilizzati dalla libreria client è uguale al numero massimo di per 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 delle 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 sono descritte le best practice per l'implementazione delle sessioni in un client libreria per Spanner o per l'utilizzo di sessioni con il token 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 modello non utilizzato
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
sessione precedente, per poi crearne una nuova la volta successiva che sarà necessaria.
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 siano idempotenti.
- 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 extra sul database mentre aggiorna i 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 del 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 causa una fuga di sessioni, la rimozione dal pool di sessioni 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 notizie. 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:
- Le librerie client di Java e Go.
- gli strumenti dell'ecosistema Spanner che dipendono dalle librerie client Java e Go, come PGAdapter, JDBC, Hibernate, driver di database/sql e GORM.
- 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 e Go librerie client, è disabilitata per impostazione predefinita. Puoi utilizzare Libreria client Java o libreria client Go per attivare sessioni multiplex. Per attivare una sessione multiplex utilizzando Java o Go, consulta Abilita le sessioni multiplex.
Attiva sessioni multiplex
Per attivare le sessioni multiplex utilizzando il client Java o Go, 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
and
false per visualizzare le sessioni regolari.
- Configurare Opentelemetry per Spanner utilizzando le procedure in Spanner Opentelemetry Prima di iniziare .
Vai a Esplora metriche.
Nel menu a discesa Metrica, filtra in base a
generic
.Fai clic su Attività generica e vai a Spanner > Spanner/num_acquired_sessions.
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.