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

Lisez ce document pour obtenir des conseils sur la mise à l'échelle 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 comprend des rubriques avancées pour vous aider à comprendre le système en profondeur. Si vous débutez avec Cloud Firestore, consultez plutôt le guide de démarrage rapide .

Cloud Firestore et les SDK mobiles/Web Firebase fournissent un modèle puissant pour développer des applications sans serveur où 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 des mises à jour en temps réel pour créer des applications réactives qui ne nécessitent pas d'infrastructure de serveur. Bien qu'il soit très facile de mettre en place quelque chose et de le faire fonctionner, cela aide à comprendre les contraintes des systèmes qui composent Cloud Firestore afin que votre application sans serveur évolue et fonctionne correctement lorsque le trafic augmente.

Consultez les sections suivantes pour obtenir des conseils sur la mise à l’échelle de votre application.

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

Le diagramme 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 à Cloud Firestore, la connexion est acheminée vers un serveur frontal Cloud Firestore dans la même 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 est également dirigée vers une interface Cloud Firestore également dans us-east1 . Ces connexions durent longtemps et restent ouvertes jusqu'à ce qu'elles soient explicitement fermées par l'application. Le frontend lit les données des systèmes de stockage Cloud Firestore sous-jacents.

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

Conception pour la fiabilité

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

Activer le mode hors ligne

Les SDK Firebase assurent la persistance des données hors ligne. Si l'application sur l'appareil de l'utilisateur ne parvient pas à se connecter à Cloud Firestore, elle reste utilisable en travaillant avec les données mises en cache localement. Cela garantit l’accès aux données même lorsque les utilisateurs rencontrent des connexions Internet inégales ou perdent complètement l’accès pendant plusieurs heures ou jours. Pour plus de détails sur le mode hors ligne, consultez Activer les données hors ligne .

Comprendre les tentatives automatiques

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

Choisissez entre des emplacements régionaux et multirégionaux

Il existe plusieurs compromis lors du choix entre des emplacements régionaux et multirégionaux. La principale différence réside dans la manière dont les données sont répliquées. Cela détermine les garanties de disponibilité de votre application. Une instance multirégionale offre une plus grande fiabilité de service et augmente la durabilité de vos données, mais le compromis est le coût.

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 dans 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 périodiquement la base de données pour les mises à jour, mais elle est souvent plus lente, plus coûteuse et nécessite plus de code. Pour obtenir des exemples de configuration et d'utilisation de requêtes en temps réel, consultez 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 meilleures pratiques pour mettre à l'échelle les requêtes en temps réel tout en conservant les performances.

Imaginez deux utilisateurs qui se connectent à Cloud Firestore via une application de messagerie créée avec l'un des SDK mobiles.

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 Cloud Firestore!'

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

Le client B écoute les mises à jour dans la même collection à l'aide d'un écouteur d'instantanés. Le client B reçoit une notification immédiate chaque fois que quelqu'un crée un nouveau message. Le diagramme suivant montre l'architecture derrière un écouteur d'instantané :

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

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

  1. Le client B ouvre une connexion à Cloud Firestore et enregistre un auditeur en appelant onSnapshot(collection("chatroom")) via le SDK Firebase. Cet auditeur peut rester actif pendant des heures.
  2. L'interface Cloud Firestore interroge le système de stockage sous-jacent pour amorcer l'ensemble de données. Il charge l'ensemble des résultats des documents correspondants. Nous appelons cela une requête d'interrogation . 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 renvoie les données à l'utilisateur.
  3. La requête du client B passe alors en mode écoute . L'écouteur s'enregistre auprès d'un gestionnaire d'abonnement et attend les mises à jour des données.
  4. Le client A envoie maintenant 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. Sur le plan transactionnel, le système valide la même mise à jour dans un journal des modifications interne. Le journal des modifications établit un ordre strict des modifications au fur et à mesure qu'elles se produisent.
  7. Le journal des modifications diffuse à son tour les données mises à jour vers un pool de gestionnaires d'abonnements.
  8. Un outil de correspondance de requête inversée s'exécute pour voir si le document mis à jour correspond aux écouteurs d'instantanés actuellement enregistrés. Dans cet exemple, le document correspond à l'écouteur d'instantané du client B. Comme son nom l'indique, vous pouvez considérer l'outil de correspondance de requêtes inversées comme une requête de base de données normale mais effectuée à l'envers. Au lieu de rechercher dans les documents pour trouver ceux qui correspondent à une requête, il recherche efficacement dans les requêtes pour trouver celles qui correspondent à un document entrant. Après avoir trouvé une correspondance, le système transmet le document en question aux auditeurs d'instantanés. Ensuite, le système évalue les règles de sécurité Firebase de la base de données pour garantir 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 Cloud Firestore dépend de la diffusion du journal des modifications vers les gestionnaires d'abonnement et les serveurs frontaux. La répartition permet à une seule modification de données de se propager efficacement pour répondre à des millions de requêtes en temps réel et d'utilisateurs connectés. En exécutant de nombreuses répliques de tous ces composants sur plusieurs zones (ou plusieurs régions dans le cas d'un déploiement multirégional), Cloud Firestore atteint une haute disponibilité et une évolutivité.

Il convient de noter que toutes les opérations de lecture émises à partir des SDK mobiles et Web suivent le modèle ci-dessus. Ils effectuent une requête d'interrogation suivie d'un mode d'écoute pour maintenir des garanties de cohérence. Cela s'applique également aux écouteurs en temps réel, aux appels pour récupérer un document et aux requêtes ponctuelles . Vous pouvez considérer les récupérations de documents uniques et les requêtes ponctuelles comme des écouteurs d'instantanés de courte durée soumis à des contraintes similaires en matière de performances.

Appliquer les meilleures pratiques pour faire évoluer les requêtes en temps réel

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

Comprendre le trafic d'écriture élevé dans le système

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

Les journaux de modifications Cloud Firestore qui pilotent les requêtes en temps réel évoluent automatiquement horizontalement à mesure que le trafic d'écriture augmente. À mesure que le taux d'écriture d'une base de données augmente au-delà de 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. Du point de vue du client et du SDK, tout cela est transparent et aucune action n'est requise de la part de l'application en cas de scission. Le diagramme suivant montre comment les requêtes en temps réel évoluent :

Architecture de la diffusion du journal des modifications

La mise à l'échelle automatique vous permet d'augmenter votre trafic d'écriture sans limites, mais à mesure que le trafic augmente, le système peut mettre un certain temps à répondre. Suivez les recommandations de la règle 5-5-5 pour éviter de créer un point d'accès en écriture. Key Visualizer est un outil utile pour analyser les points chauds d’écriture.

De nombreuses applications ont une croissance organique prévisible, à laquelle Cloud Firestore peut s'adapter sans précaution. Toutefois, les charges de travail par lots, comme l'importation d'un grand ensemble de données, peuvent accélérer les écritures trop rapidement. Lorsque vous concevez votre application, restez conscient de la provenance de votre trafic d'écriture.

Comprendre comment les écritures et les lectures interagissent

Vous pouvez considérer le système de requêtes en temps réel comme un pipeline reliant 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 Cloud Firestore garantit une forte cohérence, ce qui signifie que votre application ne reçoit jamais de notifications de mises à jour en panne par rapport au moment où la base de données a validé les modifications de données. Cela simplifie le développement d’applications en supprimant les cas extrêmes liés à la cohérence des données.

Ce pipeline connecté signifie qu'une opération d'écriture provoquant des points chauds ou un conflit de verrouillage peut affecter négativement les opérations de lecture. Lorsque les opérations d'écriture échouent ou subissent une limitation, une lecture peut s'arrêter en attendant des données cohérentes du journal des modifications. Si cela se produit dans votre application, vous pourriez constater à la fois des opérations d’écriture lentes et des temps de réponse lents corrélés pour les requêtes. Éviter les points chauds est la clé pour éviter ce problème.

Gardez les documents et les opérations d’écriture petites

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 y parvenir, essayez de garder les choses petites. Le système peut transmettre très rapidement de petits documents contenant des dizaines de champs à travers le système. Les documents plus volumineux comportant des centaines de champs et des données volumineuses prennent plus de temps à traiter.

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 de l'auteur, mais peuvent en fait augmenter le temps de notification pour les écouteurs d'instantanés. Cela est souvent contre-intuitif par rapport à l’utilisation d’autres systèmes de bases de données dans lesquels vous pourriez utiliser le traitement par lots pour améliorer les performances.

Utilisez des auditeurs efficaces

À mesure que les taux d'écriture de votre base de données augmentent, Cloud Firestore répartit le traitement des données sur plusieurs serveurs. L'algorithme de partitionnement de Cloud Firestore tente de colocaliser les données de la même collection ou du même groupe de collections sur le même serveur de journal des modifications. Le système essaie 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 bas que possible.

Cependant, certains modèles peuvent toujours conduire à un comportement sous-optimal pour les écouteurs d'instantanés. Par exemple, si votre application stocke la plupart de ses données dans une seule grande collection, l'auditeur 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 manière à ce que le système puisse servir les auditeurs sans passer par de nombreux serveurs différents. Il peut être préférable de diviser vos données en collections plus petites avec des taux d'écriture plus faibles.

Cela revient à réfléchir aux requêtes de performances dans une base de données relationnelle qui nécessitent des analyses de table complètes. Dans une base de données relationnelle, une requête qui nécessite une analyse complète de la table est l'équivalent d'un écouteur d'instantanés qui surveille une collection à fort taux de désabonnement. Son exécution peut être lente par rapport à 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 est comme un écouteur d'instantané qui surveille un seul document ou une collection qui change moins souvent. Vous devez tester en charge votre application pour mieux comprendre le comportement et les besoins de votre cas d'utilisation.

Continuez à interroger rapidement

Un autre élément clé des requêtes réactives 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é du jeu 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 les requêtes qui n'utilisent pas les index appropriés.

Un auditeur peut également passer d'un état d'écoute à un état d'interrogation dans certaines circonstances. 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 des modifications en raison des changements de charge.
  • Les points chauds entraînent des échecs ou des retards dans les écritures dans la base de données.
  • Les redémarrages transitoires 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.

Favoriser les auditeurs de longue date

Ouvrir et maintenir des auditeurs en vie le plus longtemps possible est souvent le moyen le plus rentable de créer une application utilisant Cloud Firestore. Lorsque vous utilisez Cloud Firestore, vous êtes facturé pour les documents renvoyés à votre application et non pour le maintien d'une connexion ouverte. Un écouteur d'instantané de longue durée lit uniquement les données dont il a besoin pour répondre à 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 réellement. Les requêtes ponctuelles, en revanche, relisent les données qui n'ont peut-être pas changé depuis la dernière exécution de la requête par l'application.

Dans les cas où votre application doit consommer un débit de données élevé, les écouteurs d’instantanés peuvent ne pas être appropriés. Par exemple, si votre cas d'utilisation envoie 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 ponctuelles qui s'exécutent à une fréquence plus faible.

Et après