Pub/Sub è un servizio di messaggistica asincrona progettato per essere altamente affidabile e scalabile. Il servizio si basa su un componente dell'infrastruttura di Google di base su cui si basano molti prodotti Google da oltre un decennio. I prodotti Google, tra cui Ads, Ricerca e Gmail, utilizzano questa infrastruttura per inviare oltre 500 milioni di messaggi al secondo, per un totale di oltre 1 TB/s di dati. Questo articolo descrive le funzionalità di progettazione salienti che consentono a Pub/Sub di fornire questo tipo di scalabilità in modo affidabile.
Valutare il rendimento di un servizio di messaggistica
Le prestazioni di un servizio di messaggistica come Pub/Sub possono essere valutate in tre aspetti: scalabilità, disponibilità e latenza. Questi tre fattori sono spesso in contrasto tra loro e richiedono compromessi su uno per migliorare gli altri due.
I termini "scalabilità", "disponibilità" e "latenza" possono fare riferimento a proprietà diverse di un sistema, pertanto le sezioni seguenti descrivono come vengono definiti in Pub/Sub.
Scalabilità
Un servizio scalabile deve essere in grado di gestire gli aumenti di carico senza un degrado significativo della latenza o della disponibilità. "Carico" può fare riferimento a varie dimensioni di utilizzo in Pub/Sub:
Numero di argomenti
Numero di publisher
Numero di abbonamenti
Numero di iscritti
Numero di messaggi
Dimensioni dei messaggi
Frequenza di messaggi (velocità effettiva) pubblicati o consumati
Dimensioni del backlog per un determinato abbonamento
Disponibilità
In un sistema distribuito, i tipi e la gravità dei problemi possono variare notevolmente. La disponibilità di un sistema viene misurata in base alla sua capacità di gestire diversi tipi di problemi, con un passaggio in modo corretto a un altro sistema in modo invisibile agli utenti finali. Gli errori possono verificarsi nell'hardware (ad es. unità disco non funzionanti o problemi di connettività di rete), nel software e a causa del carico. Un errore dovuto al carico può verificarsi quando un aumento improvviso del traffico nel servizio (o in altri componenti software in esecuzione sullo stesso hardware o nelle dipendenze software) comporta una scarsità di risorse. La disponibilità può peggiorare anche a causa di errori umani, ad esempio se si commettono errori durante la creazione o il deployment di software o configurazioni.
Latenza
La latenza è una misurazione basata sul tempo delle prestazioni di un sistema. In genere, un servizio vuole ridurre al minimo la latenza, se possibile. Per Pub/Sub, le due metriche di latenza più importanti sono:
Il tempo necessario per confermare un messaggio pubblicato.
Il tempo necessario per consegnare un messaggio pubblicato a un sottoscrittore.
Architettura di base di Pub/Sub
Questa sezione illustra il design di Pub/Sub per mostrare come il servizio raggiunge la scalabilità e la bassa latenza mantenendo la disponibilità. Il sistema è progettato per essere scalabile orizzontalmente, in modo che un aumento del numero di argomenti, iscrizioni o messaggi possa essere gestito aumentando il numero di istanze dei server in esecuzione.
I server Pub/Sub vengono eseguiti in tutte le regioni Google Cloud in tutto il mondo. In questo modo, il servizio offre un accesso rapido e globale ai dati, dando al contempo agli utenti il controllo sulla posizione in cui vengono archiviati i messaggi. Cloud Pub/Sub offre accesso ai dati a livello mondiale in quanto i client publisher e subscriber non sono a conoscenza della posizione dei server a cui si connettono o di come questi servizi inoltrano i dati.
I meccanismi di bilanciamento del carico di Pub/Sub indirizzano il traffico dei publisher al datacenter Google Cloud più vicino in cui è consentito l'archiviazione dei dati, come definito nella sezione Limitazione della posizione della risorsa della Console IAM e amministrazione. Ciò significa che i publisher in più regioni possono pubblicare messaggi in un singolo argomento con bassa latenza. Ogni singolo messaggio viene archiviato in una singola regione. Tuttavia, un argomento può avere messaggi archiviati in molte regioni. Quando un client sottoscrittore richiede i messaggi pubblicati in questo argomento, si connette al server più vicino che aggrega i dati di tutti i messaggi pubblicati nell'argomento per la consegna al client.
Pub/Sub è suddiviso in due parti principali: il piano dati, che gestisce il trasferimento dei messaggi tra publisher e subscriber, e il piano di controllo, che gestisce l'assegnazione di publisher e subscriber ai server nel piano dati. I server nel piano dati sono chiamati forwarder, mentre i server nel piano di controllo sono chiamati router. Quando i publisher e gli abbonati sono collegati ai forwarder assegnati, non hanno bisogno di informazioni dai router (purché questi forwarder rimangano accessibili). Pertanto, è possibile eseguire l'upgrade del piano di controllo di Pub/Sub senza influire sui client già connessi e che inviano o ricevono messaggi.
Control plane
Il piano di controllo di Pub/Sub distribuisce i client ai forwarder in modo da garantire scalabilità, disponibilità e bassa latenza per tutti i client. Qualsiasi inoltratore è in grado di servire i client per qualsiasi argomento o abbonamento. Quando un client si connette a Pub/Sub, il router decide i data center a cui deve connettersi in base alla distanza di rete più breve, una misura della latenza sulla connessione tra due punti. All'interno di un determinato data center, il router tenta di distribuire il carico complessivo nell'insieme di inoltratori disponibili. Il router deve bilanciare due obiettivi diversi durante l'esecuzione di questa assegnazione: (a) uniformità del carico (ovvero, idealmente ogni forwarder è caricato allo stesso modo); e (b) stabilità delle assegnazioni (ovvero, idealmente una variazione del carico o dell'insieme di forwarder disponibili modifica il numero più piccolo di assegnazioni esistenti). Il router utilizza una variante dell'hashing coerente sviluppata da Google Research per ottenere un equilibrio regolabile tra coerenza e uniformità. Il router fornisce al client un elenco ordinato di inoltratori a cui può connettersi. Questo elenco ordinato può cambiare in base alla disponibilità del corriere e alla forma del carico del cliente.
Un client prende questo elenco di inoltratori e si connette a uno o più di questi. Il client preferisce connettersi ai forwarder più consigliati dal router, ma prende in considerazione anche eventuali errori che si sono verificati, ad esempio potrebbe decidere di provare i forwarder in un altro data center se diversi tentativi con quelli più vicini non sono riusciti. Per separare i client Pub/Sub da questi dettagli di implementazione, esiste un proxy di servizio tra i client e i forwarder che esegue questa ottimizzazione della connessione per conto dei client.
Piano dati: il ciclo di vita di un messaggio
Il piano dati riceve i messaggi dai publisher e li invia ai client. Forse il modo migliore per comprendere il piano dati di Pub/Sub è esaminare il ciclo di vita di un messaggio, dal momento in cui viene ricevuto dal servizio a quello in cui non è più presente nel servizio. Vediamo i passaggi di elaborazione di un messaggio. Ai fini di questa sezione, assumiamo che all'argomento su cui viene pubblicato il messaggio sia associata almeno una sottoscrizione. In genere, un messaggio segue questi passaggi:
Un publisher invia un messaggio.
Il messaggio viene scritto nello spazio di archiviazione.
Pub/Sub invia al publisher una conferma di ricezione del messaggio e ne garantisce la consegna a tutte le sottoscrizioni collegate.
Contemporaneamente alla scrittura del messaggio nello spazio di archiviazione, Pub/Sub lo consegna agli iscritti.
Gli abbonati inviano a Pub/Sub un messaggio di conferma dell'elaborazione del messaggio.
Una volta che almeno un sottoscrittore per ogni sottoscrizione ha confermato il messaggio, Pub/Sub lo elimina dall'archiviazione.
Innanzitutto, un publisher invia un messaggio su un argomento a Pub/Sub. Viene criptato dal livello proxy e inviato a un forwarder di pubblicazione, un forwarder a cui è connesso il publisher. Per garantire la consegna, il messaggio viene scritto immediatamente nello spazio di archiviazione. Il forwarder scrive inizialmente il messaggio in N cluster (dove N è un numero dispari) e lo considera persistente quando è stato scritto in almeno ⌈N/2⌉ cluster. Una volta che un messaggio è stato mantenuto, l'inoltrare della pubblicazione ne conferma la ricezione al publisher, a quel punto Pub/Sub garantisce che il messaggio verrà recapitato a tutti gli abbonamenti collegati.
All'interno di ogni cluster, il messaggio viene scritto su M dischi indipendenti (dove M è un numero dispari), il che richiede che i dati siano su ⌈M/2⌉ dischi prima che vengano considerati permanenti in quel cluster. In totale, qualsiasi messaggio pubblicato verrà scritto su almeno ⌈M/2⌉ dischi indipendenti in ⌈N/2⌉ cluster prima di essere considerato permanente e alla fine verrà replicato su N*M dischi.
Il forwarder di pubblicazione contiene un elenco di tutte le sottoscrizioni associate a un argomento. È responsabile della persistenza sia dei messaggi pubblicati sia dei metadati che descrivono quali messaggi sono stati confermati da ogni abbonamento. L'insieme di messaggi ricevuti e archiviati da un inoltro di pubblicazione per un determinato argomento, insieme a questo monitoraggio dei messaggi confermati, è chiamato "origine messaggio di pubblicazione". A seconda dei requisiti di throughput per l'argomento, un singolo publisher può inviare i propri messaggi a più inoltratori di pubblicazione e archiviarli in più origini messaggio di pubblicazione. Publisher diversi per lo stesso argomento possono anche inviare messaggi a diversi inoltratori di pubblicazione. Ogni messaggio viene inviato a un solo inoltro di pubblicazione. Pub/Sub ottimizza dinamicamente il numero di inoltratori di pubblicazione che ricevono i messaggi per un determinato argomento man mano che il throughput cambia.
I sottoscrittori ricevono i messaggi collegandosi a inoltratori sottoscrittori, tramite i quali i messaggi vengono inoltrati ai sottoscrittori dai publisher. "Connessione" nel caso di un sottoscrittore pull significa l'emissione di una richiesta pull. "Connessione" nel caso di un sottoscrittore push significa che l'endpoint push è registrato in Pub/Sub. Una volta creata una sottoscrizione, è garantito che tutti i messaggi pubblicati dopo questo punto verranno recapitati a quella sottoscrizione, ovvero ciò che chiamiamo garanzia del punto di sincronizzazione.
Ogni mittente di inoltro sottoscrittore deve richiedere i messaggi ai mittenti di inoltro di pubblicazione che hanno origini messaggio di pubblicazione per l'argomento. Come i publisher, gli abbonati possono connettersi a più di un mittente che si è iscritto per ricevere messaggi. In questo modo, non tutti i forwarder che si abbonano devono essere a conoscenza o ricevere messaggi da ogni origine di messaggio di pubblicazione per un argomento, una proprietà importante per la scalabilità orizzontale di Pub/Sub. In base al throughput dei messaggi inviati ai sottoscrittori, Pub/Sub regola dinamicamente il numero di inoltratori di iscrizioni tramite i quali i sottoscrittori ricevono i messaggi per un determinato argomento man mano che il throughput cambia.
Un forwarder sottoscrittore invia richieste a uno o più forwarder di pubblicazione che hanno origini messaggio di pubblicazione per un argomento per richiedere i messaggi di cui ha bisogno. Il forwarder di pubblicazione invia i messaggi non confermati al forwarder di sottoscrizione, che li inoltra a un abbonato.
Una volta elaborato un messaggio, l'abbonato invia un messaggio di conferma al mittente dell'inoltro. L'inoltrare di sottoscrizione inoltra questo riconoscimento all'inoltrare di pubblicazione, che lo memorizza nell'origine del messaggio di pubblicazione. Una volta che tutte le sottoscrizioni di un argomento hanno confermato un messaggio, questo viene eliminato in modo asincrono dall'origine di pubblicazione del messaggio e dallo spazio di archiviazione.
Messaggi diversi per un singolo argomento e una singola sottoscrizione possono passare attraverso molti publisher, sottoscrittori, inoltratori di pubblicazione e inoltratori di sottoscrizione. I publisher possono pubblicare contemporaneamente in più inoltratori e i sottoscrittori possono connettersi a più inoltratori sottoscrittori per ricevere i messaggi. Pertanto, il flusso di messaggi attraverso le connessioni tra publisher, sottoscrittori e inoltratori può essere complesso. Il seguente diagramma mostra come i messaggi potrebbero essere inviati per un singolo argomento e abbonamento, dove i diversi colori indicano i diversi percorsi che i messaggi possono seguire dai publisher agli abbonati:
Mantenere Pub/Sub in funzione
Garantire che un sistema distribuito come Pub/Sub possa rimanere in funzione e servire efficacemente tutti i clienti richiede una grande visibilità e controllo del sistema. La manutenzione del servizio è responsabilità dei nostri Site Reliability Engineer (SRE). Per Pub/Sub, questi ingegneri si trovano in più località in tutto il mondo per fornire una copertura 24 ore su 24, 7 giorni su 7.
Ambienti
La prima parte della manutenzione di un sistema come Pub/Sub consiste nel poter testare il software prima che venga utilizzato dai clienti. Per rendere possibile questo, esistono tre ambienti Pub/Sub: test, di gestione temporanea e di produzione. I test e le fasi di staging non contengono traffico dei clienti, ma solo i nostri test e il monitoraggio in esecuzione continua che aiutano a trovare eventuali problemi con le release. Questi ambienti ricevono le nuove release del software prima della produzione. La differenza tra test e gestione temporanea è che quest'ultima è una replica esatta di ciò che è presente (o sarà a breve) nell'ambiente di produzione, inclusa la versione del software e i flag della riga di comando. Nel primo caso potrebbero essere attivate funzionalità su cui gli sviluppatori stanno lavorando e che prevedono di rilasciare in futuro.
Implementazione
La procedura di implementazione e test di Pub/Sub è progettata per ridurre al minimo il potenziale impatto. Vediamo i passaggi tipici per l'implementazione di una nuova versione di Pub/Sub:
Assicurati che tutti i test di unità e di integrazione siano superati.
Crea una nuova versione di tutti i server.
Esegui il deployment dei nuovi server negli ambienti di test e di staging.
Esegui i server nell'ambiente di test e di staging per diversi giorni.
Se non ci sono problemi noti, rilascia i server in canary, un sottoinsieme dell'ambiente di produzione con una piccola quantità di traffico dei clienti.
Se non vengono rilevati problemi nella versione canary, implementa gradualmente i server in più ambienti di produzione nell'arco di diversi giorni finché non vengono rilasciati ovunque.
Poiché Pub/Sub è progettato per essere resiliente agli errori, ad esempio tramite la separazione del piano di controllo e del piano dati, l'implementazione di nuove versioni dei server è semplice per i clienti e non dovrebbe influire sul rendimento che vedono.
Monitoraggio
La chiave per mantenere Pub/Sub in funzione è rilevare e attenuare automaticamente i problemi prima che diventino visibili agli utenti finali. Per farlo è necessario un monitoraggio approfondito del sistema. Il team di Site Reliability Engineering (SRE) gestisce un insieme di indicatori del livello di servizio (SLI), metriche ben definite che descrivono il comportamento del sistema. Le metriche possono includere "tempo necessario per il completamento di una richiesta CreateSubscription" o "tasso di errori generati dalle richieste di pubblicazione". Queste metriche vengono misurate in vari modi. Alcuni sono segretamente interni ai nostri forwarder e router. Ad esempio, misurano il tempo necessario per scrivere i messaggi sul disco.
Tutte queste misure contribuiscono a definire gli obiettivi del livello di servizio (SLO) interni, obiettivi specifici per gli SLI. Ad esempio, "la richiesta CreateSubscription non deve richiedere più di cinque secondi per essere completata". Gli SRE ricevono avvisi per le violazioni degli SLO e devono rispondere agli avvisi entro cinque minuti.
Un accordo sul livello del servizio (SLA) elenca gli SLO che definiscono le nostre garanzie di prestazioni per gli utenti finali e le conseguenze in caso di mancato rispetto. Puoi leggere lo SLA di Pub/Sub.
Gestiamo un insieme di client che pubblicano e si abbonano in modo prevedibile. Questi sono chiamati sonde. Esistono sondaggi sia per il piano dati sia per il piano di controllo. Ciascuno dei nostri probers esegue azioni specifiche come farebbe un cliente e misura il tempo necessario per le operazioni. Ad esempio, abbiamo un probe che crea un nuovo abbonamento, pubblica un messaggio e vede il tempo necessario per creare l'abbonamento e ricevere il messaggio. Se i probers rilevano che una delle metriche misurate non è quella prevista, viene inviato un avviso agli SRE.
Le metriche relative ai nostri server e ai nostri probers sono riassunte in diverse dashboard interne, il primo posto in cui gli SRE cercano quando diagnosticano potenziali problemi. Queste pagine consentono di accedere rapidamente a statistiche e grafici dell'intero servizio. Possono anche essere suddivisi per argomento, data center o singola attività.
Le metriche più interessanti per gli utenti del servizio sono esposte tramite Google Cloud Monitoring.
Controlli
Abbiamo a disposizione diversi controlli per ottimizzare il rendimento di Pub/Sub. Alcuni di questi controlli sono progettati per gestire le interruzioni del data center o delle macchine. Possiamo applicare limitazioni di routing su alcuni o tutti gli argomenti, ovvero regole che specificano insiemi di client che possono e/o non possono connettersi a insiemi di inoltratori. Utilizziamo i vincoli di routing per allontanare il traffico dalle singole attività di inoltro o da interi data center che non funzionano come previsto.
Un'altra funzionalità regolabile è il controllo del flusso. Questa funzionalità ci consente di massimizzare il throughput evitando al contempo il sovraccarico del servizio. Il controllo del flusso è una forma di saturazione del traffico che consente di attenuare nel tempo i picchi improvvisi e imprevisti del carico per una maggiore stabilità del servizio. Il controllo del flusso opera a livello di sistema o per argomento o abbonato per limitare il numero di messaggi o di byte trasferiti o in sospeso. In questo caso, "in sospeso" significa che la richiesta è stata inviata al cliente, ma non è ancora stata confermata. Sia i vincoli di controllo del flusso che quelli di routing ci consentono di ottimizzare le prestazioni di Pub/Sub senza che i clienti debbano preoccuparsi di questi dettagli di basso livello.
Riepilogo
I vantaggi in termini di scalabilità, disponibilità e latenza di un servizio come Pub/Sub definiscono la proposta di valore per i clienti che stanno valutando il passaggio ai servizi cloud gestiti. Qualsiasi servizio di messaggistica asincrona deve essere creato da zero tenendo conto di queste funzionalità. Con oltre un decennio di esperienza nell'invio rapido e affidabile di molti messaggi, il team di Pub/Sub ha creato e gestisce un servizio in grado di soddisfare le esigenze dei prodotti più fondamentali di Google. Ora lo stesso servizio è disponibile per tutti i clienti esterni che vogliono inviare i propri messaggi in tutto il mondo senza doversi preoccupare se il loro sistema di messaggistica può gestire il doppio, il triplo o il decuplo del carico attuale.
Glossario
Termine | Descrizione |
---|---|
cluster | Un raggruppamento logico di macchine che in genere condividono lo stesso dominio in errore (ad es. rete locale condivisa e alimentazione condivisa). |
Control plane | Il livello di Pub/Sub che gestisce l'assegnazione di publisher e subscriber ai server nel piano dati. |
piano dati | Il livello di Pub/Sub che gestisce il trasferimento dei messaggi tra publisher e sottoscrittori. |
forwarder | Un server nel piano dati. |
accesso ai dati a livello globale | I client publisher e subscriber di Pub/Sub non sono a conoscenza della posizione dei dati. Tutto il routing e lo spazio di archiviazione vengono eseguiti dal servizio stesso, in conformità con le norme relative alle restrizioni sulla località. |
scalabile orizzontalmente | La capacità di un servizio di gestire senza problemi un maggiore carico aumentando il numero di istanze dei componenti del servizio. |
messaggio | I dati che passano attraverso Pub/Sub. |
distanza di rete | Una misura della latenza sulla connessione tra due punti. |
sonda | Un'attività che agisce come client ed esegue in modo prevedibile una o più azioni sui server Pub/Sub. |
pubblica l'origine messaggio | Un insieme di messaggi ricevuti e archiviati da un forwarder di pubblicazione e l'insieme di ID dei messaggi confermati da tutte le sottoscrizioni collegate. |
servizio Pub/Sub (pubblica/sottoscrivi) | Un servizio di messaggistica in cui i mittenti dei messaggi vengono disaccoppiati dai destinatari dei messaggi |
publisher | Un client di Pub/Sub che crea messaggi e li invia (pubblica) in un argomento specificato. |
router | Un server nel piano di controllo. |
vincoli di routing | Un elenco di regole che indica quali inoltratori devono o non devono essere inviati dai router ai client come possibili endpoint a cui connettersi. |
Accordo sul livello del servizio (SLA) | Un elenco di SLO che definiscono le garanzie di prestazioni di un sistema per i clienti e illustrano le conseguenze in caso di mancato rispetto. |
indicatore del livello del servizio (SLI) | Una metrica ben definita che descrive il comportamento del sistema. |
obiettivo del livello di servizio (SLO) | Un target specifico per un indicatore del livello del servizio. |
sottoscrittore | Un client di Pub/Sub che riceve messaggi su una sottoscrizione specificata. |
abbonamento | Un'entità denominata che rappresenta l'interesse a ricevere tutti i messaggi su un determinato argomento. |
garanzia del punto di sincronizzazione | L'ora in cui viene creata una sottoscrizione, in cui tutti i messaggi pubblicati successivamente verranno recapitati ai sottoscrittori. |
argomento | Un'entità denominata che rappresenta un feed di messaggi. |