Comprendere le query in tempo reale su larga scala

Leggi questo documento per indicazioni su come scalare la tua app serverless oltre le migliaia di operazioni al secondo o centinaia di migliaia di utenti in contemporanea. Questo documento include argomenti avanzati per aiutare conoscere in dettaglio il sistema. Se stai iniziando Cloud Firestore, consulta invece la guida rapida.

Cloud Firestore e gli SDK Firebase web/mobile forniscono un modello efficace per lo sviluppo di app serverless in cui il codice lato client accede direttamente per configurare un database. Gli SDK consentono ai clienti di ascoltare gli aggiornamenti dei dati in tempo reale. Tu Puoi utilizzare gli aggiornamenti in tempo reale per creare app adattabili che non richiedono server dell'infrastruttura. Sebbene sia molto facile configurare qualcosa, aiuta per comprendere i vincoli nei sistemi che compongono Cloud Firestore in modo che la tua app serverless scala e funzioni bene quando il traffico aumenta.

Consulta le sezioni seguenti per consigli sulla scalabilità della tua app.

Scegli una località del database vicina agli utenti

Il seguente diagramma illustra l'architettura di un'app in tempo reale:

Esempio di architettura delle app in tempo reale

Quando un'app in esecuzione sul dispositivo di un utente (mobile o web) stabilisce una connessione a Cloud Firestore, la connessione viene instradata a un Cloud Firestore server frontend nella stessa region in cui si trova il database. Ad esempio, se il database si trova in us-east1, la connessione va anche a un frontend Cloud Firestore in us-east1. Queste connessioni sono di lunga durata e rimangono aperti finché l'app non viene chiusa esplicitamente. La il frontend legge i dati dai sistemi di archiviazione Cloud Firestore sottostanti.

La distanza tra la posizione fisica di un utente e Cloud Firestore la posizione del database influisce sulla latenza sperimentata dall'utente. Ad esempio, un utente in India la cui app comunica con un database in una regione Google Cloud del Nord America potrebbe trovare l'esperienza più lenta e l'app meno scattante rispetto a se il database si trovasse più vicino, ad esempio in India o in un'altra parte dell'Asia.

Progetta per l'affidabilità

I seguenti argomenti migliorano o influiscono sull'affidabilità della tua app:

Abilita modalità offline

Gli SDK Firebase forniscono la persistenza dei dati offline. Se l'app sul dispositivo dell'utente non riesce a connettersi a Cloud Firestore, l'app rimane utilizzabile lavorando con dati memorizzati nella cache locale. Questo assicura che i dati l'accesso anche quando la connessione a internet è instabile o perdono completamente l'accesso per diverse ore o giorni. Per ulteriori dettagli su modalità offline, consulta l'articolo Attivare i dati offline.

Informazioni sui nuovi tentativi automatici

Gli SDK Firebase si occupano di riprovare le operazioni e di ristabilire le connessioni interrotte. In questo modo è possibile aggirare gli errori temporanei causati riavviando i server o causando problemi di rete tra il client per configurare un database.

Scegli tra località a singola regione e a più regioni

Ci sono diversi compromessi nella scelta tra regionale e località multiregionali. La differenza principale è il modo in cui i dati vengono replicati. Questo determina la disponibilità garantita della tua app. Un'istanza multiregionale offre una maggiore affidabilità di servizio e aumenta la durabilità dei dati, il compromesso è il costo.

Comprendere il sistema di query in tempo reale

Le query in tempo reale, chiamate anche listener di snapshot, consentono all'app di ascoltare modifiche nel database e ricevi notifiche a bassa latenza non appena i dati modifiche. Un'app può ottenere lo stesso risultato eseguendo periodicamente il polling del database per verificare la presenza di aggiornamenti, ma spesso è più lenta, più costosa e richiede più codice. Per esempi di come impostare e utilizzare query in tempo reale, vedi Ricevi aggiornamenti in tempo reale. Le seguenti sezioni entrare nel dettaglio del funzionamento dei listener di snapshot e descrivere alcune delle best practice per scalare le query in tempo reale senza rinunciare alle prestazioni.

Immagina due utenti che si connettono a Cloud Firestore tramite un'app di messaggistica creata con uno degli SDK mobile.

Il client A scrive nel database per aggiungere e aggiornare i documenti di una raccolta chiamato chatroom:

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

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

Il client B rimane in ascolto degli aggiornamenti nella stessa raccolta utilizzando un listener snapshot. Il cliente B riceve una notifica immediata ogni volta che qualcuno crea un nuovo messaggio. Il seguente diagramma mostra l'architettura alla base di un listener di snapshot:

Architettura di una connessione di listener degli snapshot

Quando il client B connette uno snapshot, si verifica la seguente sequenza di eventi listener per il database:

  1. Il client B apre una connessione a Cloud Firestore e registra una ascoltatore effettuando una chiamata a onSnapshot(collection("chatroom")) tramite l'SDK Firebase. Questo listener può rimanere attivo per ore.
  2. Il frontend Cloud Firestore esegue query sul sistema di archiviazione sottostante per avviare il set di dati. Carica l'intero set di risultati documenti. Questo tipo di query viene chiamato query di polling. Il sistema valuta i valori Regole di sicurezza di Firebase per verificare che l'utente possa accedere a questi dati. Se l'utente è autorizzato, restituisce i dati all'utente.
  3. La query del client B passa quindi in modalità di ascolto. L'ascoltatore si registra con un gestore degli abbonamenti e attende gli aggiornamenti dei dati.
  4. Il client A ora invia un'operazione di scrittura per modificare un documento.
  5. Il database esegue il commit della modifica del documento completamente gestito di Google Cloud.
  6. A livello transazionale, il sistema esegue il commit dello stesso aggiornamento in una changelog. Il log delle modifiche stabilisce un ordine rigoroso delle modifiche, quando accadono.
  7. Il log delle modifiche a sua volta trasferisce i dati aggiornati a un pool di iscrizioni e i gestori di rete.
  8. Viene eseguito un matcher inversa delle query per verificare se il documento aggiornato corrisponde listener di snapshot attualmente registrati. In questo esempio, il documento corrisponde al listener snapshot del Client B. Come suggerisce il nome, puoi pensare il matcher inverso come una normale query di database, ma al contrario. Anziché cercare tra i documenti per trovare quelli che corrispondono a una query, cerca in modo efficiente per trovare quelle che corrispondono a un documento in arrivo. Una volta trovata una corrispondenza, il sistema inoltra il documento in questione agli ascoltatori degli snapshot. Quindi il sistema valuta le regole di sicurezza di Firebase del database. per garantire che solo gli utenti autorizzati ricevano i dati.
  9. Il sistema inoltra l'aggiornamento del documento all'SDK sul dispositivo del client B. viene attivato il callback onSnapshot. Se la persistenza locale è abilitata, l'SDK e applica l'aggiornamento anche alla cache locale.

Una parte fondamentale della scalabilità di Cloud Firestore dipende dal fan-out da il log delle modifiche ai gestori delle sottoscrizioni e ai server frontend. La il fan-out consente a una singola modifica di dati di propagarsi in modo efficiente query in tempo reale e utenti connessi. Eseguendo molte repliche di tutti questi componenti su più zone (o più regioni nel caso di un deployment multi-regione), Cloud Firestore raggiunge un'alta disponibilità e scalabilità.

Vale la pena notare che tutte le operazioni di lettura eseguite da SDK web e per dispositivi mobili segui il modello riportato sopra. Esegue una query di polling seguita dalla modalità di ascolto per mantenere le garanzie di coerenza. Questo vale anche per chi ascolta in tempo reale, per recuperare un documento e query one-shot. Puoi pensare a singole i recuperi di documenti e le query one-shot come listener di snapshot di breve durata che presentano vincoli simili in termini di rendimento.

Applica le best practice per scalare le query in tempo reale

Applica le seguenti best practice per progettare query scalabili in tempo reale.

Comprendi il traffico di scrittura elevato nel sistema

Questa sezione ti aiuta a capire come il sistema risponde a un numero crescente di richieste di scrittura.

I log delle modifiche di Cloud Firestore che generano le query in tempo reale scalare automaticamente orizzontalmente all'aumento del traffico in scrittura. Come velocità di scrittura per un database va oltre la capacità di gestione di un singolo server, il log delle modifiche è suddiviso tra più server e l'elaborazione delle query inizia e consumano i dati di più gestori di abbonamenti invece che uno. Da dal punto di vista del client e dell'SDK, è tutto trasparente e non è richiesta alcuna azione dall'app in caso di suddivisione. Il seguente diagramma mostra come la scalabilità delle query in tempo reale:

Architettura del fan-out del log delle modifiche

La scalabilità automatica consente di aumentare il traffico di scrittura senza limiti, ma man mano che il traffico aumenta, il sistema potrebbe impiegare un po' di tempo per rispondere. Segui i consigli della regola 5-5-5 per evitare di creare un hotspot di scrittura. Key Visualizer è una uno strumento utile per analizzare gli hotspot di scrittura.

Molte app hanno una crescita organica prevedibile, che Cloud Firestore può gestire senza precauzioni. per carichi di lavoro in batch, del set di dati, tuttavia, può aumentare le scritture troppo rapidamente. Mentre progetti la tua app, della provenienza del traffico di scrittura.

Informazioni sulle interazioni tra scritture e letture

Puoi pensare al sistema di query in tempo reale come a una pipeline che collega la scrittura operazioni con i lettori. Ogni volta che un documento viene creato, aggiornato o eliminato la modifica si propaga dal sistema di archiviazione a quello attualmente registrato e ascoltatori. La struttura del log delle modifiche di Cloud Firestore garantisce un'elevata con coerenza, vale a dire che la tua app non riceve mai notifiche aggiornamenti non in ordine rispetto a quando il database ha eseguito il commit dei dati modifiche. Ciò semplifica lo sviluppo dell'app rimuovendo i casi limite legati alla coerenza dei dati.

Questa pipeline connessa indica che un'operazione di scrittura che provoca hotspot o la contesa del blocco possono influire negativamente sulle operazioni di lettura. Quando le operazioni di scrittura non riescono o vengono sottoposte a throttling, una lettura potrebbe bloccarsi in attesa di dati coerenti dal log delle modifiche. Se questo si verifica della tua app, potresti vedere operazioni di scrittura lente e una risposta lenta correlata volte per le query. Evitare gli hotspot è fondamentale per evitare problema.

Mantieni i documenti e le operazioni di scrittura di piccole dimensioni

Quando crei app con listener di snapshot, in genere vuoi che gli utenti trovino rapidamente i cambiamenti nei dati. Per raggiungere questo obiettivo, cerca di limitare le cose. Il sistema può inviare piccoli documenti con decine di campi molto rapidamente. Documenti di grandi dimensioni con centinaia di campi e dati di grandi dimensioni richiedono più tempo da elaborare.

Allo stesso modo, favorisci operazioni di commit e scrittura brevi e veloci per mantenere bassa la latenza. I batch di grandi dimensioni potrebbero offrire una velocità effettiva più elevata dal punto di vista dell'autore ma potrebbe effettivamente aumentare il tempo di notifica per i listener di snapshot. Questo approccio è spesso controintuitivo rispetto all'utilizzo di altri sistemi di database in cui potresti usare la gestione in batch per migliorare le prestazioni.

Utilizzare listener efficienti

Con l'aumento della velocità di scrittura del database, Cloud Firestore suddivide l'elaborazione dei dati tra più server. L'algoritmo di sharding di Cloud Firestore tenta di collocare i dati della stessa raccolta o dello stesso gruppo di raccolte sullo stesso server di log delle modifiche. La di sistema cerca di massimizzare la possibile velocità effettiva di scrittura, conservando al contempo il numero il più basso possibile di server coinvolti nell'elaborazione di una query.

Tuttavia, alcuni pattern potrebbero comunque portare a un comportamento non ottimale per lo snapshot e ascoltatori. Ad esempio, se l'app archivia la maggior parte dei dati in un ambiente raccolta, il listener potrebbe dover connettersi a più server per ricevere di cui ha bisogno. Questo vale anche se applichi un filtro di query. Connessione in corso... a molti server aumenta il rischio di risposte più lente.

Per evitare queste risposte più lente, progetta lo schema e l'app in modo che il sistema può gestire i listener senza passare per molti server diversi. Potrebbe funzionare è preferibile suddividere i dati in raccolte più piccole con velocità di scrittura inferiori.

È un po' come pensare alle query sulle prestazioni in un database relazionale che richiede scansioni complete delle tabelle. In un contesto relazionale, un database, una query che richiede una scansione completa della tabella è l'equivalente di listener di snapshot che monitora una raccolta con un tasso di abbandono elevato. Potrebbe funzionare lentamente rispetto a una query che il database può gestire usando un indice più specifico. Una query con un indice più specifico è come un listener di snapshot che controlla un documento singolo o una raccolta che cambia con minore frequenza. Dovresti caricare testare l'app per comprenderne al meglio il comportamento e le esigenze.

Fai in modo che le query di polling siano rapide

Un'altra parte fondamentale delle query in tempo reale responsive consiste nell'assicurarsi che la query di polling per l'avvio dei dati sia rapida ed efficiente. La prima volta che si connette un nuovo listener di snapshot, il listener deve caricare il l'intero set di risultati e invialo al dispositivo dell'utente. Le query lente rendono la tua app è meno reattiva. Sono incluse, ad esempio, query a leggere molti documenti o query che non usano gli indici appropriati.

In alcune circostanze, un ascoltatore potrebbe anche passare da uno stato di ascolto a uno stato di polling. Ciò avviene automaticamente ed è trasparente per SDK e la tua app. Le seguenti condizioni potrebbero attivare uno stato di polling:

  • Il sistema riequilibra un log delle modifiche a causa di variazioni del carico.
  • Gli hotspot causano scritture non riuscite o in ritardo nel database.
  • I riavvii temporanei del server influiscono temporaneamente sui listener.

Se le query di polling sono abbastanza veloci, lo stato di sondaggio diventa trasparente agli utenti della tua app.

Prediligi gli ascoltatori di lunga durata

Avviare e mantenere vivi gli ascoltatori il più a lungo possibile è spesso la un modo conveniente per creare un'app che usa Cloud Firestore. Quando utilizzi Cloud Firestore, ti vengono addebitati i documenti restituiti alla tua app e non la manutenzione di una connessione aperta. Un listener di snapshot a lunga durata legge e solo i dati necessari per eseguire la query per tutta la durata del ciclo di vita. Questo include un'operazione di polling iniziale seguita dalle notifiche quando i dati cambia effettivamente. Le query one-shot, invece, rileggono i dati che potrebbero non sono stati modificati dall'ultima volta che l'app ha eseguito la query.

Nei casi in cui la tua app deve utilizzare una quantità elevata di dati, i listener di snapshot potrebbe non essere appropriato. Ad esempio, se il tuo caso d'uso esegue il push di molti documenti al secondo tramite una connessione per un periodo di tempo prolungato, è preferibile optare per query one-shot che vengono eseguite con una frequenza inferiore.

Passaggi successivi