Che tu stia sviluppando un'app appena nata o gestendo un servizio ad alto traffico, puoi trarre vantaggio dagli approfondimenti 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; utilizzata in modo intercambiabile con "richiesta", "messaggio" o "query".
Richieste al secondo (RPS): una metrica per descrivere la frequenza 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 intervallo di tempo. Questa finestra, chiamata "token bucket", si riempie al termine 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 gestione vengono rifiutate per limitare la frequenza del flusso in entrata. 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 osservano errori di richiesta, latenza elevata o errori 429, devono limitare volontariamente la frequenza del flusso in uscita per evitare di aggravare la congestione.
Backoff esponenziale: quando riprovi a risolvere gli errori, aggiungi ritardi 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 nuovi tentativi tramite un processo 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 nuovi tentativi: quando i nuovi tentativi di richieste non riuscite vengono eseguiti senza backoff esponenziale/jittering, spesso si accumulano e si aggiungono al carico di traffico in corso, "amplificando" e aggravando potenzialmente i problemi di congestione del traffico.
Il problema: picchi di traffico
FCM elabora milioni di richieste al secondo (RPS). Il fattore che contribuisce maggiormente alla congestione sistemica, ai problemi di latenza e alle interruzioni sono i picchi di traffico.

Che cos'è il traffico con picchi?
Esistono diversi tipi di picchi di traffico.
Picchi all'ora: FCM riceve più del doppio del traffico durante i primi 30 secondi-2 minuti di ogni ora. Picchi simili, anche se minori, si osservano anche ai segni di mezz'ora e un quarto d'ora (esempi: 00:15, 00:30, 00:45)

Amplificazione dei nuovi tentativi: i nuovi tentativi di richieste non riuscite o scadute senza backoff esponenziale possono accumularsi in ondate ripetute di traffico oltre ai picchi di traffico esistenti.

Cambiamenti improvvisi dei pattern di traffico: l'indirizzamento di nuovo traffico a FCM o lo spostamento del traffico a FCM tra regioni senza fattori di attenuazione come l'aumento graduale può causare picchi.

Utilizzo dei token di quota in anticipo: l'esaurimento di tutti i token di quota all'inizio delle finestre di quota, anziché la distribuzione uniforme delle richieste tra le finestre di quota, creerà oscillazioni on-off difficili e costose da bilanciare.

Eventi speciali: picchi di traffico durante le festività (Capodanno) o eventi sportivi (Coppa del Mondo FIFA).

Rimedia ai picchi di traffico "appiattendo la curva"
Questa sezione descrive le strategie per attenuare i picchi di traffico, ove possibile, ovvero le strategie per "appiattire la curva".
Utilizza FCM solo per i 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 nel 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.
Evita i picchi
Un anti-pattern di scalabilità consiste nell'inviare notifiche FCM il più rapidamente possibile, invece di applicare la limitazione lato server. Considera quanto segue:
- Tutti i tuoi clienti devono ricevere la stessa notifica entro un intervallo di 1 minuto? Ad esempio, una finestra di consegna di 5 minuti soddisferebbe comunque le tue esigenze aziendali?
- 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 di 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 nel modo più graduale possibile. Come minimo, passa da 0 al numero massimo di RPS in un intervallo di tempo di 60 secondi. Preferisci finestre più lunghe per un RPS più elevato.
Evita il traffico "all'ora esatta"
Se possibile: evita di inviare messaggi entro un intervallo di 2 minuti da ciascuno dei seguenti minuti: :00, :15, :30 e :45.
Implementa 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'alta affidabilità, a volte alcune richieste scadono o non vanno a buon fine. Sebbene i motivi varino, le seguenti best practice ottimizzano il comportamento dei nuovi tentativi 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 un'intestazione retry-after, il valore predefinito è 60 secondi.
- Per gli errori 500: riprova con il backoff esponenziale.
Backoff esponenziale
Per evitare l'amplificazione dei nuovi tentativi, implementa il backoff esponenziale con jitter per i nuovi tentativi di richiesta. L'SDK Firebase Admin, ad esempio, implementa il backoff esponenziale.
Ecco alcune altre impostazioni consigliate:
- Intervallo minimo: non riprovare immediatamente a inviare 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 che non sono più tempestive, anziché riprovare all'infinito.
Se una richiesta viene ripetuta continuamente con backoff esponenziale e continua a non riuscire dopo 60 minuti, significa che è stata classificata erroneamente come errore ripetibile o che FCM sta riscontrando un'interruzione del servizio in cui i nuovi tentativi potrebbero inavvertitamente peggiorare 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 rilascio allinea le aspettative degli stakeholder. In determinate situazioni (descritte di seguito), potresti voler condividere il tuo piano di rilascio in anticipo con il team di FCM per evitare sorprese.
- Un piano di rollback ti consente di tenere conto delle emergenze e di preparare meccanismi per riprenderti in modo rapido e sicuro da errori imprevisti.
- L'apporto di modifiche graduali ha due aspetti:
- Aumenti graduali: i passaggi devono essere 1% -> 5% -> 10% -> 25% -> 50% -> 75% -> 100% o più precisi. "Immergiti" (osserva il comportamento del sistema sotto carico) in ogni passaggio per un periodo compreso tra 1 giorno e 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 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 rischio di hotspot e congestione.
Ecco uno scenario ipotetico per la migrazione di 500.000 RPS a livello globale dall'API HTTP FCM precedente all'API FCM HTTP v1:
| Settimana | Step | Strategia di applicazione graduale |
|---|---|---|
| 0 | Applicazione graduale dell'1% | Aumenta gradualmente da 0 a 5000 RPS verso FCM HTTP v1 nel corso di un'ora. |
| 1 | Applicazione graduale del 5% | Aumenta gradualmente da 5000 a 25.000 RPS nell'arco di 2 ore. |
| 2 | Applicazione graduale del 10% | Aumenta gradualmente da 25.000 a 50.000 RPS nell'arco di 2 ore |
| 3 | Applicazione graduale del 25% | Aumento da 50.000 a 125.000 RPS in 3 ore |
| 4 | Applicazione graduale al 50% | Aumento da 125.000 a 250.000 RPS in 6 ore |
| 5 | 75% di applicazione graduale | Aumento da 250.000 a 375.000 RPS in 6 ore |
| 6 | Applicazione graduale al 100% | Aumento da 375.000 a 500.000 RPS in 6 ore |
Piano di rollback ipotetico:
- Se la latenza del 95° percentile aumenta fino a superare i 500 ms o se il rapporto di errore supera l'1% per più di un'ora in qualsiasi passaggio, utilizza la configurazione dinamica per eseguire immediatamente il rollback al passaggio precedente.
- Continua i rollback ai passaggi precedenti finché la latenza e il tasso di errore 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 tuoi pattern di invio entro un periodo di 3 mesi su una scala di 100.000 RPS a livello globale o 30.000 RPS a livello continentale.