Panoramica dell'architettura di Pub/Sub

Pub/Sub è un servizio di messaggistica asincrono progettato per essere altamente affidabile e scalabile. Il servizio si basa su un componente essenziale dell'infrastruttura Google su 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 caratteristiche di progettazione più importanti 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 alle sue prestazioni in base a tre aspetti: scalabilità, disponibilità e latenza. Questi tre fattori sono spesso in contrasto tra loro e richiedono una compromissione in uno per migliorare gli altri due.

I termini "scalabilità", "disponibilità" e "latenza" possono fare riferimento a diverse proprietà di un sistema, per cui nelle sezioni seguenti viene descritto come vengono definiti in Pub/Sub.

Scalabilità

Un servizio scalabile dovrebbe essere in grado di gestire aumenti del carico senza un notevole degrado della latenza o della disponibilità. "Caricamento" 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 utilizzati

  • Dimensioni 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 a come gestisce i diversi tipi di problemi, eseguendo il failover controllato in modo non percepito dagli 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 improvviso aumento del traffico nel servizio (o in altri componenti software in esecuzione sullo stesso hardware o nelle dipendenze software) determina una carenza di risorse. La disponibilità può anche ridursi a causa di errori umani, ovvero errori nella creazione o nel deployment di software o configurazioni.

Latenza

La latenza è una misura basata sul tempo delle prestazioni di un sistema. 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 la pubblicazione di un messaggio.

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

Architettura di base di Pub/Sub

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

I server Pub/Sub vengono eseguiti in tutte le regioni di Google Cloud nel mondo. Ciò consente al servizio di offrire un accesso rapido e globale ai dati, dando allo stesso tempo agli utenti il controllo su dove sono archiviati i messaggi. Cloud Pub/Sub offre l'accesso globale ai dati in quell'editore e i clienti abbonati non sono a conoscenza della posizione dei server a cui si connettono o del modo in cui questi servizi instradano i dati.

I meccanismi di bilanciamento del carico di Pub/Sub indirizzano il traffico dell'editore al data center Google Cloud più vicino dove è consentita l'archiviazione dei dati, come definito nella sezione Restrizione sulla località delle risorse di IAM e console di amministrazione. Ciò significa che i publisher di più regioni possono pubblicare messaggi in un singolo argomento con bassa latenza. Ogni singolo messaggio è archiviato in un'unica regione. Tuttavia, un argomento potrebbe 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 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 dei publisher e degli abbonati ai server sul piano dati. I server nel piano dati sono denominati forwarder, mentre quelli nel piano di controllo sono denominati router. Quando gli editori e gli abbonati sono collegati ai loro inoltro assegnati, non hanno bisogno di alcuna informazione dai router (purché questi ultimi rimangano accessibili). Di conseguenza, è possibile eseguire l'upgrade del piano di controllo di Pub/Sub senza influire sui client già connessi che inviano o ricevono messaggi.

Piano di controllo

Il piano di controllo Pub/Sub distribuisce i client ai server di inoltro in modo tale da garantire scalabilità, disponibilità e bassa latenza per tutti i client. Qualsiasi utente di inoltro è in grado di servire i clienti per qualsiasi argomento o sottoscrizione. Quando un client si connette a Pub/Sub, il router decide a quali data center 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 tra i mittenti disponibili. Il router deve bilanciare due diversi obiettivi durante l'esecuzione dell'assegnazione: (a) uniformità del carico (ovvero, idealmente ogni inoltro è caricato in modo uguale); e (b) stabilità degli incarichi (ossia, idealmente un cambiamento nel carico o una modifica del gruppo di mittenti disponibili cambia il numero minimo di incarichi esistenti). Il router utilizza una variante di hashing coerente sviluppata da Google Research per raggiungere un equilibrio sintonizzabile tra coerenza e uniformità. Il router fornisce al client un elenco ordinato di mittenti a cui può connettersi. Questo elenco ordinato può variare in base alla disponibilità dello spedizioniere e alla forma del carico da parte del client.

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

Data Plane - La vita di un messaggio

Il piano dati riceve i messaggi dagli editori e li invia ai clienti. Forse il modo migliore per comprendere il piano dati di Pub/Sub è osservare la vita di un messaggio, dal momento in cui viene ricevuto dal servizio a quello in cui non è più presente. Vediamo i passaggi dell'elaborazione di un messaggio. Ai fini di questa sezione, supponiamo che all'argomento su cui è pubblicato il messaggio sia allegato almeno una sottoscrizione. In genere, un messaggio esegue i seguenti passaggi:

  1. Un publisher invia un messaggio.

  2. Il messaggio viene scritto nello spazio di archiviazione.

  3. Pub/Sub invia al publisher una conferma di ricezione del messaggio e garantisce la consegna a tutte le sottoscrizioni allegate.

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

  5. I sottoscrittori inviano a Pub/Sub una conferma di elaborazione del messaggio.

  6. 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 viene inviato a un utente che ha effettuato l'inoltro, ovvero a un inoltro a cui è collegato l'editore. Per garantire la consegna, il messaggio viene immediatamente scritto nello spazio di archiviazione. Il gestore dell'inoltro scrive inizialmente il messaggio in N cluster (dove N è un numero dispari) e considera il messaggio persistente quando è stato scritto in almeno ⌈N/2⌉ cluster. Quando il messaggio viene reso persistente, chi ha eseguito l'inoltro della pubblicazione conferma la ricezione del messaggio al publisher, dopodiché Pub/Sub garantisce che il messaggio verrà consegnato a tutte le sottoscrizioni allegate. Un processo in background scrive regolarmente tutti i messaggi non presenti in tutti i N cluster 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 che siano considerati persistenti in quel cluster. In totale, qualsiasi messaggio pubblicato verrà scritto su almeno ⌈M/2⌉ dischi indipendenti in cluster ⌈N/2⌉ prima di essere considerato persistente e alla fine verrà replicato su dischi N*M.

Chi ha effettuato l'inoltro della pubblicazione ha un elenco di tutte le sottoscrizioni collegate a un argomento. È responsabile di mantenere in modo permanente sia i messaggi pubblicati sia i metadati che descrivono quali messaggi sono stati confermati da ogni sottoscrizione. L'insieme di messaggi ricevuti e archiviati da un utente che ha eseguito l'inoltro della pubblicazione per un determinato argomento, insieme al monitoraggio dei messaggi confermati, viene chiamato "origine messaggio di pubblicazione". A seconda dei requisiti di velocità effettiva per l'argomento, un singolo publisher può inviare i messaggi a più utenti che eseguono l'inoltro della pubblicazione e archiviare i messaggi in più origini dei messaggi di pubblicazione. diversi publisher per lo stesso argomento possono anche inviare messaggi a utenti che eseguono l'inoltro della pubblicazione diversi. Ogni messaggio viene inviato a un solo utente che ha eseguito l'inoltro della pubblicazione. Pub/Sub ottimizza in modo dinamico il numero di utenti che eseguono l'inoltro della pubblicazione che ricevono messaggi per un determinato argomento quando cambia la velocità effettiva.

I sottoscrittori ricevono i messaggi collegandosi agli utenti che si iscrivono, inoltrando i messaggi, tramite i quali i messaggi arrivano ai sottoscrittori dagli editori. Nel caso di un sottoscrittore di tipo pull, "connettersi" equivale a inviare una richiesta di pull. Nel caso di un sottoscrittore push, "connettersi" significa registrare l'endpoint push con Pub/Sub. Una volta creata una sottoscrizione, è garantito che tutti i messaggi pubblicati in seguito vengano recapitati a quella sottoscrizione, ovvero una garanzia del punto di sincronizzazione.

Ogni utente che ha effettuato l'inoltro della sottoscrizione deve richiedere messaggi agli utenti che eseguono l'inoltro delle pubblicazioni che hanno origini messaggi pubblicate per l'argomento. Come gli editori, gli iscritti possono connettersi a più di un utente che si iscrive e può ricevere messaggi. In questo modo, non tutti gli utenti che eseguono l'inoltro delle sottoscrizioni non devono essere a conoscenza o ricevere i messaggi da ogni origine messaggio di pubblicazione per un argomento, una proprietà importante per Pub/Sub per la scalabilità orizzontale. In base alla velocità effettiva dei messaggi consegnati ai sottoscrittori, Pub/Sub ottimizza in modo dinamico il numero di inoltro della sottoscrizione tramite i quali i sottoscrittori ricevono i messaggi relativi a un determinato argomento quando cambia la velocità effettiva.

Un utente che ha effettuato l'inoltro inoltra richieste a uno o più sistemi di inoltro della pubblicazione che hanno origini messaggi pubblicate per un argomento per chiedere i messaggi di cui ha bisogno. L'autore dell'inoltro invia i messaggi non confermati all'autore dell'inoltro della sottoscrizione, che quindi inoltra i messaggi a un sottoscrittore.

Una volta che un sottoscrittore elabora un messaggio, invia una conferma all'autore della sottoscrizione. L'inoltro della sottoscrizione inoltra questa conferma all'inoltro della pubblicazione, che la archivia nell'origine del messaggio di pubblicazione. Una volta che tutte le sottoscrizioni per un argomento hanno confermato un messaggio, questo viene eliminato in modo asincrono dall'origine messaggio di pubblicazione e dallo spazio di archiviazione.

Messaggi diversi per un singolo argomento e abbonamento possono passare attraverso molti editori, abbonati, utenti che eseguono l'inoltro delle pubblicazioni e utenti che hanno effettuato l'invio degli abbonamenti. Gli editori possono pubblicare contemporaneamente più utenti che eseguono l'inoltro e gli abbonati possono connettersi a più utenti che si sono iscritti per ricevere i messaggi. Di conseguenza, il flusso dei messaggi attraverso le connessioni tra publisher, sottoscrittori e utenti che hanno effettuato l'inoltro può essere complesso. Il seguente diagramma mostra il flusso dei messaggi per un singolo argomento e sottoscrizione, dove colori diversi indicano i diversi percorsi che i messaggi possono seguire dai publisher ai sottoscrittori:

I messaggi inviati da diversi editori vengono inviati agli abbonati attraverso gli utenti che eseguono la pubblicazione e l'inoltro degli abbonamenti.

Mantieni Pub/Sub operativo

Garantire che un sistema distribuito come Pub/Sub sia in grado di rimanere attivo e funzionante e di servire efficacemente tutti i clienti richiede una grande quantità di visibilità e controllo sul sistema. Il mantenimento del servizio è responsabilità dei nostri SRE (Site Reliability Engineer). Per Pub/Sub, questi ingegneri lavorano in diverse 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 renderlo possibile, esistono tre ambienti Pub/Sub: test, gestione temporanea e produzione. I test e la gestione temporanea non contengono traffico dei clienti, ma solo test e monitoraggio in esecuzione continua che consentono di individuare 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'ultimo è una replica esatta di ciò che è (o lo sarà a breve) nell'ambiente di produzione, inclusa la versione del software e i flag della riga di comando. Nel primo caso potrebbero essere state abilitate delle funzionalità, a cui gli sviluppatori stanno attualmente lavorando e che prevedono di rilasciarle 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 i test di integrazione siano stati superati.

  2. Creare una nuova versione di tutti i server.

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

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

  5. In assenza di problemi noti, rilascia i server sulla versione canary, un sottoinsieme dell'ambiente di produzione con una piccola quantità di traffico dei clienti.

  6. Se non vengono rilevati problemi nella versione canary, implementa progressivamente i server a una parte più produttiva nell'arco di diversi giorni finché non vengono rilasciati ovunque.

Poiché Pub/Sub è progettato per essere resiliente agli errori, ad esempio attraverso la separazione del piano di controllo e del piano dati, le implementazioni di nuove versioni dei server non comportano problemi per i clienti e non dovrebbero influire sulle prestazioni che vedono.

Monitoraggio

La chiave per mantenere Pub/Sub operativo è rilevare e mitigare automaticamente i problemi prima che diventino visibili agli utenti finali. Per raggiungere questo obiettivo è necessario monitorare attentamente il sistema. Il team SRE (Site Reliability Engineering) gestisce una serie di indicatori del livello del servizio (SLI), metriche ben definite che descrivono il comportamento del sistema. Le metriche possono includere "il tempo necessario per il completamento di una richiesta CreateSubscription" o la "percentuale di errori generati dalle richieste di pubblicazione". Queste metriche vengono misurate in diversi modi. Alcuni sono strettamente interni ai nostri forwarding e router. Ad esempio, misurano il tempo necessario per scrivere i messaggi su disco.

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

Un accordo sul livello del servizio (SLA) elenca gli SLO che definiscono le nostre garanzie di prestazioni ai nostri utenti finali e le conseguenze se non le rispettiamo. Puoi leggere lo SLA di Pub/Sub.

Abbiamo un gruppo di clienti che, in modo prevedibile, pubblicano e si abbonano. Questi sono chiamati prober. I prober esistono sia per il piano dati che per il piano di controllo. Ognuno dei nostri probe esegue azioni specifiche, come farebbe un cliente, e misura la durata delle operazioni. 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 prober stabiliscono che una delle metriche misurate non è quella prevista, vengono avvisati gli SRE.

Le metriche per i nostri server e probe sono riassunte in diverse dashboard interne, in primo luogo gli SRE esaminano ogni volta che diagnosticano potenziali problemi. Queste pagine forniscono un rapido accesso 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 sono 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 insiemi di sistemi di inoltro. Utilizziamo vincoli di routing per svuotare il traffico dalle singole attività di inoltro o da interi data center che non funzionano come previsto.

Un'altra funzionalità regolabile di cui disponiamo è il controllo del flusso. Questa funzionalità ci consente di massimizzare la velocità effettiva evitando sovraccarichi nel servizio. Il controllo di flusso è una forma di formato di traffico in cui picchi improvvisi del carico imprevisti possono essere allentati nel tempo per una maggiore stabilità del servizio. Il controllo del flusso opera a livello di sistema o in base all'argomento o al sottoscrittore, in modo da limitare il numero di messaggi o il numero di byte trasferiti o in sospeso. In questo caso, "in sospeso" significa che è stato inviato al cliente, ma non è ancora stato confermato. Sia i vincoli di controllo del flusso che 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 prendendo in considerazione il passaggio ai servizi cloud gestiti. Qualsiasi servizio di messaggistica asincrono deve essere creato da zero tenendo presenti queste funzioni. Con oltre un decennio di esperienza nella distribuzione rapida di molti messaggi in modo affidabile, il team di Pub/Sub ha creato e gestisce un servizio che può stare al passo con le esigenze dei prodotti più importanti di Google. Ora lo stesso servizio è disponibile per tutti i clienti esterni che desiderano inviare messaggi in tutto il mondo, senza doversi preoccupare di se il loro sistema di messaggistica è in grado di gestire 2, 10 o 100 volte il carico attuale.

Glossario

Termine Descrizione
cluster Un raggruppamento logico di macchine che generalmente 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 publisher e i client degli abbonati Pub/Sub non sono a conoscenza della posizione dei dati. Tutto il routing e l'archiviazione sono gestiti dal servizio stesso, in conformità con i criteri relativi alla restrizione 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 si spostano attraverso Pub/Sub.
distanza della 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 del messaggio Un insieme di messaggi ricevuti e archiviati da un inoltro della pubblicazione 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 (pubblica) su un argomento specificato.
router Un server nel piano di controllo.
vincoli di routing Un elenco di regole che indica quali forwarding devono o non devono essere inviati dai router ai client come possibili endpoint a cui connettersi.
accordo sul livello del servizio (SLA, Service Level Agreement) Un elenco di SLO che definiscono le prestazioni di un sistema garantiti ai clienti e ne delinea le conseguenze se non vengono soddisfatte.
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 i messaggi su una sottoscrizione specificata.
abbonamento Un'entità denominata che rappresenta un interesse a ricevere tutti i messaggi su un determinato argomento.
garanzia del punto di sincronizzazione Il momento in cui viene creata una sottoscrizione, in cui tutti i messaggi pubblicati successivamente vengono recapitati ai sottoscrittori.
di Pub/Sub. Un'entità denominata che rappresenta un feed di messaggi.