Panoramica dell'architettura di Pub/Sub

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 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.

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 diverse proprietà di un sistema, quindi le sezioni seguenti descrivono come vengono definite 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à. "Carica" 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

  • 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 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 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 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 come raggiunge la sua scalabilità e bassa latenza mantenendo la disponibilità. Il sistema è progettato per essere scalabile orizzontalmente, ossia un aumento delle di argomenti, sottoscrizioni o messaggi può essere gestito aumentando di istanze di server in esecuzione.

I server Pub/Sub vengono eseguiti in tutte le regioni di Google Cloud in tutto il mondo. Questo consente al servizio di offrire un accesso rapido e globale ai dati, gli utenti controllano dove vengono archiviati i messaggi. Cloud Pub/Sub offre dati globali dell'editore e i client sottoscrittori non sono a conoscenza della posizione i server a cui si connettono o il modo in cui questi servizi instradano i dati.

I meccanismi di bilanciamento del carico di Pub/Sub indirizzano il traffico dei publisher il data center Google Cloud più vicino in cui è consentita l'archiviazione dei dati, come definito nella restrizione sulla località delle risorse delle sezioni IAM e Console di amministrazione. Ciò significa che i publisher in più regioni possono pubblicare a un singolo argomento con bassa latenza. Vengono archiviati tutti i singoli messaggi all'interno di 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 la consegna 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 i publisher e gli abbonati sono collegati ai forwarder assegnati, non hanno bisogno di alcuna informazione 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 Pub/Sub distribuisce i client ai server di inoltro 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 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 tenta di distribuire il carico complessivo nell'insieme di inoltratori disponibili. Il router deve bilanciare due obiettivi diversi quando esegue questa assegnazione: (a) uniformità del carico (ovvero, idealmente ogni utente di inoltro deve avere lo stesso carico di lavoro); e (b) la stabilità delle assegnazioni (vale a dire, idealmente, una modifica del carico o una modifica nel gruppo di inoltro disponibili cambia il numero minimo di incarichi 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 cliente 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 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 allontanare 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. Vediamo i passaggi di 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 viene 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. Contemporaneamente alla scrittura del messaggio nello spazio di archiviazione, Pub/Sub lo consegna agli iscritti.

  5. I sottoscrittori inviano una conferma a Pub/Sub per confermare 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 forwarder di pubblicazione, un forwarder a cui è connesso 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 nei cluster in cui mancano i messaggi tutti i messaggi che non si trovano in tutti i cluster.

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, 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 dispone di 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 velocità effettiva per l'argomento, un singolo publisher può inviare i propri messaggi a più server di inoltro e archiviarli in più origini dei messaggi di pubblicazione. Publisher diversi per lo stesso argomento possono anche inviare messaggi a diversi utenti che effettuano la 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 agli utenti che effettuano l'inoltro di sottoscrizione, gli inoltri attraverso i quali i messaggi passano 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 da quel momento in poi verranno consegnati a quella sottoscrizione, una garanzia del punto di sincronizzazione.

Ogni mittente deve richiedere i messaggi ai mittenti di pubblicazione che hanno origini di messaggi 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 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 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 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 di più publisher vengono inoltrati ai sottoscrittori tramite i relativi publisher e sottoscrittori.

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 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 gestione di un sistema come Pub/Sub è avere la possibilità di 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 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. Per il primo potrebbero essere attivate funzionalità a cui gli sviluppatori stanno attualmente lavorando e che ne pianificheranno il rilascio 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:

  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 staging.

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

  5. Se non sono presenti problemi noti, rilascia i server in 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 superiore 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

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 SRE (Site Reliability Engineering) gestisce una serie degli indicatori del livello del servizio (SLI), metriche ben definite che descrivono il comportamento del sistema. Le metriche possono includere "quantità di tempo necessaria per creare una sottoscrizione richiesta di completamento" o "percentuale 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, misurare il tempo necessario per scrivere i messaggi su disco.

Tutte queste misure aiutano a definire obiettivi del livello di servizio (SLO), target specifici per gli SLI. Ad esempio, "una richiesta CreateSubscription non dovrebbe richiedere più di cinque secondi." gli SRE vengono avvisati in caso di violazioni degli SLO e devono e si occupa di ricevere 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.

Abbiamo un gruppo di clienti che pubblicano e si abbonano in modo prevedibile. Si tratta di chiamati prober. I prober esistono sia per il piano dati che per dal 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 prober che crea una nuova sottoscrizione, un messaggio e vede quanto tempo è stato necessario per creare la sottoscrizione 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 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 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 vincoli di routing per svuotare il traffico da attività di inoltro individuali o 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 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 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 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 quadruplo 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 sottoscrittori ai server sul piano dati.
piano dati Il livello di Pub/Sub che gestisce lo spostamento dei messaggi tra publisher e sottoscrittori.
forwarder Un server nel piano di dati.
accesso globale ai dati I client sottoscrittori e publisher Pub/Sub non sono a conoscenza la posizione dei dati. Tutto il routing e l'archiviazione sono a carico del servizio stessa, in conformità con le norme relative alle limitazioni di 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 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 di pubblicazione/sottoscrizione (Pub/Sub) 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 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 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 successivi pubblicati saranno recapitati ai sottoscrittori.
argomento Un'entità denominata che rappresenta un feed di messaggi.