Che tu stia sviluppando un'app nascente o gestendo già un servizio con un traffico elevato, puoi trarre vantaggio dalle informazioni e dai consigli di questa guida su come scalare senza problemi con FCM. Questi concetti e queste pratiche possono aiutarti a evitare impatti negativi quando devi inviare grandi volumi di messaggi.
Termini e concetti chiave
Richiesta di messaggio: una richiesta di messaggio FCM; utilizzato in modo intercambiabile con "richiesta", "messaggio" o "query".
Richieste al secondo (RPS): una metrica per descrivere la velocità delle richieste in entrata a FCM; utilizzata in modo intercambiabile con Query al secondo (QPS).
Token di quota, bucket di token e ricariche: quando invii messaggi all'API FCM HTTP v1, ogni richiesta consuma un token di quota assegnato in un determinato periodo di tempo. Questa finestra, chiamata "Token Bucket", si riempie completamente alla fine della finestra temporale. Ad esempio, l'API HTTP v1 assegna 600.000 token di quota per ogni Token Bucket di 1 minuto, che si riempie completamente alla fine di ogni finestra di 1 minuto.
Limitazione lato server: quando il volume di traffico supera la capacità del servizio FCM, le richieste che superano la capacità di pubblicazione vengono rifiutate per limitare la velocità del flusso di ingresso. Potrebbero essere restituite risposte di errore 429
con intestazioni retry-after
per indicare che devi attendere un determinato periodo di tempo prima di riprovare a inviare la richiesta.
Limitazione lato client: quando i client rilevano errori di richiesta, latenza elevata o errori 429
, devono limitare volontariamente la velocità del flusso di uscita per evitare di esacerbare la congestione.
Backoff esponenziale: Quando riprovi a risolvere gli errori, aggiungi ritardi di tempo che aumentano in modo esponenziale. Ad esempio: 1 s, 2 s, 4 s, 8 s, 16 s, 32 s e così via.
Jittering: evita di riprovare le richieste a intervalli esatti. Con il jittering, vari i ritardi dei tentativi tramite una procedura casuale per distribuirli in modo uniforme nel tempo (ad esempio: 0,9 s, 2,3 s, 4,1 s, 8,5 s, 17,9 s, 34,7 s).
Amplificazione dei tentativi: quando i tentativi di richiesta non riusciti vengono ripetuti senza backoff/jittering esponenziale, spesso si accumulano e aumentano il carico di traffico in corso, potenzialmente "amplificando" ed esacerbando i problemi di congestione del traffico.
Il problema: picchi di traffico
FCM elabora milioni di richieste al secondo (RPS). Il principale fattore che contribuisce a congestione sistemica, problemi di latenza e interruzioni del servizio sono i picchi di traffico.
Che cos'è il traffico con picchi?
Esistono diversi tipi di picchi di traffico.
Picchi orari: FCM riceve più del doppio del traffico durante i primi 30 secondi e 2 minuti di ogni ora. Picchi simili, anche se minori, si osservano anche ai segni di mezz'ora e di un quarto d'ora (ad esempio: 00:15, 00:30, 00:45).
Riprova dell'amplificazione: il nuovo tentativo di richieste non riuscite o con timeout senza Exponential backoff può accumularsi in onde di traffico ripetute in aggiunta ai picchi di traffico esistenti.
Cambiamenti improvvisi del pattern di traffico: indirizzare il nuovo traffico a FCM o spostare il traffico su FCM in tutte le regioni senza fattori di smoothing come l'aumento graduale può causare picchi.
Utilizzo dei token di quota in anticipo: esaurire tutti i token di quota all'inizio delle finestre di quota anziché distribuire le richieste in modo uniforme nelle finestre di quota creerà oscillazioni on-off difficili e costose da bilanciare.
Eventi speciali: picchi di traffico durante le festività (Capodanno) o eventi sportivi (Mondiali FIFA).
Rimediare ai picchi di traffico "appiattendo la curva"
Questa sezione descrive le strategie per appianare i picchi di traffico, ove possibile, ovvero le strategie per "appiattire la curva".
Utilizza FCM solo per casi d'uso appropriati
Esistono alcuni casi d'uso in cui l'utilizzo di FCM per inviare una notifica non è necessario o appropriato.
Ad esempio, per le notifiche degli eventi di calendario, puoi pianificare un'attività locale nella tua app per visualizzare una notifica negli orari appropriati anziché inviarla dal server dell'app. Limita i messaggi FCM alle sincronizzazioni del calendario.
Evitare i picchi
Un anti-pattern di scalabilità consiste nell'inviare notifiche FCM il più rapidamente possibile, anziché applicare la limitazione lato server. Considera quanto segue:
- Tutti i tuoi clienti devono ricevere la stessa notifica entro un periodo di 1 minuto? Ad esempio, una finestra di consegna di 5 minuti soddisferebbe comunque le esigenze della tua attività?
- I tuoi clienti possono essere segmentati in base alla priorità per attenuare i picchi?
- Le notifiche possono essere programmate in anticipo?
Ove possibile: evita strategie che comportano l'esaurimento immediato della quota di invio FCM, per poi ripetere il pattern non appena il token bucket si riempie. Questo pattern di accesso crea problemi di bilanciamento del carico per FCM e i relativi sistemi dipendenti. Aumenta il traffico il più gradualmente possibile. Come minimo, aumenta da 0 al numero massimo di RPS in un intervallo di tempo di 60 secondi. Preferisci finestre più lunghe per un RPS più elevato.
Evitare il traffico "all'ora"
Ove possibile: evita di inviare messaggi entro un intervallo di 2 minuti da ciascuno dei segni di :00, :15, :30 e :45 minuti.
Implementare la limitazione lato server
Implementa la limitazione lato server per monitorare e gestire il flusso di traffico verso FCM.
Gestione dei nuovi tentativi
Sebbene FCM si impegni a garantire un'elevata disponibilità, a volte alcune richieste andranno in timeout o non andranno a buon fine. Sebbene i motivi varino, le seguenti best practice ottimizzano il comportamento di ripetizione per recapitare i messaggi il prima possibile, riducendo al minimo l'impatto sulla congestione del traffico.
Timeout
Imposta un timeout di almeno 10 secondi per le richieste di invio prima di riprovare. La maggior parte delle chiamate di procedura remota interne di FCM utilizza un timeout di 10 secondi.
Errori
- Per gli errori 400, 401, 403, 404: interrompi e non riprovare.
- Per gli errori 429: riprova dopo aver atteso la durata impostata nell'intestazione retry-after. Se non è impostata alcuna intestazione Retry-After, il valore predefinito è 60 secondi.
- Per gli errori 500: riprova con il backoff esponenziale.
Backoff esponenziale
Per evitare l'amplificazione dei tentativi, implementa il backoff esponenziale con jittering per i tentativi di richiesta. L'SDK Firebase Admin, ad esempio, implementa il backoff esponenziale.
Ecco alcune impostazioni consigliate:
- Intervallo minimo: non riprovare immediatamente una richiesta non riuscita con FCM. Attendi almeno 10 secondi prima di riprovare una richiesta non riuscita.
- Intervallo massimo: imposta un intervallo massimo per l'eliminazione delle richieste non più tempestive, anziché riprovare all'infinito.
Se un tentativo di richiesta viene ripetuto continuamente con backoff esponenziale e non va a buon fine 60 minuti dopo, l'errore è stato classificato erroneamente come riprovabile oppure FCM sta riscontrando un'interruzione in cui i tentativi potrebbero peggiorare involontariamente la situazione.
Crea piani di implementazione e rollback e apporta modifiche graduali
Quando apporti modifiche al traffico su larga scala, ad esempio aumentando il traffico verso FCM o spostando il traffico tra regioni o reti, la progettazione di un piano di implementazione/rollback e l'implementazione di modifiche graduali proteggeranno i tuoi utenti, il tuo servizio e FCM.
- Un piano di implementazione allinea le aspettative degli stakeholder. In determinate situazioni (descritte di seguito), potresti voler condividere il tuo piano di implementazione in anticipo con il team FCM per evitare sorprese.
- Un piano di rollback ti consente di tenere conto delle emergenze e preparare meccanismi per ripristinare rapidamente e in sicurezza i guasti imprevisti.
- L'implementazione di modifiche graduali ha due aspetti:
- Aumenti "graduali": i passaggi devono essere 1% -> 5% -> 10% -> 25% -> 50% -> 75% -> 100% o più precisi. "Test di stress" (osserva il comportamento del sistema sotto carico) ogni passaggio per 1 giorno o 1 settimana. In questo modo, puoi individuare potenziali problemi prima del successivo "step-up".
- Aumenti graduali del traffico: quando esegui ogni "passaggio" per aumentare il traffico, distribuiscilo uniformemente nell'arco di almeno un'ora. In questo modo, l'infrastruttura di bilanciamento del carico di FCM può scalare in modo appropriato il nuovo traffico, riducendo al minimo il potenziale di hotspot e congestione.
Ecco uno scenario ipotetico per la migrazione di 500.000 RPS a livello globale dall'API HTTP legacy di FCM all'API HTTP v1 di FCM:
Settimana | Step | Strategia di applicazione graduale |
---|---|---|
0 | Applicazione graduale dell'1% | Aumenta gradualmente da 0 a 5000 RPS a FCM HTTP v1 nell'arco di un'ora. |
1 | Applicazione graduale del 5% | Aumenta gradualmente da 5000 a 25.000 RPS in 2 ore. |
2 | Applicazione graduale del 10% | Aumenta gradualmente da 25.000 a 50.000 RPS in 2 ore |
3 | Applicazione graduale del 25% | Aumento graduale da 50.000 a 125.000 RPS in 3 ore |
4 | Applicazione graduale del 50% | Aumento graduale da 125.000 a 250.000 RPS in 6 ore |
5 | Applicazione graduale del 75% | Aumento graduale da 250.000 a 375.000 RPS in 6 ore |
6 | Applicazione graduale al 100% | Aumento graduale da 375.000 a 500.000 RPS in 6 ore |
Piano di rollback ipotetico:
- Se la latenza del 95° percentile aumenta a più di 500 ms o se il tasso di errori supera l'1% per più di un'ora in qualsiasi passaggio, utilizza la configurazione dinamica per eseguire il rollback al passaggio precedente immediatamente.
- Continua a eseguire rollback ai passaggi precedenti finché la latenza e il tasso di errori non tornano ai livelli nominali.
Quando contattare FCM
Contatta FCM tramite l'assistenza Firebase se si verifica una delle seguenti condizioni:
- Le quote predefinite non soddisfano più il tuo caso d'uso
- Stai modificando i pattern di invio in un periodo di tre mesi a una scala di 100.000 RPS a livello globale o 30.000 RPS a livello continentale.