Analysez les requêtes en temps réel à grande échelle

Lisez ce document pour obtenir des conseils sur le scaling de votre application sans serveur au-delà de milliers d'opérations par seconde ou de centaines de milliers d'utilisateurs simultanés. Ce document aborde des sujets avancés pour vous aider à comprendre le système en profondeur. Si vous débutez avec Firestore, consultez plutôt le guide de démarrage rapide.

Firestore et les SDK mobiles/Web Firebase fournissent un modèle performant pour le développement d'applications sans serveur dans lesquelles le code côté client accède directement à la base de données. Les SDK permettent aux clients d'écouter les mises à jour des données en temps réel. Vous pouvez utiliser les mises à jour en temps réel pour créer des applications responsives qui ne nécessitent pas d'infrastructure de serveur. Bien qu'il soit très facile de mettre en œuvre quelque chose, il est utile de comprendre les contraintes des systèmes qui composent Firestore afin que votre application sans serveur évolue et fonctionne correctement lorsque le trafic augmente.

Consultez les sections suivantes pour obtenir des conseils sur le scaling de votre application.

Choisissez un emplacement de base de données proche de vos utilisateurs

Le schéma suivant illustre l'architecture d'une application en temps réel:

Exemple d'architecture d'application en temps réel

Lorsqu'une application exécutée sur l'appareil d'un utilisateur (mobile ou Web) établit une connexion à Firestore, la connexion est acheminée vers un serveur frontend Firestore dans la région où se trouve votre base de données. Par exemple, si votre base de données se trouve dans us-east1, la connexion à une interface Firestore se trouve également dans us-east1. Ces connexions ont une longue durée de vie et restent ouvertes jusqu'à ce qu'elles soient explicitement fermées par l'application. L'interface lit les données des systèmes de stockage Firestore sous-jacents.

La distance entre l'emplacement physique d'un utilisateur et l'emplacement de la base de données Firestore affecte la latence rencontrée par l'utilisateur. Par exemple, un utilisateur en Inde dont l'application communique avec une base de données située dans une région Google Cloud d'Amérique du Nord peut trouver l'expérience plus lente et l'application moins rapide que si la base de données était plutôt plus proche, comme en Inde ou dans une autre partie d'Asie.

Concevoir des solutions fiables

Les sujets suivants améliorent ou affectent la fiabilité de votre application:

Activer le mode hors connexion

Les SDK Firebase assurent la persistance des données hors connexion. Si l'application installée sur l'appareil de l'utilisateur ne peut pas se connecter à Firestore, elle reste utilisable en utilisant des données mises en cache localement. Cela garantit l'accès aux données même lorsque les utilisateurs rencontrent des problèmes de connexion Internet ou qu'ils perdent complètement l'accès pendant plusieurs heures, voire plusieurs jours. Pour en savoir plus sur le mode hors connexion, consultez Activer les données hors connexion.

Comprendre les nouvelles tentatives automatiques

Les SDK Firebase se chargent de relancer les opérations et de rétablir les connexions rompues. Cela permet de contourner les erreurs temporaires causées par le redémarrage de serveurs ou des problèmes de réseau entre le client et la base de données.

Faites votre choix entre des emplacements régionaux et multirégionaux

Le choix entre les emplacements régionaux et multirégionaux implique plusieurs compromis. La principale différence réside dans la façon dont les données sont répliquées. Cela garantit les garanties de disponibilité de votre application. Une instance multirégionale offre une plus grande fiabilité de diffusion et augmente la durabilité de vos données, mais en contrepartie, le coût est élevé.

Comprendre le système de requêtes en temps réel

Les requêtes en temps réel, également appelées écouteurs d'instantanés, permettent à l'application d'écouter les modifications apportées à la base de données et de recevoir des notifications à faible latence dès que les données changent. Une application peut obtenir le même résultat en interrogeant régulièrement la base de données pour rechercher des mises à jour, mais elle est souvent plus lente, plus coûteuse et nécessite davantage de code. Pour obtenir des exemples de configuration et d'utilisation des requêtes en temps réel, consultez la page Obtenir des mises à jour en temps réel. Les sections suivantes expliquent en détail le fonctionnement des écouteurs d'instantanés et décrivent certaines des bonnes pratiques pour le scaling des requêtes en temps réel tout en préservant les performances.

Imaginez que deux utilisateurs se connectent à Firestore via une application de messagerie créée avec l'un des SDK pour mobile.

Le client A écrit dans la base de données pour ajouter et mettre à jour des documents dans une collection appelée chatroom:

collection chatroom:
    document message1:
      from: 'Sparky'
      message: 'Welcome to Firestore!'

    document message2:
      from: 'Santa'
      message: 'Presents are coming'

Le client B écoute les mises à jour de la même collection à l'aide d'un écouteur d'instantanés. Le client B reçoit immédiatement une notification dès qu'un utilisateur crée un message. Le schéma suivant illustre l'architecture derrière un écouteur d'instantanés:

Architecture d'une connexion d'écouteur d'instantanés

La séquence d'événements suivante se produit lorsque le client B connecte un écouteur d'instantanés à la base de données:

  1. Le client B ouvre une connexion à Firestore et enregistre un écouteur en appelant onSnapshot(collection("chatroom")) via le SDK Firebase. Cet écouteur peut rester actif pendant des heures.
  2. L'interface Firestore interroge le système de stockage sous-jacent pour amorcer l'ensemble de données. Elle charge l'ensemble des résultats de documents correspondants. C'est ce que nous appelons une requête de sondage. Le système évalue ensuite les règles de sécurité Firebase de la base de données pour vérifier que l'utilisateur peut accéder à ces données. Si l'utilisateur est autorisé, la base de données lui renvoie les données.
  3. La requête du client B passe ensuite en mode d'écoute. L'écouteur s'enregistre auprès d'un gestionnaire d'abonnements et attend les mises à jour des données.
  4. Le client A envoie désormais une opération d'écriture pour modifier un document.
  5. La base de données valide la modification du document dans son système de stockage.
  6. De manière transactionnelle, le système valide la même mise à jour dans un journal de modifications interne. Le journal de modifications établit un ordre strict des modifications au fur et à mesure qu'elles se produisent.
  7. Le journal de modifications transfère à son tour les données mises à jour vers un pool de gestionnaires d'abonnements.
  8. Un outil de mise en correspondance des requêtes inversées s'exécute pour voir si le document mis à jour correspond à un écouteur d'instantanés actuellement enregistré. Dans cet exemple, le document correspond à l'écouteur d'instantanés du client B. Comme son nom l'indique, l'outil de mise en correspondance des requêtes inversée peut être considéré comme une requête de base de données normale, mais effectuée à l'envers. Au lieu de rechercher dans les documents ceux qui correspondent à une requête, il effectue une recherche efficace dans les requêtes pour trouver celles qui correspondent à un document entrant. Lorsqu'une correspondance est trouvée, le système transmet le document en question aux écouteurs d'instantanés. Le système évalue ensuite les règles de sécurité Firebase de la base de données pour s'assurer que seuls les utilisateurs autorisés reçoivent les données.
  9. Le système transmet la mise à jour du document au SDK sur l'appareil du client B, et le rappel onSnapshot se déclenche. Si la persistance locale est activée, le SDK applique également la mise à jour au cache local.

Un élément clé de l'évolutivité de Firestore dépend de la distribution ramifiée du journal de modifications vers les gestionnaires d'abonnement et les serveurs frontend. La distribution ramifiée permet à une seule modification de données de se propager efficacement afin de répondre à des millions de requêtes en temps réel et d'utilisateurs connectés. En exécutant de nombreuses instances répliquées de tous ces composants dans plusieurs zones (ou dans plusieurs régions dans le cas d'un déploiement multirégional), Firestore bénéficie d'une haute disponibilité et d'une évolutivité.

Notez que toutes les opérations de lecture émises à partir des SDK pour mobile et Web suivent le modèle ci-dessus. Ils effectuent une requête d'interrogation suivie d'un mode d'écoute pour maintenir les garanties de cohérence. Cela s'applique également aux écouteurs en temps réel, aux appels de récupération d'un document et aux requêtes uniques. Vous pouvez considérer la récupération de document unique et les requêtes uniques comme des écouteurs d'instantanés de courte durée qui présentent des contraintes similaires en termes de performances.

Appliquer les bonnes pratiques de scaling des requêtes en temps réel

Appliquez les bonnes pratiques suivantes pour concevoir des requêtes évolutives en temps réel.

Identifier un trafic élevé en écriture dans le système

Cette section vous aide à comprendre comment le système répond à un nombre croissant de requêtes d'écriture.

Les journaux de modifications Firestore qui génèrent les requêtes en temps réel évoluent automatiquement horizontalement à mesure que le trafic en écriture augmente. Lorsque le taux d'écriture d'une base de données dépasse ce qu'un seul serveur peut gérer, le journal des modifications est réparti sur plusieurs serveurs, et le traitement des requêtes commence à consommer les données de plusieurs gestionnaires d'abonnement au lieu d'un seul. Du point de vue du client et du SDK, tout est transparent, et aucune action n'est requise de la part de l'application en cas de fractionnement. Le schéma suivant illustre le scaling des requêtes en temps réel:

Architecture de la distribution ramifiée du journal des modifications

Le scaling automatique vous permet d'augmenter votre trafic en écriture sans limite. Toutefois, à mesure que le trafic augmente, le système peut mettre un certain temps à répondre. Suivez les recommandations de la règle des 5-5-5 pour éviter de créer une zone cliquable en écriture. Key Visualizer est un outil utile pour analyser les zones cliquables en écriture.

De nombreuses applications ont une croissance organique prévisible, que Firestore peut s'adapter sans précautions. En revanche, les charges de travail par lot, telles que l'importation d'un ensemble de données volumineux, peuvent accélérer le nombre d'écritures trop rapidement. Lorsque vous concevez votre application, gardez à l'esprit la provenance de votre trafic en écriture.

Comprendre comment interagissent les lectures et les écritures

Vous pouvez considérer le système de requêtes en temps réel comme un pipeline connectant les opérations d'écriture aux lecteurs. Chaque fois qu'un document est créé, mis à jour ou supprimé, la modification se propage du système de stockage aux écouteurs actuellement enregistrés. La structure du journal des modifications de Firestore garantit une cohérence forte, ce qui signifie que votre application ne reçoit jamais de notifications de mises à jour dans le désordre par rapport au moment où la base de données a validé les modifications des données. Cela simplifie le développement d'applications en supprimant les cas limites liés à la cohérence des données.

Ce pipeline connecté signifie qu'une opération d'écriture provoquant des points d'accès ou des conflits de verrous peut affecter négativement les opérations de lecture. Lorsque des opérations d'écriture échouent ou sont soumises à une limitation, une lecture peut se bloquer dans l'attente de données cohérentes du journal de modifications. Si cela se produit dans votre application, vous constaterez peut-être à la fois des opérations d'écriture lentes et des temps de réponse lents pour les requêtes. Il est essentiel d'éviter les hotspots pour éviter ce problème.

Limiter la taille des documents et des opérations d'écriture

Lorsque vous créez des applications avec des écouteurs d'instantanés, vous souhaitez généralement que les utilisateurs soient informés rapidement des modifications de données. Pour ce faire, essayez de limiter les choses. Le système peut transmettre très rapidement au système de petits documents comportant des dizaines de champs. Le traitement des documents volumineux comportant des centaines de champs et de données volumineuses prend plus de temps.

De même, privilégiez les opérations de commit et d'écriture courtes et rapides pour maintenir une latence faible. Les lots volumineux peuvent vous offrir un débit plus élevé du point de vue du rédacteur, mais ils peuvent en réalité augmenter le délai de notification des écouteurs d'instantanés. Cela est souvent contre-intuitif par rapport à l'utilisation d'autres systèmes de base de données dans lesquels vous pouvez utiliser le traitement par lot pour améliorer les performances.

Utiliser des écouteurs efficaces

À mesure que les taux d'écriture de votre base de données augmentent, Firestore répartit le traitement des données sur plusieurs serveurs. L'algorithme de segmentation de Firestore tente de colocaliser les données d'une même collection ou d'un même groupe de collections sur le même serveur de journaux de modifications. Le système tente de maximiser le débit d'écriture possible tout en maintenant le nombre de serveurs impliqués dans le traitement d'une requête aussi faible que possible.

Cependant, certains modèles peuvent toujours entraîner un comportement non optimal des écouteurs d'instantanés. Par exemple, si votre application stocke la plupart de ses données dans une seule grande collection, l'écouteur devra peut-être se connecter à plusieurs serveurs pour recevoir toutes les données dont il a besoin. Cela reste vrai même si vous appliquez un filtre de requête. La connexion à de nombreux serveurs augmente le risque de réponses plus lentes.

Pour éviter ces réponses plus lentes, concevez votre schéma et votre application de sorte que le système puisse diffuser des écouteurs sans accéder à de nombreux serveurs différents. Il est peut-être préférable de diviser vos données en collections plus petites avec des vitesses d'écriture plus faibles.

Cela revient à penser aux requêtes de performances dans une base de données relationnelle nécessitant des analyses complètes de table. Dans une base de données relationnelle, une requête nécessitant une analyse complète de la table équivaut à un écouteur d'instantanés qui surveille une collection générant un grand nombre de pertes d'utilisateurs. Elle peut être plus lente qu'une requête que la base de données peut traiter à l'aide d'un index plus spécifique. Une requête avec un index plus spécifique s'apparente à un écouteur d'instantanés qui surveille un seul document ou une collection dont les modifications sont moins fréquentes. Vous devez tester le chargement de votre application pour mieux comprendre le comportement et les besoins de votre cas d'utilisation.

Accélérez l'interrogation des requêtes

Un autre élément clé des requêtes responsives en temps réel consiste à s'assurer que la requête d'interrogation pour amorcer les données est rapide et efficace. La première fois qu'un nouvel écouteur d'instantanés se connecte, il doit charger l'intégralité de l'ensemble de résultats et l'envoyer à l'appareil de l'utilisateur. Les requêtes lentes rendent votre application moins réactive. Cela inclut, par exemple, les requêtes qui tentent de lire de nombreux documents ou celles qui n'utilisent pas les index appropriés.

Dans certaines circonstances, un écouteur peut également revenir d'un état d'écoute à un état d'interrogation. Cela se produit automatiquement et est transparent pour les SDK et votre application. Les conditions suivantes peuvent déclencher un état d'interrogation:

  • Le système rééquilibre un journal de modifications en raison des changements de charge.
  • Les points d'accès provoquent des échecs ou des retards d'écriture dans la base de données.
  • Les redémarrages temporaires du serveur affectent temporairement les écouteurs.

Si vos requêtes d'interrogation sont suffisamment rapides, un état d'interrogation devient transparent pour les utilisateurs de votre application.

Privilégier les auditeurs de longue durée

Ouvrir et maintenir les écouteurs actifs aussi longtemps que possible est souvent le moyen le plus rentable de créer une application qui utilise Firestore. Lorsque vous utilisez Firestore, les documents renvoyés à votre application vous sont facturés, et non le maintien d'une connexion ouverte. Un écouteur d'instantanés de longue durée ne lit que les données dont il a besoin pour diffuser la requête tout au long de sa durée de vie. Cela inclut une opération d'interrogation initiale suivie de notifications lorsque les données changent. Les requêtes uniques, en revanche, lisent à nouveau des données qui n'ont peut-être pas changé depuis la dernière exécution de la requête par l'application.

Si votre application doit consommer un taux élevé de données, les écouteurs d'instantanés peuvent ne pas être appropriés. Par exemple, si votre cas d'utilisation transfère de nombreux documents par seconde via une connexion pendant une période prolongée, il peut être préférable d'opter pour des requêtes uniques exécutées à une fréquence plus faible.

Étape suivante