{"id":52525,"date":"2019-11-10T00:00:00","date_gmt":"2019-11-09T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah"},"modified":"2020-02-18T14:00:16","modified_gmt":"2020-02-18T11:00:16","slug":"rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","title":{"rendered":"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/d8e584d210a6a016a962ad6f956a2078.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nL'affidabilit\u00e0 e l'alta disponibilit\u00e0 sono temi vasti, quindi dedicheremo articoli separati a RabbitMQ e Kafka. Questo articolo \u00e8 su RabbitMQ, mentre il prossimo sar\u00e0 su Kafka, in confronto a RabbitMQ. L'articolo \u00e8 lungo, quindi sistemati comodamente.<\/p>\n<p>Esaminiamo le strategie di tolleranza ai guasti, coerenza e alta disponibilit\u00e0 (HA), oltre ai compromessi che si devono affrontare in ciascuna strategia. RabbitMQ pu\u00f2 funzionare su un cluster di nodi, classificandosi quindi come sistema distribuito. Quando si parla di sistemi distribuiti, parliamo spesso di coerenza e disponibilit\u00e0. <\/p>\n<p>Questi concetti descrivono come il sistema si comporta in caso di guasto. Guasti nelle connessioni di rete, guasti del server, guasti del disco rigido, temporanea indisponibilit\u00e0 del server a causa di garbage collection, perdita di pacchetti o rallentamenti delle connessioni di rete. Tutto ci\u00f2 pu\u00f2 portare a perdita di dati o conflitti. Risulta praticamente impossibile avere un sistema che sia completamente coerente (senza perdita di dati, senza incongruenze nei dati) e disponibile (che accetta operazioni di lettura e scrittura) per tutte le possibili situazioni di guasto.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nVedremo che la coerenza e la disponibilit\u00e0 si trovano agli opposti estremi dello spettro, e dovrai scegliere verso quale ottimizzare. La buona notizia \u00e8 che con RabbitMQ questa scelta \u00e8 possibile. Hai dei veri e propri \"pomelli da nerd\" per spostare l'equilibrio verso una maggiore coerenza o una maggiore disponibilit\u00e0.<\/p>\n<p>Presteremo particolare attenzione a quali configurazioni possono portare alla perdita di dati a causa delle conferme di registrazione. Esiste una catena di responsabilit\u00e0 tra publisher, broker e consumatori. Dopo che un messaggio \u00e8 stato inviato al broker, spetta a lui non perdere il messaggio. Quando il broker conferma al publisher di aver ricevuto il messaggio, ci aspettiamo che non venga perso. Ma vedremo che questo pu\u00f2 effettivamente accadere a seconda della configurazione del tuo broker e dell'editore.<\/p>\n<h1>Primitivi di resilienza di un nodo<\/h1>\n<p><\/p>\n<h3>Code resilienti\/routing<\/h3>\n<p>\nIn RabbitMQ ci sono due tipi di code: durevoli (durable) e non durevoli (non-durable). Tutte le code vengono salvate nel database Mnesia. Le code durevoli vengono ripristinate all'avvio del nodo e, in questo modo, sopravvivono a riavvii, crash di sistema o guasti del server (fintanto che i dati vengono salvati). Questo significa che finch\u00e9 dichiari la routing (exchange) e la coda come durevoli, l'infrastruttura di code\/routing torner\u00e0 operativa.<\/p>\n<p>Le code non durevoli e la routing vengono eliminate al riavvio del nodo.<\/p>\n<h3>Messaggi durevoli<\/h3>\n<p>\nIl fatto che una coda sia durevole non implica che tutti i suoi messaggi sopravvivano al riavvio del nodo. Saranno ripristinati solo i messaggi impostati dal publisher come <i>durevoli<\/i> (persistent). I messaggi durevoli creano effettivamente un carico aggiuntivo sul broker, ma se la perdita di un messaggio \u00e8 inaccettabile, non c'\u00e8 altra scelta.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/8b8e2de4ef82bf8497960657aac0ddb0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 1. Matrice di durevolezza<\/i><\/p>\n<h1>Clusterizzazione con mirroring della coda<\/h1>\n<p>\nPer sopravvivere alla perdita di un broker, abbiamo bisogno di ridondanza. Possiamo raggruppare pi\u00f9 nodi RabbitMQ in un cluster e poi aggiungere ulteriore ridondanza replicando le code tra pi\u00f9 nodi. In questo modo, se un nodo va gi\u00f9, non perdiamo dati e rimaniamo accessibili. <\/p>\n<p>Mirroring della coda:<\/p>\n<ul>\n<li>una coda principale (master), che riceve tutti i comandi di scrittura e lettura\n<\/li>\n<li>uno o pi\u00f9 mirror, che ricevono tutti i messaggi e i metadati dalla coda principale. Questi mirror non esistono per scalabilit\u00e0, ma esclusivamente per ridondanza.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/35f3d4bdc4f5e10da0e40eb91c5d8280.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 2. Mirroring della coda<\/i><\/p>\n<p>Il mirroring viene impostato con la politica corrispondente. Qui puoi scegliere il fattore di replicazione e persino i nodi su cui deve essere collocata la coda. Esempi:<\/p>\n<ul>\n<li><code>ha-mode: all<\/code>\n<\/li>\n<li><code>ha-mode: exactly, ha-params: 2<\/code> (un master e un mirror)\n<\/li>\n<li><code>ha-mode: nodes, ha-params: rabbit@node1, rabbit@node2<\/code><\/li>\n<\/ul>\n<p><\/p>\n<h1>Conferma al publisher<\/h1>\n<p>\nPer ottenere una registrazione coerente sono necessarie conferme al publisher (Publisher Confirms). Senza di esse, si corre il rischio di perdere messaggi. La conferma viene inviata al publisher dopo che il messaggio \u00e8 stato registrato su disco. RabbitMQ scrive i messaggi su disco non al momento della ricezione, ma con periodicit\u00e0, nell'ordine di alcune centinaia di millisecondi. Quando la coda \u00e8 speculata, la conferma viene inviata solo dopo che tutte le repliche hanno anche registrato la loro copia del messaggio su disco. Questo significa che l'uso delle conferme aggiunge un ritardo, ma se la sicurezza dei dati \u00e8 importante, sono necessarie.<\/p>\n<h1>Coda resiliente<\/h1>\n<p>\nQuando il broker termina o si arresta, tutte le code ma\u00eetre su questo nodo si disconnettono insieme a lui. Il cluster poi seleziona la replica pi\u00f9 vecchia di ciascun ma\u00eetre e la promuove a nuovo ma\u00eetre.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/8d8227c00643f35e0dc752b6617e18fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 3. Diverse code speculari e le loro politiche<\/i><\/p>\n<p>Il broker 3 si arresta. Si noti che la replica della Coda C sul Broker 2 viene promossa a ma\u00eetre. Si noti anche che \u00e8 stata creata una nuova replica per la Coda C sul Broker 1. RabbitMQ cerca sempre di mantenere il coefficiente di replica indicato nelle vostre politiche.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/d08b3ada22e79686d448714f7bab009a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 4. Il broker 3 si disconnette, causando il guasto della coda C<\/i> <\/p>\n<p>Si arresta il successivo Broker 1! Ci rimane solo un broker. La replica della Coda B viene promossa a ma\u00eetre.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/dcc1d542c40c441194fd07e51046c619.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 5<\/i><\/p>\n<p>Abbiamo ripristinato il Broker 1. Indipendentemente da quanto bene i dati abbiano sopportato la perdita e il ripristino del broker, tutti i messaggi speculati della coda vengono scartati al riavvio. \u00c8 importante notare questo, poich\u00e9 avr\u00e0 delle conseguenze. Presto esamineremo queste conseguenze. Pertanto, il Broker 1 \u00e8 di nuovo un membro del cluster, e il cluster cerca di rispettare le politiche e quindi crea repliche sul Broker 1.<\/p>\n<p>In questo caso, la perdita del Broker 1 \u00e8 stata totale, cos\u00ec come quella dei dati, quindi la Coda B non speculata \u00e8 stata completamente persa.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/7ac7ab65ea6dff9c5a49372c04c83a37.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 6. Il Broker 1 torna in funzione<\/i><\/p>\n<p>Il broker 3 \u00e8 tornato operativo, quindi le code A e B ricevono indietro gli specchi creati su di esso per soddisfare i loro politici HA. Ma ora tutte le code principali sono su un nodo! Non \u00e8 ideale, \u00e8 meglio una distribuzione uniforme tra i nodi. Sfortunatamente, qui non ci sono particolari opzioni per il riequilibrio dei master. Torneremo su questo problema pi\u00f9 tardi, poich\u00e9 per ora dobbiamo considerare la sincronizzazione della coda. <\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/a54e53bb01e2f830a54f88acaa668984.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 7. Il broker 3 torna operativo. Tutte le code principali sono su un nodo!<\/i><\/p>\n<p>Quindi, ora dovreste avere un'idea di come gli specchi forniscano ridondanza e tolleranza ai guasti. Questo garantisce accessibilit\u00e0 in caso di fallimento di un nodo e protegge dalla perdita di dati. Ma non abbiamo ancora finito, perch\u00e9 in realt\u00e0 \u00e8 molto pi\u00f9 complicato.<\/p>\n<h1>Sincronizzazione<\/h1>\n<p>\nQuando si crea un nuovo specchio, tutti i nuovi messaggi verranno sempre replicati su questo specchio e su qualsiasi altro. Per quanto riguarda i dati esistenti nella coda principale, possiamo replicarli nel nuovo specchio, che diventa una copia completa del master. Possiamo anche decidere di non replicare i messaggi esistenti e permettere alla coda principale e al nuovo specchio di allinearsi nel tempo, con i nuovi messaggi che arrivano alla coda e i messaggi esistenti che vengono rimossi dalla testa della coda principale.<\/p>\n<p>Tale sincronizzazione avviene automaticamente o manualmente e viene gestita tramite la politica delle code. Consideriamo un esempio.<\/p>\n<p>Abbiamo due code mirror. La coda A \u00e8 sincronizzata automaticamente, mentre la coda B \u00e8 sincronizzata manualmente. Entrambe le code contengono dieci messaggi.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/304f2a475fdd0cb6d3069140c667a0a7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 8. Due code con diversi modi di sincronizzazione<\/i><\/p>\n<p>Ora stiamo perdendo il Broker 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/49114966f440c407488bb467ff6dbf93.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 9. Il Broker 3 \u00e8 caduto<\/i><\/p>\n<p>Il broker 3 torna operativo. Il cluster crea uno specchio per ogni coda su un nuovo nodo e sincronizza automaticamente la nuova Coda A con il master. Tuttavia, lo specchio della nuova Coda B rimane vuoto. Ci\u00f2 significa che abbiamo una piena ridondanza della Coda A e solo uno specchio per i messaggi esistenti della Coda B.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/adffc1f5eff8806edbd83772f338d67f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 10. Il nuovo specchio della Coda A riceve tutti i messaggi esistenti, mentre il nuovo specchio della Coda B non riceve nulla.<\/i><\/p>\n<p>In entrambe le code arrivano ancora dieci messaggi. Poi il Broker 2 va in crash e la Coda A torna allo specchio pi\u00f9 vecchio, che si trova sul Broker 1. In caso di guasto non si verificano perdite di dati. Nella Coda B ci sono venti messaggi nel master e solo dieci nello specchio, poich\u00e9 questa coda non ha mai replicato i primi dieci messaggi.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/c6cfef4bced5627bf243c2f020a42646.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 11. La Coda A torna sul Broker 1 senza perdere messaggi<\/i><\/p>\n<p>In entrambe le code arrivano ancora dieci messaggi. Ora si arresta il Broker 1. La Coda A si commuta senza problemi sullo specchio senza perdita di messaggi. Tuttavia, la Coda B presenta dei problemi. A questo punto possiamo ottimizzare o la disponibilit\u00e0 o la coerenza. <\/p>\n<p>Se vogliamo ottimizzare la disponibilit\u00e0, allora la politica <b><i>ha-promote-on-failure<\/i><\/b> dovrebbe essere impostata su <b><i>always<\/i><\/b>. Questo valore \u00e8 predefinito, quindi si pu\u00f2 semplicemente non specificare affatto la politica. In tal caso, di fatto, consentiamo guasti negli specchi non sincronizzati. Ci\u00f2 porter\u00e0 a perdite di messaggi, ma la coda rimane disponibile per la lettura e la scrittura.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/cd704cf4397184c212e1576b986abbaa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 12. La Coda A torna sul Broker 3 senza perdita di messaggi. La Coda B torna sul Broker 3 con la perdita di dieci messaggi<\/i><\/p>\n<p>Possiamo anche impostare <code>ha-promote-on-failure<\/code> a valore <code>when-synced<\/code>. In questo caso, invece di tornare allo specchio, la coda aspetter\u00e0 finch\u00e9 il Broker 1 con i suoi dati non torni operativo. Dopo il suo ritorno, la coda principale si trova di nuovo sul Broker 1 senza perdita di dati. La disponibilit\u00e0 viene sacrificata a favore della sicurezza dei dati. Ma questo \u00e8 un modo rischioso, che potrebbe portare anche a una perdita totale di dati, cosa che discuteremo a breve.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/03fed936fe75220e22f68432ca81b654.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 13. La Coda B rimane non disponibile dopo la perdita del Broker 1<\/i><\/p>\n<p>Puoi chiederti: \"Forse \u00e8 meglio non usare mai la sincronizzazione automatica?\". La risposta \u00e8 che la sincronizzazione \u00e8 un'operazione bloccante. Durante la sincronizzazione, la coda principale non pu\u00f2 eseguire alcuna operazione di lettura o scrittura!<\/p>\n<p>Facciamo un esempio. Ora abbiamo code molto grandi. Come possono crescere a tale dimensione? Per varie ragioni:<\/p>\n<ul>\n<li>Le code non vengono utilizzate attivamente\n<\/li>\n<li>Queste sono code ad alta velocit\u00e0, e proprio ora i consumatori stanno lavorando lentamente \n<\/li>\n<li>Queste sono code ad alta velocit\u00e0, si \u00e8 verificato un guasto e i consumatori stanno recuperando<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/dd4b0fd70cbbc0b7defc06536157770d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 14. Due grandi code con diversi regimi di sincronizzazione<\/i><\/p>\n<p>Ora il Broker 3 cade.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/8c31cfdf485ab4c9dfe13e86a151df4f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 15. Il Broker 3 cade, lasciando un master e uno specchio in ciascuna coda<\/i><\/p>\n<p>Il Broker 3 ritorna in funzione e vengono creati nuovi specchi. La Coda Principale A inizia a replicare i messaggi esistenti su un nuovo specchio e durante questo tempo la Coda non \u00e8 disponibile. La replicazione dei dati richiede due ore, il che porta a due ore di inattivit\u00e0 per questa Coda!<\/p>\n<p>Tuttavia, la Coda B rimane disponibile per tutto il periodo. Ha sacrificato un po' di ridondanza per garantire la disponibilit\u00e0.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/28e641300a1c3f4d70e29a16db51521e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 16. La coda rimane non disponibile durante la sincronizzazione<\/i><\/p>\n<p>Dopo due ore, anche la Coda A diventa disponibile e pu\u00f2 ricominciare a ricevere operazioni di lettura e scrittura.<\/p>\n<h3>Aggiornamenti<\/h3>\n<p>\nQuesto comportamento bloccante durante la sincronizzazione rende difficile l'aggiornamento dei cluster con code molto grandi. Ad un certo punto, il nodo con il master deve essere riavviato, il che significa passare a uno specchio o disabilitare la coda durante l'aggiornamento del server. Se scegliamo di passare, perderemo i messaggi se gli specchi non sono sincronizzati. Di default, durante la disattivazione del broker, non si passa a uno specchio non sincronizzato. Questo significa che non appena il broker ritorna, non perdiamo messaggi, l'unico danno \u00e8 stato l'inattivit\u00e0 della coda. Le regole di comportamento per la disattivazione del broker sono definite dalla politica <code>ha-promote-on-shutdown<\/code>. Puoi impostare uno dei due valori:<\/p>\n<ul>\n<li><code>always<\/code>= attivare il passaggio a specchi non sincronizzati\n<\/li>\n<li><code>when-synced<\/code>= passaggio solo a specchi sincronizzati, altrimenti la coda diventa non disponibile per lettura e scrittura. La coda ritorna in funzione non appena il broker ritorna<\/li>\n<\/ul>\n<p>\nIn ogni caso, con grandi code bisogna scegliere tra perdita di dati e non disponibilit\u00e0.<\/p>\n<h3>Quando la disponibilit\u00e0 aumenta la sicurezza dei dati<\/h3>\n<p>\nPrima di prendere una decisione, \u00e8 necessario considerare un'altra complicazione. Anche se la sincronizzazione automatica \u00e8 migliore per la ridondanza, come influisce sulla sicurezza dei dati? Certo, grazie a una migliore ridondanza RabbitMQ ha una minore probabilit\u00e0 di perdere messaggi esistenti, ma che dire dei nuovi messaggi dai publisher?<\/p>\n<p>Qui bisogna considerare quanto segue:<\/p>\n<ul>\n<li>Il publisher pu\u00f2 semplicemente restituire un errore e il servizio superiore o l'utente possono riprovare in seguito?\n<\/li>\n<li>Il publisher pu\u00f2 salvare il messaggio localmente o nel database per riprovare pi\u00f9 tardi?<\/li>\n<\/ul>\n<p>\nSe il publisher pu\u00f2 solo scartare il messaggio, in realt\u00e0, il miglioramento della disponibilit\u00e0 aumenta anche la sicurezza dei dati.<\/p>\n<p>Di conseguenza, \u00e8 necessario trovare un equilibrio e la soluzione dipende dalla situazione specifica.<\/p>\n<h1>Problemi con ha-promote-on-failure=when-synced<\/h1>\n<p>\nIdea <i><b>ha-promote-on-failure<\/b><\/i>= <i><b>when-synced<\/b><\/i> consiste nell'impedire il passaggio a uno specchio non sincronizzato, evitando cos\u00ec la perdita di dati. La coda rimane non accessibile per la lettura o la scrittura. Invece, cerchiamo di recuperare il broker guasto con dati intatti affinch\u00e9 possa riprendere a funzionare come master senza perdita di dati. <\/p>\n<p>Ma (ed \u00e8 un grande ma) se il broker ha perso i suoi dati, abbiamo un grosso problema: la coda \u00e8 persa! Tutti i dati sono svaniti! Anche se hai specchi che sostanzialmente stanno raggiungendo la coda principale, questi specchi vengono anch'essi scartati.<\/p>\n<p>Per riaggiungere un nodo con lo stesso nome, diciamo al cluster di dimenticare il nodo perduto (comando <i>rabbitmqctl forget_cluster_node<\/i>) e avviare un nuovo broker con lo stesso nome host. Finch\u00e9 il cluster ricorda il nodo perduto, ricorda la vecchia coda e gli specchi non sincronizzati. Quando si dice al cluster di dimenticare il nodo perduto, anche questa coda viene dimenticata. Ora deve essere nuovamente dichiarata. Abbiamo perso tutti i dati, anche se avevamo specchi con un insieme parziale di dati. Sarebbe stato meglio passare a uno specchio non sincronizzato!<\/p>\n<p>Pertanto, la sincronizzazione manuale (e la mancata esecuzione della sincronizzazione) insieme a <code>ha-promote-on-failure=when-synced<\/code>, a mio parere, \u00e8 piuttosto rischiosa. I documenti affermano che tale opzione esiste per la sicurezza dei dati, ma si tratta di una lama a doppio taglio.<\/p>\n<h1>Ribilanciamento dei master<\/h1>\n<p>\nCome promesso, torniamo al problema della concentrazione di tutti i master su uno o pi\u00f9 nodi. Questo pu\u00f2 accadere anche a causa di un aggiornamento \"rolling\" del cluster. In un cluster con tre nodi, tutte le code principali si concentreranno su uno o due nodi.<\/p>\n<p>Il ribilanciamento dei master pu\u00f2 rivelarsi problematico per due motivi:<\/p>\n<ul>\n<li>Non ci sono buoni strumenti per eseguire il ribilanciamento<\/li>\n<li>Sincronizzazione delle code<\/li>\n<\/ul>\n<p>\nPer la riconfigurazione c'\u00e8 un terzo <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Ayanda-D\/rabbitmq-queue-master-balancer\">plugin<\/a><\/noindex>, che non \u00e8 ufficialmente supportato. Riguardo ai plugin di terzi nel manuale di RabbitMQ <noindex><a rel=\"nofollow\" href=\"https:\/\/www.rabbitmq.com\/upgrade.html\">si dice<\/a><\/noindex>: \u00abIl plugin fornisce alcuni strumenti aggiuntivi per la configurazione e il reporting, ma non \u00e8 supportato e non \u00e8 stato verificato dal team di RabbitMQ. Utilizzalo a tuo rischio e pericolo\u00bb.<\/p>\n<p>C'\u00e8 un altro trucco per spostare la coda principale tramite politiche HA. Nel manuale si menziona <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/rabbitmq\/support-tools\/blob\/master\/scripts\/rebalance-queue-masters\">script<\/a><\/noindex> per questo. Funziona come segue:<\/p>\n<ul>\n<li>Rimuove tutti i mirror utilizzando una politica temporanea con priorit\u00e0 superiore rispetto alla politica HA esistente.\n<\/li>\n<li>Modifica la politica HA temporanea per utilizzare la modalit\u00e0 \u00abnodi\u00bb specificando il nodo su cui si desidera spostare la coda principale.\n<\/li>\n<li>Sincronizza la coda per forzare la migrazione.\n<\/li>\n<li>Dopo aver completato la migrazione, rimuove la politica temporanea. L'originale politica HA entra in vigore e viene creato il numero necessario di mirror.<\/li>\n<\/ul>\n<p>\nLo svantaggio \u00e8 che questo approccio potrebbe non funzionare se hai code di grandi dimensioni o requisiti rigorosi di ridondanza.<\/p>\n<p>Ora vediamo come i cluster RabbitMQ gestiscono le partizioni di rete.<\/p>\n<h1>Violazione della coerenza<\/h1>\n<p>\nI nodi di un sistema distribuito sono collegati da legami di rete, e i legami di rete possono e saranno disconnessi. La frequenza delle disconnessioni dipende dall'infrastruttura locale o dall'affidabilit\u00e0 del cloud scelto. In ogni caso, i sistemi distribuiti devono essere in grado di affrontarle. Una volta di pi\u00f9, ci troviamo di fronte a una scelta tra disponibilit\u00e0 e coerenza, e di nuovo la buona notizia \u00e8 che RabbitMQ offre entrambe le opzioni (ovviamente non simultaneamente).<\/p>\n<p>Con RabbitMQ abbiamo due opzioni principali:<\/p>\n<ul>\n<li>Consentire la divisione logica (split-brain). Questo garantisce la disponibilit\u00e0, ma pu\u00f2 provocare perdita di dati.\n<\/li>\n<li>Vietare la divisione logica. Questo potrebbe portare a una perdita di disponibilit\u00e0 a breve termine a seconda di come i client si connettono al cluster. Potrebbe anche portare a un'impossibilit\u00e0 totale nel cluster di due nodi.<\/li>\n<\/ul>\n<p>\nMa cos'\u00e8 la divisione logica? \u00c8 quando un cluster si divide in due a causa della perdita di legami di rete. Su ciascun lato, i mirror vengono elevati a master, quindi alla fine ogni coda ha pi\u00f9 master.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/d880a935df450fb994edfed0715e026e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 17. La coda principale e due specchi, ciascuno su un nodo separato. Poi si verifica un guasto di rete e uno specchio si distacca. Il nodo separato vede che gli altri due si sono disconnessi e promuove i propri specchi a master. Ora abbiamo due code principali, entrambe consentono scrittura e lettura.<\/i> <\/p>\n<p>Se i publisher inviano dati ad entrambi i master, avremo due copie divergenti della coda.<\/p>\n<p>Diverse modalit\u00e0 di RabbitMQ garantiscono o disponibilit\u00e0, o coerenza.<\/p>\n<h3>Modalit\u00e0 Ignore (predefinita)<\/h3>\n<p>\nQuesta modalit\u00e0 garantisce disponibilit\u00e0. Dopo la perdita di connettivit\u00e0 si verifica una separazione logica. Dopo il ripristino della connettivit\u00e0, l'amministratore deve decidere quale sezione privilegiare. La parte perdente verr\u00e0 riavviata e tutti i dati accumulati su quel lato andranno persi.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/4d82c13b5ef21837ba819f5c246a1e41.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 18. Tre publisher sono collegati a tre broker. Internamente, il cluster dirige tutte le richieste alla coda principale sul Broker 2.<\/i><\/p>\n<p>Ora perdiamo il Broker 3. Vede che gli altri broker si sono disconnessi e promuove il suo specchio a master. Si verifica quindi una separazione logica.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/c7e01d51b24023bacdd93cfad95c9eab.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 19. Separazione logica (split-brain). Le scritture vanno in due code principali, e due copie divergono.<\/i><\/p>\n<p>La connettivit\u00e0 viene ripristinata, ma la separazione logica rimane. L'amministratore deve scegliere manualmente la parte perdente. Nel caso seguente, l'amministratore riavvia il Broker 3. Vanno persi tutti i messaggi che non \u00e8 riuscito a inviare.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/51c3ee15024d3c83ba625e3ff9cdeb90.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 20. L'amministratore disabilita il Broker 3.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/0bac8e33de25c0c5381d336d26464858.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 21. L'amministratore avvia il Broker 3 e si unisce al cluster, perdendo tutti i messaggi che erano rimasti.<\/i><\/p>\n<p>Durante la perdita di connettivit\u00e0 e dopo il suo ripristino, il cluster e questa coda erano disponibili per lettura e scrittura.<\/p>\n<h3>Modalit\u00e0 Autoheal<\/h3>\n<p>\nFunziona in modo simile alla modalit\u00e0 Ignore, tranne per il fatto che il cluster stesso sceglie automaticamente la parte perdente dopo la separazione e il ripristino della connettivit\u00e0. La parte perdente torna al cluster vuota e la coda perde tutti i messaggi inviati solo a quella parte.<\/p>\n<h3>Modalit\u00e0 Pause Minority<\/h3>\n<p>\nSe non vogliamo consentire una divisione logica, l'unica opzione \u00e8 rinunciare alla lettura e alla scrittura sul lato inferiore dopo la partizione del cluster. Quando il broker vede di trovarsi sul lato inferiore, sospende il funzionamento, chiudendo tutte le connessioni esistenti e rifiutando qualsiasi nuova. Una volta al secondo controlla il ripristino della connettivit\u00e0. Non appena la connettivit\u00e0 \u00e8 ripristinata, riprende il funzionamento e si riunisce al cluster.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/7a51cf509b2c94e2ae100c7dedd9d21a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 22. Tre publisherr sono collegati a tre broker. Internamente, il cluster dirige tutte le richieste alla coda principale sul Broker 2.<\/i><\/p>\n<p>Poi i Broker 1 e 2 si separano dal Broker 3. Invece di elevare il suo mirror a master, il Broker 3 sospende il funzionamento e diventa non disponibile.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/c12ec38a47e1f8ccceebfa1854f54f21.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 23. Il Broker 3 sospende il funzionamento, disconnette tutti i clienti e rifiuta le richieste di connessione.<\/i><\/p>\n<p>Non appena la connettivit\u00e0 \u00e8 ripristinata, torna al cluster.<\/p>\n<p>Diamo un'occhiata a un altro esempio, dove la coda principale si trova sul Broker 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/4cc6a28270f00a280ecb5af5252f4e07.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 24. La coda principale sul Broker 3.<\/i><\/p>\n<p>Si verifica quindi la stessa perdita di connettivit\u00e0. Il Broker 3 va in pausa, poich\u00e9 si trova sul lato inferiore. Dall'altra parte, i nodi vedono che il Broker 3 \u00e8 andato offline, quindi il mirror pi\u00f9 vecchio dai Broker 1 e 2 viene elevato a master.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/d0d032385533bb53c5a95927afcd3119.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 25. Transizione al Broker 2 in assenza del Broker 3.<\/i><\/p>\n<p>Quando la connettivit\u00e0 \u00e8 ripristinata, il Broker 3 si unir\u00e0 al cluster.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster\" src=\"\/wp-content\/uploads\/2019\/11\/53f8186a040ae07724ef59cf79b72a0c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Fig. 26. Il cluster \u00e8 tornato a operare normalmente.<\/i><\/p>\n<p>\u00c8 importante capire che otteniamo coerenza, ma possiamo anche ottenere disponibilit\u00e0, <i><b>se<\/b><\/i> riusciamo a reindirizzare i clienti sulla parte pi\u00f9 grande della partizione. Per la maggior parte delle situazioni, personalmente sceglierei la modalit\u00e0 Pause Minority, ma in realt\u00e0 dipende dal caso specifico.<\/p>\n<p>Per garantire la disponibilit\u00e0 \u00e8 fondamentale assicurarsi che i clienti si connettano con successo al nodo. Consideriamo le nostre opzioni.<\/p>\n<h1>Garantire la connettivit\u00e0 dei clienti<\/h1>\n<p>\nAbbiamo diverse opzioni su come reindirizzare i clienti alla parte principale del cluster o ai nodi operativi dopo la perdita di connettivit\u00e0 (dopo il fallimento di un nodo). Iniziamo a ricordare che una specifica coda \u00e8 collocata su un nodo particolare, ma il routing e le politiche vengono replicate su tutti i nodi. I clienti possono connettersi a qualsiasi nodo e il routing interno li guider\u00e0 dove necessario. Ma quando un nodo \u00e8 sospeso, rifiuta le connessioni, quindi i clienti devono connettersi a un altro nodo. Se un nodo fallisce, ha veramente poche possibilit\u00e0 di intervenire.<\/p>\n<p>Le nostre opzioni:<\/p>\n<ul>\n<li>L'accesso al cluster avviene tramite un bilanciatore di carico che semplicemente itera ciclicamente sui nodi e i clienti effettuano tentativi di connessione fino al completamento con successo. Se un nodo non funziona o \u00e8 sospeso, i tentativi di connessione a quel nodo falliranno, ma i successivi tentativi andranno verso altri server (in modalit\u00e0 ciclica). Questo \u00e8 adatto per una perdita temporanea di connettivit\u00e0 o per un server non funzionante che verr\u00e0 rapidamente ripristinato.\n<\/li>\n<li>Accesso al cluster tramite bilanciatore di carico e rimozione dei nodi sospesi\/falliti dall'elenco non appena vengono rilevati. Se lo facciamo rapidamente e se i clienti sono in grado di ripetere i tentativi di connessione, otterremo una disponibilit\u00e0 continua.\n<\/li>\n<li>Fornire a ogni cliente un elenco di tutti i nodi e il cliente, durante la connessione, sceglie casualmente uno di essi. Se durante il tentativo di connessione riceve un errore, passa al nodo successivo nell'elenco fino a connettersi.\n<\/li>\n<li>Reindirizzare il traffico dal nodo non operativo\/sospeso tramite DNS. Questo viene fatto utilizzando un basso TTL.<\/li>\n<\/ul>\n<p><\/p>\n<h1>Conclusioni<\/h1>\n<p>\nLa clusterizzazione di RabbitMQ ha i suoi vantaggi e svantaggi. Gli svantaggi pi\u00f9 significativi sono:<\/p>\n<ul>\n<li>quando ci si unisce al cluster, i nodi scartano i propri dati;\n<\/li>\n<li>la sincronizzazione bloccante porta all'inaccessibilit\u00e0 della coda.<\/li>\n<\/ul>\n<p>\nTutte le decisioni difficili derivano da queste due caratteristiche dell'architettura. Se RabbitMQ potesse salvare i dati durante la riconnessione del cluster, la sincronizzazione sarebbe pi\u00f9 veloce. Se fosse in grado di una sincronizzazione non bloccante, sarebbe migliore nel supportare grandi code. Risolvere questi due problemi migliorerebbe significativamente le caratteristiche di RabbitMQ come tecnologia di messaggistica resiliente e altamente disponibile. Non mi sentirei di raccomandare RabbitMQ con clustering nelle seguenti situazioni:<\/p>\n<ul>\n<li>Rete inaffidabile.\n<\/li>\n<li>Memoria inaffidabile.\n<\/li>\n<li>Code molto grandi.<\/li>\n<\/ul>\n<p>\nPer quanto riguarda le impostazioni per alta disponibilit\u00e0, considera le seguenti:<\/p>\n<ul>\n<li><code>ha-promote-on-failure=always<\/code>\n<\/li>\n<li><code>ha-sync-mode=manual<\/code>\n<\/li>\n<li><code>cluster_partition_handling=ignore<\/code> (o <code>autoheal<\/code>)\n<\/li>\n<li>messaggi resilienti\n<\/li>\n<li>assicurati che i client si connettano a un nodo attivo quando un nodo fallisce<\/li>\n<\/ul>\n<p>\nPer la coerenza (sicurezza dei dati), considera le seguenti impostazioni:<\/p>\n<ul>\n<li>Publisher Confirms e Manual Acknowledgements dal lato del consumatore\n<\/li>\n<li><code>ha-promote-on-failure=when-synced<\/code>, se i publisher possono riprovare in seguito e se hai una memoria molto affidabile! Altrimenti imposta <code>=always<\/code>.\n<\/li>\n<li><code>ha-sync-mode=automatic<\/code> (ma per grandi code inattive potrebbe essere necessario il modo manuale; inoltre, considera se la mancanza di disponibilit\u00e0 porter\u00e0 alla perdita di messaggi)\n<\/li>\n<li>modalit\u00e0 Pause Minority\n<\/li>\n<li>messaggi resilienti<\/li>\n<\/ul>\n<p>\nNon abbiamo ancora considerato tutte le questioni di resilienza e alta disponibilit\u00e0; ad esempio, come eseguire procedure amministrative in modo sicuro (come gli aggiornamenti graduali). \u00c8 necessario parlare anche di federazione e del plugin Shovel.<\/p>\n<p>Se ho trascurato qualcosa, ti prego di farmelo sapere.<\/p>\n<p>Vedi anche il mio <noindex><a rel=\"nofollow\" href=\"https:\/\/jack-vanlightly.com\/blog\/2018\/9\/10\/how-to-lose-messages-on-a-rabbitmq-cluster\">post<\/a><\/noindex>, dove faccio un'analisi nel cluster RabbitMQ usando Docker e Blockade per testare alcuni scenari di perdita di messaggi descritti in questo articolo.<\/p>\n<p>Articoli precedenti della serie: <br \/>\n\u21161 \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/416629\/\">habr.com\/ru\/company\/itsumma\/blog\/416629<\/a><\/noindex> <br \/>\n\u21162 \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/418389\/\">habr.com\/ru\/company\/itsumma\/blog\/418389<\/a><\/noindex> <br \/>\n\u21163 \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/437446\/\">habr.com\/ru\/company\/itsumma\/blog\/437446<\/a><\/noindex><br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/471858\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u2014 \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0442\u0435\u043c\u044b, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u0441\u0432\u044f\u0442\u0438\u043c RabbitMQ \u0438 Kafka \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438. \u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043e RabbitMQ, \u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u2014 \u043e Kafka, \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0441 RabbitMQ. \u0421\u0442\u0430\u0442\u044c\u044f \u0434\u043b\u0438\u043d\u043d\u0430\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043f\u043e\u0443\u0434\u043e\u0431\u043d\u0435\u0435. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438, \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u0438 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 (HA), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0434\u0442\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438. RabbitMQ \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52525","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\".\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47RabbitMQ \u043f\u0440\u043e\u0442\u0438\u0432 Kafka: \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430\u0445 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\".\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-09T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:16+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47RabbitMQ contro Kafka: resilienza e alta disponibilit\u00e0 nei cluster | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47RabbitMQ \u043f\u0440\u043e\u0442\u0438\u0432 Kafka: \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430\u0445 | ProHoster","og:description":".","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost-v-klasterah","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-09T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:16+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52525","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 03:54:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:41:25","updated":"2026-01-24 03:54:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/52525","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=52525"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/52525\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=52525"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=52525"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=52525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}