Sessions

Cette page décrit le concept avancé de sessions dans Spanner. y compris les bonnes pratiques pour les sessions lors de la création d'une bibliothèque cliente, à l'aide des API REST ou RPC, ou des bibliothèques clientes Google.

Présentation des sessions

Une session représente un canal de communication avec la base de données Spanner Google Cloud. Une session permet d'effectuer des transactions qui lisent, écrivent ou modifient dans une base de données Spanner. Chaque session s'applique à une base de données unique.

Les sessions peuvent exécuter une ou plusieurs transactions à la fois. Quand ? plusieurs transactions, la session est appelée session multiplexée.

Les lectures, les écritures et les requêtes autonomes utilisent une transaction en interne.

Avantages d'un pool de sessions en termes de performances

Créer une session coûte cher. Pour éviter les coûts liés aux performances chaque fois qu'une une opération de base de données est effectuée, les clients doivent conserver un pool de session, qui est un pool disponibles et prêtes à être utilisées. Le pool doit stocker les sessions existantes et renvoyer le type de session approprié si vous y êtes invité, et gérer le nettoyage de sessions inutilisées. Pour obtenir un exemple d'implémentation d'un pool de sessions, consultez la le code source de l'une des bibliothèques clientes Spanner, comme Bibliothèque cliente Go ou bibliothèque cliente Java.

Les sessions sont censées avoir une longue durée de vie. Par conséquent, après qu'une session est utilisée pendant opération de base de données, le client doit renvoyer la session au pool pour la réutiliser.

Présentation des canaux gRPC

Les canaux gRPC sont utilisés par le client Spanner pour la communication. Un gRPC est à peu près équivalent à une connexion TCP. Un canal gRPC peut gérer jusqu'à 100 requêtes simultanées. Cela signifie qu'une application a besoin d'au moins autant de canaux gRPC que de requêtes simultanées que l'application divisé par 100.

Le client Spanner crée un pool de canaux gRPC lorsque vous le créer.

Bonnes pratiques concernant l'utilisation des bibliothèques clientes Google

Vous trouverez ci-dessous les bonnes pratiques à suivre lors de l'utilisation du client Google bibliothèques pour Spanner.

Configurer le nombre de sessions et de canaux gRPC dans les pools

Les bibliothèques clientes ont un nombre par défaut de sessions dans le pool de sessions. un nombre par défaut de canaux gRPC dans le pool de canaux. Les deux valeurs par défaut conviennent dans la plupart des cas. Vous trouverez ci-dessous le nombre minimal et maximal de sessions par défaut. le nombre par défaut de canaux gRPC pour chaque langage de programmation.

C++

MinSessions: 100
MaxSessions: 400
NumChannels: 4

C#

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Go

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Java

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Node.js

Le client Node.js n'accepte pas plusieurs canaux gRPC. Il est donc est recommandé de créer plusieurs clients au lieu d'augmenter la taille au-delà de 100 sessions pour un seul client.

MinSessions: 25
MaxSessions: 100

PHP

Le client PHP n'accepte pas un nombre configurable de canaux gRPC.

MinSessions: 1
MaxSessions: 500

Python

Python accepte quatre types de pools de sessions différents que vous pouvez utiliser pour gérer des sessions.

Ruby

Le client Ruby n'est pas compatible avec plusieurs canaux gRPC. Il est donc est recommandé de créer plusieurs clients au lieu d'augmenter la taille au-delà de 100 sessions pour un seul client.

MinSessions: 10
MaxSessions: 100

Le nombre de sessions utilisées par votre application est égal au nombre de les transactions simultanées exécutées par votre application. Vous devez modifier le paramètres du pool de sessions par défaut uniquement si vous prévoyez qu'une seule instance d'application d'exécuter plus de transactions simultanées que le pool de sessions par défaut ne peut en gérer.

Pour les applications à simultanéité élevée, nous vous recommandons d'appliquer les conseils suivants:

  1. Définissez MinSessions sur le nombre attendu de transactions simultanées qu'un client unique s’exécutera.
  2. Définissez MaxSessions sur le nombre maximal de transactions simultanées qu'un peut être exécutée par un seul client.
  3. Définissez MinSessions=MaxSessions si la simultanéité attendue ne change pas. pendant la durée de vie de l'application. Cela empêche le pool de session un scaling à la hausse ou à la baisse. Le scaling à la hausse ou à la baisse du pool de sessions consomme également ressources.
  4. Définissez NumChannels sur MaxSessions / 100. Un canal gRPC peut gérer jusqu'à 100 requêtes simultanées. Augmentez cette valeur si vous observez une queue haute (latence p95/p99), car cela pourrait indiquer que gRPC l'encombrement des canaux.

L'augmentation du nombre de sessions actives utilise des ressources supplémentaires sur la service de base de données Spanner et dans la bibliothèque cliente. Augmenter la valeur au-delà des besoins réels de l'application pourraient dégrader les performances de votre système.

Augmenter le pool de sessions plutôt que le nombre de clients

La taille du pool de sessions d'une application détermine le nombre transactions qu'une seule instance d'application peut exécuter. Augmenter la durée de la session au-delà de la simultanéité maximale qu'une seule instance d'application peut identifiant n'est pas recommandé. Si l'application reçoit une série de requêtes au-delà du nombre de sessions dans le pool, les requêtes sont mises en file d'attente en attendant qu'une session soit disponible.

Les ressources utilisées par la bibliothèque cliente sont les suivantes:

  1. Chaque canal gRPC utilise une connexion TCP.
  2. Chaque appel gRPC nécessite un thread. Le nombre maximal de les threads utilisés par la bibliothèque cliente est égal au nombre maximal de de requêtes simultanées exécutées par l'application. Ces fils de discussion s’affichent en haut des threads que l'application utilise pour sa propre logique métier.

Augmenter la taille du pool de session au-delà du nombre maximal de threads qu'une seule instance d'application peut gérer n'est pas recommandé. À la place, augmenter le nombre d'instances d'application.

Gérer la fraction des sessions d'écriture

Pour certaines bibliothèques clientes, Spanner réserve une partie des sessions pour les transactions en lecture/écriture, appelée fraction des sessions d'écriture. Si votre application utilise toutes les sessions de lecture, alors Spanner utilise le modèle même pour les transactions en lecture seule. Les sessions en lecture/écriture nécessitent spanner.databases.beginOrRollbackReadWriteTransaction. Si l'utilisateur se trouve dans spanner.databaseReader, l'appel échoue et Spanner renvoie le message d'erreur suivant:

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

Vous pouvez définir la fraction de sessions d'écriture pour les bibliothèques clientes qui gèrent une fraction des sessions d'écriture.

C++

Les sessions C++ sont toutes similaires. Il n'existe pas de sessions en lecture seule ou en lecture-écriture.

C#

La fraction des sessions d'écriture par défaut pour C# est de 0,2. Vous pouvez modifier à l'aide du champ WriteSessionsFraction de SessionPoolOptions.

Go

Toutes les sessions Go sont identiques. Il n'existe pas de sessions en lecture seule ou en lecture-écriture.

Java

Les sessions Java sont toutes similaires. Il n'existe pas de sessions en lecture seule ou en lecture-écriture.

Node.js

Toutes les sessions Node.js sont identiques. Il n'existe pas de sessions en lecture seule ou en lecture-écriture.

PHP

Les sessions PHP sont toutes similaires. Il n'existe pas de sessions en lecture seule ou en lecture-écriture.

Python

Python accepte quatre types de pools de sessions différents que vous pouvez utiliser pour gérer les sessions de lecture seule et de lecture-écriture.

Ruby

La fraction des sessions d'écriture par défaut pour Ruby est de 0,3. Vous pouvez la modifier à l'aide de la méthode d'initialisation du client.

Bonnes pratiques lors de la création d'une bibliothèque cliente ou de l'utilisation des API REST ou RPC

Vous trouverez ci-dessous les bonnes pratiques à suivre pour implémenter des sessions dans un client. pour Spanner, ou pour utiliser des sessions avec l'API REST ou RPC.

Ces bonnes pratiques ne s'appliquent que si vous développez une bibliothèque cliente ou si vous utilisez des API REST/RPC. Si vous utilisez l'un des clients Google pour Spanner, consultez Bonnes pratiques concernant l'utilisation des bibliothèques clientes Google

Créer et dimensionner le pool de session

Pour déterminer la taille optimale du pool de sessions pour un processus client, définissez le la limite inférieure au nombre de transactions simultanées attendues, et définissez la limite supérieure associé à un numéro de test initial, tel que 100. Si la limite supérieure n'est pas suffisante, augmentez-la. Augmenter le nombre de sessions actives utilise des ressources supplémentaires sur le service de base de données Spanner. Par conséquent, l'échec du nettoyage des sessions inutilisées peut dégrader les performances. Pour les utilisateurs qui se servent de l'API RPC, nous vous recommandons de ne pas avoir plus de 100 sessions par canal gRPC.

Gérer les sessions supprimées

Pour supprimer une session, trois méthodes s'offrent à vous :

  • Un client peut supprimer une session.
  • Le service de base de données Spanner peut supprimer une session lorsqu'elle est inactif pendant plus d'une heure.
  • Le service de base de données Spanner peut supprimer une session si celle-ci est datant de plus de 28 jours.

Les tentatives d'utilisation d'une session supprimée ont pour résultat NOT_FOUND. Si vous rencontrez cette erreur, créez et utilisez une nouvelle session, ajoutez-la au pool, puis et retirer la session supprimée du pool.

Gérer l'activation d'une session inactive

Le service de base de données Spanner se réserve le droit de supprimer une instance session. Si vous souhaitez absolument avoir la possibilité de réactiver une session inactive, par exemple, si vous prévoyez une augmentation importante de l'utilisation de la base de données à court terme, vous pouvez empêcher la suppression de la session. Effectuez une opération peu coûteuse telle que l'exécution de la requête SQL SELECT 1 pour maintenir la session active. Si vous disposez d'un une session inactive qui n'est pas nécessaire pour une utilisation à court terme, laissez Spanner supprimer une session, puis créez-en une la prochaine fois qu'une session est nécessaire.

Un scénario efficace pour garder les sessions actives consiste à gérer les pics de demande réguliers dans la base de données. Si la base de données est utilisée de façon intensive quotidiennement de 9h à 18h, faites en sorte de pouvoir activer certaines sessions inactives pendant ce laps de temps, car elles seront probablement utiles lors des pics d'activité. Après 18h, vous pouvez laisser Spanner supprimer les sessions inactives. Avant 9h chaque jour, créez de nouvelles sessions afin qu'elles soient prêtes en fonction de la demande attendue.

Autre scénario : si votre application utilise Spanner vous devez éviter les frais de connexion le cas échéant. Pour ce faire, gardez un ensemble de sessions actif.

Masquer les détails de la session vis-à-vis de l'utilisateur de la bibliothèque cliente

Si vous créez une bibliothèque cliente, n'exposez pas les sessions au client bibliothèque cliente. Donnez au client la possibilité d'exécuter des appels de base de données sans la complexité liée à la création et à la gestion de sessions. Par exemple, qui masque les détails de la session au consommateur de la bibliothèque cliente, consultez la bibliothèque cliente Spanner pour Java.

Traiter les erreurs pour les transactions d'écriture qui ne sont pas idempotentes

Les transactions d'écriture sans protection de réexécution peuvent appliquer des mutations plusieurs fois. Si une mutation n'est pas idempotente, une mutation appliquée plusieurs fois peut entraîner un échec. Par exemple, une insertion peut échouer et générer une erreur ALREADY_EXISTS, même si la ligne n'existait pas avant la tentative d'écriture. Cette erreur peut se produire si le serveur backend a validé la mutation, mais est incapable de communiquer la réussite de l'opération au client. Dans ce cas, une nouvelle tentative d'exécution de la mutation sera effectuée, ce qui entraînera l'erreur ALREADY_EXISTS.

Voici différentes manières de résoudre ce scénario lorsque vous mettez en œuvre votre propre bibliothèque cliente ou utilisez l'API REST :

  • Structurez votre écriture pour qu'elle soit idempotente.
  • Utilisez les écritures avec protection de réexécution.
  • Mettez en œuvre une méthode qui exécute la logique "upsert" : insérer en cas de nouveauté ou mettre à jour l'existant.
  • Traitez l'erreur pour le compte du client.

Maintenir des connexions stables

Pour des performances optimales, la connexion que vous utilisez pour héberger une session doit rester stable. Lorsque la connexion qui héberge une session change, Spanner peut annuler la transaction active sur la session et provoquer une petite quantité une charge supplémentaire sur votre base de données pendant qu'il met à jour les métadonnées de session. Pas de problème si certaines connexions changent de façon sporadique, mais évitez les situations qui entraîneraient la modification d'un grand nombre de connexions simultanément. Si vous utilisez un proxy entre le client et Spanner, vous devez préserver la stabilité de la connexion pour chaque session.

Surveiller les sessions actives

Vous pouvez utiliser la commande ListSessions pour surveiller les sessions actives dans votre base de données à partir de la ligne de commande, avec l'API REST ou avec l'API RPC. ListSessions affiche les sessions actives pour une base de données donnée. Cette fonction est utile si vous avez besoin de trouver la cause d'une fuite de session. (Une fuite de session est un incident au cours duquel les sessions sont créés, mais ne sont pas renvoyés à un pool de session pour être réutilisés.)

ListSessions vous permet d'afficher des métadonnées sur vos sessions actives, y compris la date de création et la date de la dernière utilisation d'une session. L'analyse de ces données vous orientera dans la bonne direction lors du dépannage des sessions. Si la plupart des sessions actives n'ont pas de approximate_last_use_time récent, cela pourrait indiquent que les sessions ne sont pas réutilisées correctement par votre application. Consultez le Documentation de référence de l'API RPC pour plus d'informations sur le champ approximate_last_use_time.

Consultez la documentation de référence de l'API REST, la documentation de référence de l'API RPC ou la commande gcloud de l'outil de ligne de commande pour en savoir plus sur l'utilisation de ListSessions.

Nettoyage automatique des fuites de session

Lorsque vous utilisez toutes les sessions de votre pool de sessions, chaque nouvelle transaction attend qu'une session soit renvoyée dans le pool. Lors de la création des sessions mais qui ne sont pas renvoyées au pool de sessions pour être réutilisées, cela s'appelle une fuite de session. En cas de fuite de session, les transactions en attente d'une session ouverte sont bloquées. indéfiniment et de bloquer l'application. Les fuites de sessions sont souvent dues à des transactions problématiques qui s'exécutent sur une très longue période ne sont pas validées.

Vous pouvez configurer votre pool de sessions pour résoudre automatiquement ces les transactions inactives. Lorsque vous autorisez votre bibliothèque cliente à prendre automatiquement résoudre la transition inactive, il identifie les transactions problématiques qui peut entraîner une fuite de session, les supprimer du pool de sessions les remplace par une nouvelle session.

La journalisation peut également vous aider à identifier ces transactions problématiques. Si la journalisation est activée, les journaux d'avertissement sont partagés par défaut lorsque plus de 95% de votre pool de sessions est utilisé. Si elle est supérieure à 95%, vous devez augmenter le nombre maximal de sessions autorisé dans votre pool ou une fuite de session. Les journaux d'avertissement contiennent une pile des traces de transactions plus longues que prévu et qui peuvent permet d'identifier la cause d'une utilisation élevée du pool de sessions. Les journaux d'avertissement sont transmis en fonction de la configuration de votre exportateur de journaux.

Activer la bibliothèque cliente pour résoudre automatiquement les transactions inactives

Vous pouvez activer la bibliothèque cliente pour envoyer des journaux d'avertissement résoudre les transactions inactives, ou autoriser la bibliothèque cliente à ne recevoir qu'un avertissement journaux.

Java

Pour recevoir les journaux d'avertissement et supprimer les transactions inactives, utilisez setWarnAndCloseIfInactiveTransactions.

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

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

Pour recevoir uniquement les journaux d'avertissement, utilisez setWarnIfInactiveTransactions

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

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

Go

Pour recevoir les journaux d'avertissement et supprimer les transactions inactives, utilisez SessionPoolConfig avec 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()

Pour ne recevoir que les journaux d'avertissement, utilisez 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)

Sessions multiplexées

Les sessions multiplex vous permettent de créer un nombre illimité de requêtes simultanées en même temps. Les sessions multiplex présentent les avantages suivants:

  • Réduction des besoins en ressources de backend Par exemple, ils évitent les sessions les activités de maintenance associées à la maintenance de la propriété de session la récupération de mémoire.
  • Session de longue durée qui ne nécessite pas de requêtes keep-alive en cas d'inactivité.
  • Les bibliothèques clientes standards peuvent utiliser une session multiplexée pour chaque client. La le nombre de sessions standards utilisées est inférieur pour les clients utilisant le multiplexé pour certaines opérations, par rapport aux clients qui n'utilisent que des sessions.
  • Il n'est pas nécessaire d'avoir une affinité avec un seul canal gRPC. Les clients peuvent envoyer des requêtes sur plusieurs canaux pour la même session multiplexée.

Les sessions multiplex sont compatibles avec les fonctionnalités suivantes:

  • Bibliothèque cliente Java
  • Les outils de l'écosystème Spanner qui dépendent de la bibliothèque cliente Java, tels que PGAdapter, JDBC et Hibernate
  • API Spanner pour les transactions en lecture seule

Vous allez utiliser les métriques OpenTelemetry pour voir comment le trafic est réparti. entre le pool de sessions existant et la session multiplexée. OpenTelemetry propose Un filtre de métrique, is_multiplexed, qui affiche les sessions multiplexées lorsqu'il est défini sur true

Les sessions multiplex sont activées par défaut pour les adaptateurs JDBC et PG. Pour Java bibliothèques clientes, il est désactivé par défaut. Utilisez les Bibliothèque cliente Java pour activer sessions multiplexées. Pour activer une session multiplexée à l'aide de Java, consultez Activez les sessions multiplexées.

Activer les sessions multiplexées

Pour activer les sessions multiplexées à l'aide du client Java, définissez De GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS à true.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE

Afficher le trafic des sessions standards et multiplexées

Le filtre is_multiplexed d'OpenTelemetry affiche le trafic pour sessions multiplexées. Définissez ce filtre sur true to view multiplexed sessions andfalse` pour afficher les sessions standards.

  1. Configurez OpenTelemetry pour Spanner à l'aide des procédures du Spanner OpenTelemetry Avant de commencer .
  2. Accédez à l'Explorateur de métriques.

    Accéder à l'explorateur de métriques

  3. Dans le menu déroulant Métrique, filtrez sur generic.

  4. Cliquez sur Generic Task (Tâche générique) et accédez à Spanner > Spanner/num_acquired_sessions

  5. Dans le champ Filtrer, sélectionnez l'une des options suivantes:

    a. is_multiplexed = false pour afficher les sessions standards. b. is_multiplexed = true pour afficher les sessions multiplexées.

    L'image suivante montre l'option Filtrer avec des sessions multiplexées. sélectionnée.

Pour en savoir plus sur l'utilisation d'OpenTelemetry avec Spanner, consultez la page utiliser OpenTelemetry pour démocratiser l'observabilité dans Spanner ; Examiner la latence dans un composant Spanner à l'aide d'OpenTelemetry

Tableau de bord OpenTelemetry affichant le filtre est multiplexé.