Panoramica dell'architettura di Pub/Sub

Pub/Sub è un servizio di messaggistica asincrono progettato per essere altamente affidabile e scalabile. Il servizio è basato su un componente fondamentale dell'infrastruttura Google a cui molti prodotti Google fanno affidamento da oltre un decennio. I prodotti Google, tra cui Google 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.

Valutazione delle prestazioni di un servizio di messaggistica

Un servizio di messaggistica come Pub/Sub può essere valutato in base a 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 diverse proprietà di un sistema, quindi le sezioni seguenti descrivono come vengono definiti in Pub/Sub.

Scalabilità

Un servizio scalabile deve essere in grado di gestire l'aumento del carico senza un peggioramento evidente della latenza o della disponibilità. "Caricamento" può fare riferimento a varie dimensioni di utilizzo in Pub/Sub:

  • Numero di argomenti

  • Numero di editori

  • Numero di abbonamenti

  • Numero di iscritti

  • Numero di messaggi

  • Dimensione dei messaggi

  • Percentuale di messaggi (velocità effettiva) pubblicati o consumati

  • Dimensione del backlog di 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 all'efficacia con cui viene gestito con diversi tipi di problemi, fallendo con grazia in un modo impercettibile agli utenti finali. Possono verificarsi errori nell'hardware (ad esempio unità del disco non funzionanti o problemi di connettività di rete), nel software e a causa del carico. Un errore dovuto al carico potrebbe verificarsi quando un improvviso aumento del traffico nel servizio (o in altri componenti software in esecuzione sullo stesso hardware o in dipendenze software) determina una scarsità di risorse. La disponibilità può peggiorare anche a causa di un errore umano, che comporta errori nella creazione o nel deployment di software o configurazioni.

Latenza

La latenza è una misura delle prestazioni di un sistema basata sul tempo. In genere un servizio vuole ridurre al minimo la latenza quando possibile. Per Pub/Sub, le due metriche di latenza più importanti sono:

  1. Il tempo necessario per confermare un messaggio pubblicato.

  2. Il tempo necessario per consegnare un messaggio pubblicato a un sottoscrittore.

Architettura di base di Pub/Sub

Questa sezione spiega la progettazione di Pub/Sub per mostrare in che modo il servizio raggiunge la scalabilità e la bassa latenza, pur mantenendo la disponibilità. Il sistema è progettato per essere scalabile orizzontalmente e consentire di gestire un aumento del numero di argomenti, sottoscrizioni o messaggi aumentando il numero di istanze dei server in esecuzione.

I server Pub/Sub vengono eseguiti in tutte le regioni di Google Cloud in tutto il mondo. Ciò consente al servizio di offrire un accesso rapido e globale ai dati, garantendo al contempo agli utenti il controllo sulla posizione in cui vengono archiviati i messaggi. Cloud Pub/Sub offre un accesso globale ai dati perché i client publisher e sottoscrittori non sono a conoscenza della posizione dei server a cui si connettono o di come questi servizi instradano i dati.

I meccanismi di bilanciamento del carico di Pub/Sub indirizzano il traffico dei publisher al data center Google Cloud più vicino in cui è consentita l'archiviazione dei dati, come definito nella sezione relativa alla limitazione sulla località delle risorse di IAM e console di amministrazione. Ciò significa che gli editori in più regioni possono pubblicare messaggi in un singolo argomento con bassa latenza. Ogni singolo messaggio è archiviato in un'unica regione. Tuttavia, un argomento potrebbe contenere 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 il recapito al client.

Pub/Sub è diviso in due parti principali: il piano dati, che gestisce lo spostamento dei messaggi tra publisher e sottoscrittori, e il piano di controllo, che gestisce l'assegnazione di publisher e sottoscrittori ai server sul piano dati. I server nel piano dati sono chiamati forwarder, mentre quelli nel piano di controllo sono denominati router. Quando editori e sottoscrittori sono collegati ai loro inoltro assegnati, non hanno bisogno di alcuna informazione dai router (purché questi ultimi 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.

Piano di controllo

Il piano di controllo Pub/Sub distribuisce i client ai server di inoltro in modo da garantire scalabilità, disponibilità e bassa latenza per tutti i client. Qualsiasi inoltro è in grado di servire i client per qualsiasi argomento o sottoscrizione. Quando un client si connette a Pub/Sub, il router decide i data center a cui il client 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 cerca di distribuire il carico complessivo tra l'insieme di server di inoltro disponibili. Il router deve bilanciare due obiettivi diversi quando esegue questa assegnazione: (a) uniformità del carico (ovvero, idealmente ogni utente di inoltro è caricato in modo uguale); e (b) stabilità delle assegnazioni (ovvero una variazione del carico o una modifica dell'insieme di spedizionieri disponibili cambia il numero minimo di assegnazioni esistenti). Il router utilizza una variante di hashing coerente sviluppata da Google Research per raggiungere un equilibrio regolabile tra coerenza e uniformità. Il router fornisce al client un elenco ordinato di server di inoltro a cui può prendere in considerazione la connessione. Questo elenco ordinato può cambiare in base alla disponibilità del servizio di inoltro e alla forma del carico proveniente dal client.

Un client prende questo elenco di forwarding e si connette a uno o più di essi. Il client preferisce connettersi ai server di inoltro più consigliati dal router, ma prende in considerazione anche gli eventuali errori che si sono verificati, ad esempio potrebbe decidere di provare gli forwarding in un data center diverso se diversi tentativi verso quelli più vicini non sono andati a buon fine. Per astrarre i client Pub/Sub da questi dettagli di implementazione, esiste un proxy di servizio tra i client e gli utenti che eseguono l'ottimizzazione della connessione per conto dei client.

Piano dati - La 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 la durata di un messaggio, dal momento in cui viene ricevuto dal servizio fino a quando non è più presente nel servizio. Seguiamo i passaggi per l'elaborazione di un messaggio. Ai fini di questa sezione, presupponiamo che all'argomento in cui è pubblicato il messaggio sia associato almeno una sottoscrizione. In generale, un messaggio prevede i seguenti passaggi:

  1. Un publisher invia un messaggio.

  2. Il messaggio è scritto nello spazio di archiviazione.

  3. Pub/Sub invia una conferma al publisher di aver ricevuto il messaggio e ne garantisce la consegna a tutte le sottoscrizioni allegate.

  4. Nel momento in cui si scrive il messaggio nello spazio di archiviazione, Pub/Sub lo consegna ai sottoscrittori.

  5. I sottoscrittori inviano una conferma a Pub/Sub di aver elaborato il messaggio.

  6. Una volta che almeno un sottoscrittore per ogni sottoscrizione ha confermato il messaggio, Pub/Sub elimina il messaggio dall'archiviazione.

Innanzitutto, un publisher invia un messaggio su un argomento a Pub/Sub. Viene criptato dal livello proxy e inviato a un server di inoltro, ovvero a cui è collegato il publisher. Per assicurare il recapito, il messaggio viene immediatamente scritto nello spazio di archiviazione. Inizialmente il server di inoltro scrive il messaggio in N cluster (dove N è un numero dispari) e considera il messaggio persistente quando è stato scritto in almeno ⌈N/2⌉ cluster. Una volta mantenuto un messaggio, l'autore dell'inoltro conferma di averlo ricevuto al publisher, dopodiché Pub/Sub garantisce che il messaggio verrà consegnato a tutte le sottoscrizioni collegate. Un processo in background scrive regolarmente tutti i messaggi che non si trovano in tutti i cluster N nei cluster in cui mancano i messaggi.

All'interno di ogni cluster, il messaggio viene scritto su dischi indipendenti M (dove M è un numero dispari), richiedendo che i dati siano su dischi ⌈M/2⌉ prima di essere considerati persistenti in quel cluster. In totale, ogni messaggio pubblicato verrà scritto su dischi indipendenti ⌈M/2⌉ in cluster ⌈N/2⌉ prima di essere considerato persistente e alla fine verrà replicato su dischi N*M.

La persona che esegue l'inoltro della pubblicazione ha un elenco di tutte le sottoscrizioni collegate a un argomento. È responsabile della conservazione sia dei messaggi pubblicati che dei metadati, descrivendo quali messaggi sono stati confermati da ciascuna sottoscrizione. L'insieme di messaggi ricevuti e archiviati da un utente che esegue l'inoltro per un determinato argomento, insieme a questo monitoraggio dei messaggi confermati, viene chiamato "origine dei messaggi di pubblicazione". A seconda dei requisiti di velocità effettiva per l'argomento, un singolo publisher può inviare i propri messaggi a più utenti che hanno effettuato l'inoltro e archiviarli in più origini dei messaggi di pubblicazione. Editori diversi per lo stesso argomento possono anche inviare messaggi a utenti che hanno inoltrato la pubblicazione diversi. Ogni messaggio viene inviato a un solo utente che ha effettuato l'inoltro. Pub/Sub regola in modo dinamico il numero di server di inoltro che ricevono messaggi per un determinato argomento man mano che la velocità effettiva cambia.

I sottoscrittori ricevono i messaggi collegandosi agli utenti che effettuano l'inoltro di sottoscrizione, gli inoltri attraverso i quali i messaggi passano ai sottoscrittori dai publisher. Nel caso di un sottoscrittore di tipo pull, "connessione" implica l'invio di una richiesta di pull. Nel caso di un sottoscrittore push, "connessione" implica la registrazione dell'endpoint push in Pub/Sub. Una volta creata una sottoscrizione, è garantito che tutti i messaggi pubblicati da quel momento in poi verranno recapitati in quella sottoscrizione, una garanzia del punto di sincronizzazione.

Ogni utente che esegue l'inoltro della sottoscrizione deve richiedere messaggi ai server di inoltro che dispongono di origini di messaggi pubblicate per l'argomento. Come per i publisher, i sottoscrittori possono connettersi a più di un utente che effettua l'inoltro di sottoscrizione per ricevere messaggi. In questo modo, non tutti gli utenti che effettuano l'inoltro di sottoscrizione devono essere a conoscenza o ricevere messaggi da tutte le origini dei messaggi di pubblicazione per un argomento. Si tratta di una proprietà importante per cui Pub/Sub può scalare orizzontalmente. In base alla velocità effettiva dei messaggi consegnati ai sottoscrittori, Pub/Sub regola dinamicamente il numero di forwarding della sottoscrizione tramite i quali i sottoscrittori ricevono i messaggi per un determinato argomento man mano che la velocità effettiva cambia.

Un utente che esegue l'inoltro della sottoscrizione invia richieste a uno o più server di inoltro che hanno origini di messaggi di pubblicazione per un argomento per richiedere i messaggi di cui ha bisogno. Il server di inoltro della pubblicazione invia i messaggi non confermati al forwarding della sottoscrizione, che li inoltra quindi a un sottoscrittore.

Una volta che un sottoscrittore elabora un messaggio, invia una conferma all'inoltro di sottoscrizione. Il mittente della sottoscrizione inoltra questa conferma al forwarding della pubblicazione, che la archivia nell'origine del messaggio di pubblicazione. Dopo che tutte le sottoscrizioni di un argomento hanno confermato un messaggio, quest'ultimo viene eliminato in modo asincrono dall'origine del messaggio di pubblicazione e dall'archiviazione.

Messaggi diversi per un singolo argomento e una singola sottoscrizione possono passare attraverso un numero elevato di publisher, sottoscrittori, utenti che hanno effettuato l'inoltro e utenti che effettuano l'inoltro della sottoscrizione. I publisher possono pubblicare per più utenti di inoltro contemporaneamente e i sottoscrittori possono connettersi a più utenti di inoltro della sottoscrizione per ricevere messaggi. Pertanto, il flusso di messaggi attraverso le connessioni tra publisher, sottoscrittori e utenti di inoltro può essere complesso. Il seguente diagramma mostra la potenziale trasmissione dei messaggi per un singolo argomento e una singola sottoscrizione, in cui colori diversi indicano i diversi percorsi che i messaggi possono seguire dai publisher ai sottoscrittori:

I messaggi provenienti da diversi editori passano attraverso gli utenti che si occupano di pubblicazione e inoltro delle iscrizioni agli abbonati.

Mantenere Pub/Sub in esecuzione

Garantire che un sistema distribuito come Pub/Sub possa rimanere attivo e funzionante e servire in modo efficace tutti i clienti richiede una grande visibilità e un notevole controllo del sistema. La manutenzione del servizio è responsabilità dei nostri Site Reliability Engineer (SRE). Per Pub/Sub, questi tecnici 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 gestione di un sistema come Pub/Sub è avere la possibilità di testare il software prima che venga utilizzato dai clienti. Per rendere possibile tutto ciò, sono disponibili tre ambienti Pub/Sub: test, gestione temporanea e produzione. Le funzionalità di test e gestione temporanea non contengono traffico di clienti; contengono solo i nostri test e il nostro monitoraggio continui che consentono di individuare eventuali problemi con le release. Questi ambienti ricevono nuove release del software prima della produzione. La differenza tra test e gestione temporanea è che quest'ultima è una replica esatta di ciò che si trova nell'ambiente di produzione (o lo sarà a breve), inclusi la versione del software e i flag della riga di comando. Per il primo potrebbero essere attivate funzionalità a cui gli sviluppatori stanno attualmente lavorando e che ne pianificano il rilascio in futuro.

Implementazione

La procedura per implementare e testare Pub/Sub è progettata per ridurre al minimo il potenziale impatto. Vediamo i passaggi tipici per l'implementazione di una nuova versione di Pub/Sub:

  1. Assicurati che tutti i test delle unità e di integrazione abbiano superato il test.

  2. Crea una nuova versione di tutti i server.

  3. Esegui il deployment dei nuovi server negli ambienti di test e di gestione temporanea.

  4. Esegui i server nell'ambiente di test e gestione temporanea per diversi giorni.

  5. Se non esistono problemi noti, rilascia i server di rilascio alla versione canary, un sottoinsieme dell'ambiente di produzione con una piccola quantità di traffico dei clienti.

  6. Se nella versione canary non vengono rilevati problemi, esegui progressivamente il rilascio dei server a una fase di produzione maggiore nell'arco di diversi giorni, fino a quando non vengono rilasciati ovunque.

Poiché Pub/Sub è progettato per essere resiliente agli errori, ad esempio attraverso la separazione tra piano di controllo e piano dati, le implementazioni delle nuove versioni dei server avvengono senza problemi per i clienti e non dovrebbero avere alcun impatto sulle prestazioni che vedono.

Monitoraggio

Per mantenere Pub/Sub attivo e in esecuzione, è fondamentale rilevare e mitigare automaticamente i problemi prima che diventino visibili agli utenti finali. A questo scopo, è necessario monitorare il sistema in modo approfondito. Il team SRE (Site Reliability Engineering) gestisce una serie di indicatori del livello del servizio (SLI), ovvero metriche ben definite che descrivono il comportamento del sistema. Le metriche possono includere "quantità di tempo necessario per il completamento di una richiesta CreateSubscription" o "percentuale di errori generati dalle richieste di pubblicazione". Queste metriche vengono misurate in vari modi. Alcuni di loro sono strettamente interni ai nostri server di inoltro e router. Ad esempio, misurano il tempo necessario per scrivere messaggi su disco.

Tutte queste misure aiutano a definire gli obiettivi del livello di servizio (SLO) interni, ovvero i target specifici per gli SLI. Ad esempio, "Il completamento di una richiesta CreateSubscription non deve richiedere più di cinque secondi". Gli SRE vengono avvisati in caso di violazioni degli SLO e devono prestare attenzione agli avvisi entro cinque minuti.

Un accordo sul livello del servizio (SLA) elenca gli SLO che definiscono le nostre garanzie di rendimento per i nostri utenti finali e le conseguenze nel caso in cui non li rispetti. Puoi leggere lo SLA di Pub/Sub.

Abbiamo un gruppo di clienti che pubblicano e si abbonano in modo prevedibile. Questi sono chiamati prober. I prober esistono sia per il piano dati che per il piano di controllo. Ognuno dei nostri probe compie azioni specifiche come farebbe un cliente, e misura il tempo necessario. Ad esempio, abbiamo un prober che crea una nuova sottoscrizione, pubblica un messaggio e vede quanto tempo è stato necessario per creare la sottoscrizione e ricevere il messaggio. Se i probe determinano che una qualsiasi delle metriche misurate non è quella prevista, gli SRE vengono avvisati.

Le metriche per i nostri server e probe sono riassunte in diverse dashboard interne, il primo posto in cui gli SRE esaminano ogni volta che diagnosticano potenziali problemi. Queste pagine consentono di accedere rapidamente alle statistiche e ai grafici dell'intero servizio. Possono anche essere suddivisi per argomento, data center o singola attività.

Le metriche più interessanti per gli utenti del servizio vengono esposte tramite Google Cloud Monitoring.

Controlli

Abbiamo a disposizione diversi controlli per ottimizzare le prestazioni di Pub/Sub. Alcuni di questi controlli sono progettati per aiutare in caso di interruzioni dei data center o delle macchine. Possiamo applicare vincoli di routing su alcuni o tutti gli argomenti, ovvero regole che specificano insiemi di client che possono e/o non possono connettersi a gruppi di inoltro. Utilizziamo vincoli di routing per svuotare il traffico delle singole attività di inoltro o di interi data center che non funzionano come previsto.

Un'altra funzionalità ottimizzabile è il controllo del flusso. Questa funzionalità ci consente di massimizzare la velocità effettiva evitando di sovraccaricare il servizio. Il controllo del flusso è un tipo di formato di traffico per cui picchi improvvisi di carico possono essere attenuati nel tempo per una maggiore stabilità del servizio. Il controllo del flusso funziona a livello di sistema oppure in base all'argomento o al sottoscrittore per limitare il numero di messaggi o il numero di byte trasferiti o in sospeso. In questo caso, per "eccesso" si intende la consegna al cliente, ma non ancora confermata. Sia il controllo del flusso che i vincoli 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 considerando di passare ai servizi cloud gestiti. Qualsiasi servizio di messaggistica asincrono deve essere creato da zero tenendo presenti queste funzionalità. Con oltre un decennio di esperienza nella consegna rapida di messaggi in modo affidabile, il team di Pub/Sub ha creato e gestisce un servizio in grado di stare al passo con le esigenze dei prodotti più importanti di Google. Ora lo stesso servizio è disponibile per tutti i clienti esterni che vogliono inviare i loro messaggi in tutto il mondo senza doversi preoccupare se il loro sistema di messaggistica è in grado di gestire 2 volte, 10 o 100 volte il 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).
piano di controllo Il livello di Pub/Sub che gestisce l'assegnazione di publisher e sottoscrittori ai server sul piano dati.
piano dati Il livello di Pub/Sub che gestisce lo spostamento dei messaggi tra publisher e sottoscrittori.
inoltro Un server nel piano dati.
accesso globale ai dati I client di sottoscrittori e publisher Pub/Sub non sono a conoscenza della posizione dei dati. Tutte le operazioni di routing e archiviazione vengono eseguite dal servizio stesso, in conformità con le norme relative alla limitazione della località.
scalabile orizzontalmente La capacità di un servizio di gestire senza problemi un carico maggiore mediante l'aumento del numero di istanze dei componenti del servizio.
messaggio I dati che si spostano attraverso Pub/Sub.
distanza di rete Una misura della latenza sulla connessione tra due punti.
Prober Un'attività che agisce come client ed esegue in modo prevedibile una o più azioni sui server Pub/Sub.
pubblica origine messaggio Un insieme di messaggi ricevuti e archiviati da un server di inoltro e l'insieme di ID dei messaggi confermati da tutte le sottoscrizioni allegate.
servizio di pubblicazione/sottoscrizione (Pub/Sub) Un servizio di messaggistica in cui i mittenti dei messaggi sono disaccoppiati dai destinatari dei messaggi
publisher Un client di Pub/Sub che crea messaggi e li invia (pubblicali) su un argomento specifico.
router Un server nel piano di controllo.
vincoli di routing Un elenco di regole che indica quali server di inoltro 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 delineano le conseguenze nel caso in cui non vengano soddisfatti.
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 in base a una sottoscrizione specificata.
abbonamento Un'entità denominata che rappresenta un interesse a ricevere tutti i messaggi relativi a un determinato argomento.
garanzia del punto di sincronizzazione Il momento in cui viene creata una sottoscrizione, in cui tutti i messaggi successivi pubblicati saranno recapitati ai sottoscrittori.
di Pub/Sub. Un'entità denominata che rappresenta un feed di messaggi.