{"id":38172,"date":"2019-10-31T22:22:05","date_gmt":"2019-10-31T19:22:05","guid":{"rendered":"https:\/\/prohoster.info\/blog\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka\/"},"modified":"2019-10-31T22:22:05","modified_gmt":"2019-10-31T19:22:05","slug":"ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka","title":{"rendered":"Comprendere i broker di messaggi. Esplorando la meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 3. Kafka","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Continuazione della traduzione di un piccolo libro:<br \/>\n\u00abUnderstanding Message Brokers\u00bb,<br \/>\nautore: Jakub Korab, editore: O'Reilly Media, Inc., data di pubblicazione: Giugno 2017, ISBN: 9781492049296.<\/p>\n<p>Parte precedentemente tradotta: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">Comprendere i broker di messaggi. Esplorando la meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 1. Introduzione<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>CAPITOLO 3<\/h2>\n<p><\/p>\n<h2>Kafka<\/h2>\n<p>\nKafka \u00e8 stata sviluppata in LinkedIn per superare alcune limitazioni dei tradizionali broker di messaggi e per evitare la necessit\u00e0 di configurare pi\u00f9 broker di messaggi per diverse interazioni \"point-to-point\", come descritto in questo libro nella sezione \"Scalabilit\u00e0 verticale e orizzontale\" a pagina 28. Gli scenari d'uso in LinkedIn si basavano principalmente su un'assorbimento unidirezionale di enormi volumi di dati, come i clic sulle pagine e i log di accesso, consentendo allo stesso tempo a pi\u00f9 sistemi di utilizzare questi dati senza impattare sulle prestazioni dei produttori o degli altri consumatori. Infatti, la ragione d'essere di Kafka \u00e8 quella di fornire un'architettura di messaggistica come descritta nel Universal Data Pipeline.<\/p>\n<p>Tenendo presente questo obiettivo finale, sono naturalmente emerse altre esigenze. Kafka deve:<\/p>\n<ul>\n<li>Essere estremamente veloce<\/li>\n<li>Fornire un'alta capacit\u00e0 di gestione dei messaggi<\/li>\n<li>Supportare modelli \"Publisher-Subscriber\" e \"Point-to-Point\"<\/li>\n<li>Non rallentare nell'aggiungere consumatori. Ad esempio, le prestazioni e le code e i topic in ActiveMQ peggiorano all'aumentare del numero di consumatori sul destinatario.<\/li>\n<li>Essere orizzontalmente scalabile; se un broker che persiste i messaggi pu\u00f2 farlo solo alla massima velocit\u00e0 del disco, allora vale la pena oltrepassare un singolo istanza di broker per aumentare le prestazioni.<\/li>\n<li>Separare l'accesso allo storage e il recupero dei messaggi.<\/li>\n<\/ul>\n<p>\nPer raggiungere tutto ci\u00f2, Kafka ha adottato un'architettura che ha ridefinito i ruoli e le responsabilit\u00e0 dei clienti e dei broker di messaggistica. Il modello JMS \u00e8 molto orientato sul broker, dove quest'ultimo si occupa della distribuzione dei messaggi e i clienti devono preoccuparsi solo di inviare e ricevere messaggi. Kafka, al contrario, \u00e8 cliente-centrico, con il cliente che assume molte delle funzioni tradizionali del broker, come la distribuzione equa dei messaggi pertinenti tra i consumatori, ricevendo in cambio un broker estremamente veloce e scalabile. Per coloro che hanno lavorato con sistemi di messaggistica tradizionali, l'utilizzo di Kafka richiede cambiamenti fondamentali nel modo di pensare.<br \/>\nQuesta direzione ingegneristica ha portato alla creazione di un'infrastruttura di messaggistica capace di aumentare di molti ordini di grandezza la capacit\u00e0 rispetto a un broker convenzionale. Come vedremo, questo approccio comporta dei compromessi, il che significa che Kafka non \u00e8 adatto per determinati tipi di carichi e software consolidato.<\/p>\n<h3>Modello unificato del destinatario<\/h3>\n<p>\nPer soddisfare i requisiti descritti sopra, Kafka ha combinato la messaggistica di tipo 'pubblica-sottoscrizione' e 'point-to-point' all'interno di un'unica forma di destinatario \u2014 <i>topic<\/i>. Questo pu\u00f2 confondere le persone che hanno lavorato con sistemi di messaggistica dove la parola 'topic' si riferisce a un meccanismo di broadcasting, da cui (dal topic) la lettura non \u00e8 affidabile. I topic di Kafka dovrebbero essere considerati un tipo ibrido di destinatario, secondo la definizione fornita nell'introduzione di questo libro.<\/p>\n<blockquote><p>Nella restante parte di questo capitolo, se non diversamente specificato, il termine 'topic' si riferir\u00e0 al topic di Kafka.<\/p><\/blockquote>\n<p>\nPer comprendere appieno come si comportano i topic e quali garanzie offrono, dobbiamo prima esaminare come sono implementati in Kafka.<br \/>\n<i>Ogni topic in Kafka ha il proprio log.<\/i><br \/>\nI produttori che inviano messaggi a Kafka scrivono in questo registro, mentre i consumatori leggono dal registro tramite puntatori che si spostano continuamente in avanti. Periodicamente, Kafka elimina le parti pi\u00f9 vecchie del registro, indipendentemente dal fatto che i messaggi in quelle parti siano stati letti o meno. Una parte centrale del design di Kafka \u00e8 che il broker non si preoccupa di sapere se i messaggi sono stati letti; questa responsabilit\u00e0 ricade sul cliente.<\/p>\n<blockquote><p>I termini \"registro\" e \"puntatore\" non compaiono nella <noindex><a rel=\"nofollow\" href=\"https:\/\/kafka.apache.org\/documentation.html\">documentazione di Kafka<\/a><\/noindex>. Questi termini ben noti vengono utilizzati qui per facilitare la comprensione.<\/p><\/blockquote>\n<p>\nQuesto modello \u00e8 completamente diverso da ActiveMQ, dove i messaggi di tutte le code vengono memorizzati in un unico registro, e il broker contrassegna i messaggi come eliminati dopo che sono stati letti.<br \/>\nOra approfondiamo un po' e consideriamo il registro del topic pi\u00f9 nel dettaglio.<br \/>\nIl registro di Kafka \u00e8 composto da pi\u00f9 partizioni (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/tm\/w2\/yf\/tmw2yf3lanppqtrumxoidotplhi.png\">Figura 3-1<\/a><\/noindex>). Kafka garantisce un rigoroso ordinamento in ogni partizione. Ci\u00f2 significa che i messaggi scritti in una partizione in un determinato ordine verranno letti nello stesso ordine. Ogni partizione \u00e8 implementata come un file di registro circolare (rolling) che contiene <i>un sottoinsieme <\/i>di tutti i messaggi inviati al topic dai suoi produttori. Il topic creato contiene per impostazione predefinita una partizione. L'idea delle partizioni \u00e8 un concetto centrale di Kafka per la scalabilit\u00e0 orizzontale.<\/p>\n<p><img decoding=\"async\" alt=\"Comprendere i broker di messaggi. Esplorando la meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/39f41ebcb73ec247656c0dea438158a9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figura 3-1. Partizioni Kafka<\/i><\/p>\n<p>Quando un produttore invia un messaggio a un topic Kafka, decide in quale partizione inviare il messaggio. Esamineremo questo argomento pi\u00f9 nel dettaglio in seguito.<\/p>\n<h2>Lettura dei messaggi<\/h2>\n<p>\nIl client che desidera leggere i messaggi gestisce un puntatore nominato, chiamato <i>gruppo di consumatori (consumer group)<\/i>, che punta a <i>un offset<\/i> del messaggio nella partizione. L'offset \u00e8 una posizione con un numero crescente, che inizia da 0 all'inizio della partizione. Questo gruppo di consumatori, a cui si riferisce l'API tramite un identificatore group_id definito dall'utente, corrisponde <i>a un singolo consumatore logico o sistema<\/i>.<\/p>\n<p>La maggior parte dei sistemi di messaggistica legge i dati dal destinatario attraverso pi\u00f9 istanze e flussi per l'elaborazione parallela dei messaggi. Di conseguenza, ci saranno generalmente molte istanze di consumatori che condividono lo stesso gruppo di consumatori.<\/p>\n<p>Il problema della lettura pu\u00f2 essere rappresentato nei seguenti termini:<\/p>\n<ul>\n<li>Un topic ha diverse partizioni<\/li>\n<li>Molti gruppi di consumatori possono utilizzare il topic contemporaneamente<\/li>\n<li>Un gruppo di consumatori pu\u00f2 avere diverse istanze distinte<\/li>\n<\/ul>\n<p>\nSi tratta di un problema non banale di \"molti a molti\". Per capire come Kafka gestisce le relazioni tra gruppi di consumatori, istanze di consumatori e partizioni, consideriamo una serie di scenari di lettura che diventano progressivamente pi\u00f9 complessi.<\/p>\n<h3>Consumatori e gruppi di consumatori<\/h3>\n<p>\nPrendiamo come punto di partenza un topic con una partizione (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/6z\/tz\/dh\/6ztzdhqmjweck-z15htxb2xbe28.png\">Figura 3-2<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Comprendere i broker di messaggi. Esplorando la meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/46c92e6bd38774dfef3be4bd198bf35d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figura 3-2. Un consumatore legge da una partizione<\/i><\/p>\n<p>Quando un'istanza del consumatore si connette a questo argomento con il proprio group_id, viene assegnata una partizione per la lettura e uno spostamento in questa partizione. La posizione di questo spostamento viene configurata nel client come un puntatore alla posizione pi\u00f9 recente (il messaggio pi\u00f9 recente) o alla posizione pi\u00f9 antica (il messaggio pi\u00f9 vecchio). Il consumatore richiede (polls) i messaggi dall'argomento, il che porta alla loro lettura sequenziale dal registro.<br \/>\nLa posizione dello spostamento viene regolarmente committata nuovamente in Kafka e salvata come messaggi nell'argomento interno <i>_consumer_offsets<\/i>. I messaggi letti non vengono comunque eliminati, a differenza di un broker normale, e il client pu\u00f2 riavvolgere (rewind) lo spostamento per elaborare nuovamente i messaggi gi\u00e0 visualizzati.<\/p>\n<p>Quando si collega un secondo consumatore logico, utilizzando un altro group_id, gestisce un secondo puntatore, che non dipende dal primo (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/qe\/v1\/yk\/qev1yktga3s-g1gqlynylbe3n9w.png\">Figura 3-3<\/a><\/noindex>). In questo modo, il topic Kafka funge da coda, in cui esiste un consumatore e, come un normale topic publish-subscribe (pub-sub), a cui sono iscritti pi\u00f9 consumatori, con l'ulteriore vantaggio che tutti i messaggi vengono conservati e possono essere elaborati pi\u00f9 volte.<\/p>\n<p><img decoding=\"async\" alt=\"Comprendere i broker di messaggi. Esplorando la meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/e9e8b9063ef7367005254d36abb47f4f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figura 3-3. Due consumatori in gruppi di consumatori diversi leggono da una partizione<\/i><\/p>\n<h3>Consumatori nel gruppo di consumatori<\/h3>\n<p>\nQuando un'istanza del consumatore legge dati da una partizione, controlla completamente l'offset e elabora i messaggi come descritto nel precedente paragrafo.<br \/>\nSe pi\u00f9 istanze di consumatori si sono collegate con lo stesso group_id a un topic con una partizione, all'istanza che si \u00e8 collegata per ultima verr\u00e0 assegnato il controllo dell'offset e da quel momento ricever\u00e0 tutti i messaggi (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/0j\/ao\/f2\/0jaof2mdwg3cqvmwemhtxkrltuq.png\">Figura 3-4<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Comprendere i broker di messaggi. Esplorando la meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/ec6af819445dad4028f65449a735ae22.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figura 3-4. Due consumatori nella stessa gruppo di consumatori leggono da una partizione<\/i><\/p>\n<p>Questa modalit\u00e0 di elaborazione, in cui il numero di istanze dei consumatori supera il numero di partizioni, pu\u00f2 essere considerata una forma di consumatore monopolistico. Questo pu\u00f2 essere utile se hai bisogno di una clusterizzazione \"attiva-passiva\" (o \"calda-tiepida\") delle tue istanze dei consumatori, anche se l'esecuzione parallela di pi\u00f9 consumatori (\"attiva-attiva\" o \"calda-calda\") \u00e8 molto pi\u00f9 comune rispetto ai consumatori in attesa.<\/p>\n<blockquote><p>Questo comportamento di distribuzione dei messaggi, descritto sopra, pu\u00f2 sorprendere rispetto al comportamento di una normale coda JMS. In questo modello, i messaggi inviati alla coda saranno distribuiti uniformemente tra due consumatori.<\/p><\/blockquote>\n<p>\nPi\u00f9 spesso, quando creiamo pi\u00f9 istanze di consumatori, lo facciamo o per l'elaborazione parallela dei messaggi, o per aumentare la velocit\u00e0 di lettura, o per migliorare la resilienza del processo di lettura. Poich\u00e9 solo un'istanza del consumatore pu\u00f2 leggere dati da una partizione contemporaneamente, come si raggiunge questo in Kafka?<\/p>\n<p>Un modo per farlo \u00e8 utilizzare un singolo consumer per leggere tutti i messaggi e passarli a un pool di thread. Sebbene questo approccio aumenti la capacit\u00e0 di elaborazione, complica la logica dei consumer e non migliora la resilienza del sistema di lettura. Se un'istanza del consumer si disconnette a causa di un guasto elettrico o di un evento simile, la lettura si interrompe.<\/p>\n<p>Il modo canonico per affrontare questo problema in Kafka \u00e8 utilizzare un<i>maggiore numero di partizioni.<\/i>Partizionamento<\/p>\n<h3>Le partizioni sono il meccanismo principale per il parallelismo nella lettura e per scalare un topic oltre la capacit\u00e0 di un singolo broker. Per comprendere meglio questo, consideriamo una situazione in cui esiste un topic con due partizioni e un consumer si iscrive a questo topic (<\/h3>\n<p>\nFigure 3-5<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/en\/9g\/ct\/en9gct0o017cqp8buawguwlscty.png\">Figure 3-5. Un consumer legge da pi\u00f9 partizioni<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Comprendere i broker di messaggi. Esplorando la meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/cc766bf69af22698aacc3f1ac70b067f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>In questo scenario, al consumer viene data la possibilit\u00e0 di controllare i puntatori corrispondenti al suo group_id in entrambe le partizioni e inizia a leggere messaggi da entrambe le partizioni.<\/i><\/p>\n<p>In questo scenario, al consumatore viene dato il controllo sui puntatori corrispondenti al suo group_id in entrambe le partizioni e inizia a leggere i messaggi da entrambe le partizioni.<br \/>\nQuando viene aggiunto un consumatore aggiuntivo a questo topic per lo stesso group_id, Kafka riassegna (reallocate) una delle partizioni dal primo al secondo consumatore. Da quel momento, ogni istanza del consumatore legger\u00e0 da una partizione del topic.<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/8b\/a0\/um\/8ba0umn2yzr9yy3vztonhdfiub0.png\">Figura 3-6<\/a><\/noindex>).<\/p>\n<p>Per garantire l'elaborazione dei messaggi in parallelo su 20 thread, \u00e8 necessario avere almeno 20 partizioni. Se ci sono meno partizioni, ci saranno consumatori senza lavoro, come descritto in precedenza nella discussione sui consumatori monopolisti.<\/p>\n<p><img decoding=\"async\" alt=\"Comprendere i broker di messaggi. Esplorando la meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/a3c4001e4a5b92d53b6f529b2633254a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figura 3-6. Due consumatori nella stessa gruppo di consumatori leggono da partizioni diverse<\/i><\/p>\n<p>Questo schema riduce significativamente la complessit\u00e0 del lavoro del broker Kafka rispetto alla distribuzione dei messaggi necessaria per supportare le code JMS. Non \u00e8 necessario preoccuparsi dei seguenti aspetti:<\/p>\n<ul>\n<li>Quale consumatore dovrebbe ricevere il prossimo messaggio, basandosi sulla distribuzione ciclica (round-robin), la capacit\u00e0 attuale dei buffer di prelettura o sui messaggi precedenti (come per i gruppi di messaggi JMS).<\/li>\n<li>Quali messaggi sono stati inviati a quali consumatori e se devono essere consegnati nuovamente in caso di errore.<\/li>\n<\/ul>\n<p>\nL'unica cosa che deve fare il broker Kafka \u00e8 inviare consecutivamente i messaggi al consumatore quando quest'ultimo li richiede.<\/p>\n<p>Tuttavia, i requisiti per la parallelizzazione della lettura e la ritrasmissione dei messaggi falliti non svaniscono: la responsabilit\u00e0 per essi passa semplicemente dal broker al client. Ci\u00f2 significa che devono essere considerati nel vostro codice.<\/p>\n<h2>Invio di messaggi<\/h2>\n<p>\nLa responsabilit\u00e0 di decidere a quale partizione inviare il messaggio ricade sul produttore di quel messaggio. Per capire il meccanismo tramite il quale ci\u00f2 avviene, dobbiamo prima considerare cosa stiamo realmente inviando.<\/p>\n<p>Mentre in JMS utilizziamo una struttura di messaggio con metadati (intestazioni e propriet\u00e0) e un corpo contenente il payload, in Kafka il messaggio \u00e8 <i>una coppia 'chiave-valore'<\/i>. Il payload del messaggio viene inviato come valore. La chiave, d'altra parte, \u00e8 utilizzata principalmente per il partizionamento e deve contenere <i>una chiave specifica per la logica di business<\/i>, per collocare i messaggi correlati nella stessa partizione.<\/p>\n<p>Nel Capitolo 2 abbiamo discusso il scenario delle scommesse online, in cui eventi correlati devono essere elaborati in sequenza da un singolo consumatore:<\/p>\n<ol>\n<li>L'account utente \u00e8 impostato.<\/li>\n<li>I fondi sono accreditati sul conto.<\/li>\n<li>\u00c8 fatta una scommessa, che preleva denaro dal conto.<\/li>\n<\/ol>\n<p>\nSe ogni evento \u00e8 un messaggio inviato a un argomento, in questo caso la chiave naturale sar\u00e0 l'ID dell'account.<br \/>\nQuando un messaggio viene inviato utilizzando l'API Kafka Producer, esso viene passato alla funzione di partizionamento, che, considerando il messaggio e lo stato attuale del cluster Kafka, restituisce l'ID della partizione a cui il messaggio deve essere inviato. Questa funzione \u00e8 implementata in Java attraverso l'interfaccia Partitioner.<\/p>\n<p>Questa interfaccia appare come segue:<\/p>\n<pre><code class=\"java\">interface Partitioner {\n    int partition(String topic,\n        Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster);\n}<\/code><\/pre>\n<p>\nL'implementazione del Partitioner per determinare la partizione utilizza per impostazione predefinita un algoritmo di hashing della chiave (general-purpose hashing algorithm over the key) o round-robin, se la chiave non \u00e8 specificata. Questo valore predefinito funziona bene nella maggior parte dei casi. Tuttavia, in futuro potresti voler scrivere una tua strategia.<\/p>\n<h3>Scrivere una strategia di partizionamento personalizzata<\/h3>\n<p>\nConsideriamo un esempio in cui desideri inviare metadati insieme al payload di un messaggio. Il payload nel nostro esempio \u00e8 una istruzione per effettuare un deposito su un conto di gioco. L'istruzione \u00e8 qualcosa che vorremmo assicurare di non modificare durante la trasmissione e vogliamo essere certi che solo un sistema superiore fidato possa iniziare questa istruzione. In questo caso, i sistemi mittente e destinatario concordano sull'uso della firma per verificare l'autenticit\u00e0 del messaggio.<br \/>\nIn una normale JMS definiamo semplicemente la propriet\u00e0 \"firma del messaggio\" e la aggiungiamo al messaggio. Tuttavia, Kafka non ci fornisce un meccanismo per trasmettere metadati \u2014 solo una chiave e un valore.<\/p>\n<p>Poich\u00e9 il valore rappresenta il payload del bonifico bancario, di cui vogliamo preservare l'integrit\u00e0, non abbiamo altra scelta se non definire una struttura dati da utilizzare nella chiave. Supponendo che sia necessario un identificatore dell'account per il partizionamento, poich\u00e9 tutti i messaggi relativi all'account devono essere elaborati in ordine, elaboreremo la seguente struttura JSON:<\/p>\n<pre><code class=\"json\">{\n  \"signature\": \"541661622185851c248b41bf0cea7ad0\",\n  \"accountId\": \"10007865234\"\n}<\/code><\/pre>\n<p>\nPoich\u00e9 il valore della firma varier\u00e0 a seconda del payload, la strategia di hashing predefinita dell'interfaccia Partitioner non raggrupper\u00e0 in modo affidabile i messaggi correlati. Pertanto, dovremo scrivere una nostra strategia, che analizzi questa chiave e partizioni il valore accountId.<\/p>\n<blockquote><p>Kafka include checksum per rilevare la corruzione dei messaggi nello storage e ha un set completo di funzionalit\u00e0 di sicurezza. Anche in questo caso, a volte emergono requisiti specifici del settore, come quello riportato sopra.<\/p><\/blockquote>\n<p>\nLa strategia di partizionamento utente deve garantire che tutti i messaggi correlati finiscano nella stessa partizione. Sebbene sembri semplice, questo requisito pu\u00f2 essere complicato a causa dell'importanza di ordinare i messaggi correlati e del numero fisso di partizioni nel topic.<\/p>\n<p>Il numero di partizioni in un topic pu\u00f2 cambiare nel tempo, poich\u00e9 possono essere aggiunte se il traffico supera le aspettative iniziali. Pertanto, le chiavi dei messaggi possono essere associate alla partizione in cui sono state inizialmente inviate, implicando parte dello stato che deve essere distribuito tra le istanze del produttore.<\/p>\n<p>Un altro fattore da considerare \u00e8 l'uniformit\u00e0 della distribuzione dei messaggi tra le partizioni. In generale, le chiavi non vengono distribuite equamente tra i messaggi, e le funzioni hash non garantiscono una distribuzione equa dei messaggi per un piccolo insieme di chiavi.<br \/>\n\u00c8 importante notare che, qualunque sia il modo in cui si decide di suddividere i messaggi, il delimitatore stesso potrebbe dover essere riutilizzato.<\/p>\n<p>Consideriamo la necessit\u00e0 di replicare i dati tra i cluster Kafka in diverse ubicazioni geografiche. A tal fine, Kafka fornisce uno strumento da riga di comando chiamato MirrorMaker, che viene utilizzato per leggere i messaggi da un cluster e inviarli a un altro.<\/p>\n<p>MirrorMaker deve comprendere le chiavi del topic replicato per mantenere l'ordine relativo tra i messaggi durante la replica tra i cluster, poich\u00e9 il numero di partizioni per questo topic potrebbe non corrispondere nei due cluster.<\/p>\n<p>Le strategie di partizionamento personalizzate si incontrano relativamente raramente, poich\u00e9 il partizionamento predefinito tramite hashing o round-robin funziona con successo nella maggior parte degli scenari. Tuttavia, se avete bisogno di garanzie rigorose di ordinamento o se \u00e8 necessario estrarre metadati dai carichi utili, allora il partizionamento \u00e8 qualcosa a cui dovreste prestare maggiore attenzione.<\/p>\n<p>I vantaggi della scalabilit\u00e0 e delle prestazioni di Kafka sono dovuti al trasferimento di alcune responsabilit\u00e0 tradizionalmente gestite dal broker al cliente. In questo caso, si prende una decisione su come distribuire messaggi potenzialmente correlati tra pi\u00f9 consumatori che operano in parallelo.<\/p>\n<blockquote><p>Anche i broker JMS devono affrontare tali requisiti. \u00c8 interessante notare che il meccanismo di invio di messaggi correlati allo stesso consumatore, realizzato tramite le JMS Message Groups (una variante della strategia di bilanciamento del carico sticky load balancing (SLB)), richiede anche che il mittente contrassegni i messaggi come correlati. Nel caso di JMS, il broker \u00e8 responsabile dell'invio di questo gruppo di messaggi correlati a un consumatore tra molti e del trasferimento della propriet\u00e0 del gruppo se il consumatore si disconnette.<\/p><\/blockquote>\n<p><\/p>\n<h2>Accordi sul produttore<\/h2>\n<p>\nIl partizionamento non \u00e8 l'unico aspetto da considerare quando si inviano messaggi. Esaminiamo i metodi send() della classe Producer nell'API Java:<\/p>\n<pre><code class=\"java\">Future  send(ProducerRecord  record);\nFuture  send(ProducerRecord  record, Callback callback);<\/code><\/pre>\n<p>\n\u00c8 fondamentale notare che entrambi i metodi restituiscono un Future, il che indica che l'operazione di invio non viene eseguita immediatamente. Di conseguenza, il messaggio (ProducerRecord) viene scritto nel buffer di invio per ogni partizione attiva e inviato al broker in background attraverso la libreria client di Kafka. Sebbene questo renda il processo incredibilmente veloce, significa che un'applicazione scritta in modo inesperto pu\u00f2 perdere messaggi se il suo processo viene interrotto.<\/p>\n<p>Come sempre, esiste un modo per rendere l'operazione di invio pi\u00f9 affidabile a scapito delle prestazioni. La dimensione di questo buffer pu\u00f2 essere impostata su 0, costringendo il thread del'applicazione di invio ad attendere finch\u00e9 l'invio del messaggio al broker non \u00e8 completato, come segue:<\/p>\n<pre><code class=\"java\">RecordMetadata metadata = producer.send(record).get();<\/code><\/pre>\n<p><\/p>\n<h2>Ancora una volta, sulla lettura dei messaggi<\/h2>\n<p>\nLa lettura dei messaggi presenta ulteriori complessit\u00e0 che richiedono considerazione. A differenza dell'API JMS, che pu\u00f2 avviare un ascoltatore di messaggi in risposta all'arrivo di un messaggio, l'interfaccia <i>Consumer <\/i>Kafka effettua solo polling. Esaminiamo pi\u00f9 da vicino il metodo <i>poll ()<\/i>, utilizzato a tale scopo:<\/p>\n<pre><code class=\"java\">ConsumerRecords  poll(long timeout);<\/code><\/pre>\n<p>\nIl valore restituito dal metodo \u00e8 una struttura contenitore che contiene pi\u00f9 oggetti <i>ConsumerRecord <\/i>da potenziali pi\u00f9 partizioni. <i>ConsumerRecord <\/i>\u00e8 esso stesso un oggetto holder per una coppia chiave-valore con i relativi metadati, come la partizione da cui \u00e8 stato ottenuto.<\/p>\n<p>Come discusso nel Capitolo 2, dobbiamo sempre tenere a mente cosa succede ai messaggi dopo il loro trattamento riuscito o non riuscito, ad esempio se il consumatore non riesce a elaborare un messaggio o se si interrompe. In JMS questo veniva gestito tramite la modalit\u00e0 di riconoscimento (acknowledgement mode). Il broker rimuover\u00e0 il messaggio elaborato con successo o lo riaffider\u00e0 se non elaborato o fallito (a condizione che siano state utilizzate delle transazioni). <br \/>\nKafka funziona in modo completamente diverso. I messaggi non vengono rimossi dal broker dopo la lettura e la responsabilit\u00e0 di ci\u00f2 che accade in caso di errore ricade sul codice di lettura stesso.<\/p>\n<p>Come abbiamo gi\u00e0 detto, un gruppo di consumatori \u00e8 associato a un offset nel registro. La posizione nel registro associata a questo offset corrisponde al prossimo messaggio che sar\u00e0 emesso in risposta a <i>poll ()<\/i>. Il momento in cui questo offset aumenta \u00e8 cruciale per la lettura.<\/p>\n<p>Tornando al modello di lettura discusso in precedenza, il trattamento del messaggio consiste in tre fasi:<\/p>\n<ol>\n<li>Estrai il messaggio da leggere.<\/li>\n<li>Elabora il messaggio.<\/li>\n<li>Conferma il messaggio.<\/li>\n<\/ol>\n<p>\nIl consumer Kafka viene fornito con l'opzione di configurazione <i>enable.auto.commit<\/i>. Questa \u00e8 una delle impostazioni comunemente utilizzate di default, come accade di solito con le impostazioni che contengono la parola 'auto'.<\/p>\n<p>Fino a Kafka 0.10, il client che utilizzava questo parametro inviava l'offset dell'ultimo messaggio letto al successivo chiamato <i>poll ()<\/i> dopo l'elaborazione. Ci\u00f2 significava che eventuali messaggi gi\u00e0 estratti (fetched) potevano essere elaborati nuovamente, se il client li aveva gi\u00e0 elaborati, ma era stato inaspettatamente distrutto prima della chiamata. <i>poll ()<\/i>. Poich\u00e9 il broker non mantiene alcuno stato riguardo a quante volte il messaggio sia stato letto, il successivo consumatore che estrae questo messaggio non sapr\u00e0 che \u00e8 successo qualcosa di sbagliato. Questo comportamento era pseudo-transazionale. Lo spostamento veniva confermato solo in caso di elaborazione riuscita del messaggio, ma se il cliente interrompeva il lavoro, il broker reinviava lo stesso messaggio a un altro cliente. Questo comportamento corrispondeva alla garanzia di consegna dei messaggi \u00ab<i>almeno una volta<\/i>\u00ab<\/p>\n<p>In Kafka 0.10, il codice del client \u00e8 stato modificato in modo che la conferma venisse eseguita periodicamente dalla libreria del client, secondo l'impostazione <i>auto.commit.interval.ms<\/i>. Questo comportamento si colloca tra le modalit\u00e0 JMS AUTO_ACKNOWLEDGE e DUPS_OK_ACKNOWLEDGE. Quando si utilizza l'auto-committazione, i messaggi possono essere confermati indipendentemente dal fatto che siano stati effettivamente elaborati \u2014 ci\u00f2 potrebbe accadere in caso di consumatore lento. Se il consumatore si interrompe, i messaggi vengono recuperati dal consumatore successivo, a partire dalla posizione di commit, il che potrebbe portare a saltare un messaggio. In questo caso, Kafka non perde i messaggi; semplicemente il codice lettore non li elabora.<\/p>\n<p>Questa modalit\u00e0 ha le stesse prospettive di quella della versione 0.9: i messaggi possono essere elaborati, ma in caso di errore, l'offset potrebbe non essere stato committato, il che pu\u00f2 potenzialmente portare a duplicati nella consegna. Pi\u00f9 messaggi estraete durante l'esecuzione <i>poll ()<\/i>, maggiore sar\u00e0 questo problema.<\/p>\n<p>Come discusso nella sezione 'Lettura dei messaggi dalla coda' a pagina 21, nel sistema di messaggistica non esiste un concetto di consegna unica dei messaggi, considerando le modalit\u00e0 di errore.<\/p>\n<p>In Kafka, ci sono due modi per confermare (committare) l'offset: automaticamente e manualmente. In entrambi i casi, i messaggi possono essere elaborati pi\u00f9 volte, nel caso in cui un messaggio sia stato elaborato, ma si sia verificato un errore prima della conferma. \u00c8 anche possibile non elaborare affatto un messaggio se la conferma \u00e8 avvenuta in background e il vostro codice \u00e8 stato completato prima che iniziasse l'elaborazione (probabilmente nelle versioni Kafka 0.9 e precedenti).<\/p>\n<p>Per gestire manualmente il processo di conferma dell'offset, \u00e8 possibile utilizzare l'API del consumatore Kafka, impostando il parametro <i>enable.auto.commit<\/i> a false e richiamando esplicitamente uno dei seguenti metodi:<\/p>\n<pre><code class=\"java\">void commitSync();\nvoid commitAsync();<\/code><\/pre>\n<p>\nSe desiderate elaborare un messaggio \"almeno una volta\", dovete committare manualmente l'offset con <i>commitSync ()<\/i>, eseguendo questo comando immediatamente dopo l'elaborazione dei messaggi.<\/p>\n<p>Questi metodi non consentono di confermare (acknowledged) i messaggi fino a quando non sono stati elaborati, ma non fanno nulla per eliminare il potenziale duplicato di elaborazione, creando nel contempo un'apparenza di transazionalit\u00e0. In Kafka non esistono transazioni. Il client non ha la possibilit\u00e0 di fare quanto segue:<\/p>\n<ul>\n<li>Ripristina automaticamente un messaggio fallito. I consumatori devono gestire le eccezioni che si verificano a causa di payload problematici e interruzioni del backend, poich\u00e9 non possono fare affidamento sulla riconsegna dei messaggi da parte del broker.<\/li>\n<li>Invia messaggi a pi\u00f9 argomenti all'interno di un'unica operazione atomica. Come vedremo a breve, il controllo su diversi argomenti e partizioni pu\u00f2 trovarsi su macchine diverse nel cluster Kafka, che non coordinano le transazioni durante l'invio. Al momento della scrittura di questo articolo, \u00e8 stato fatto un certo lavoro per rendere questo possibile tramite KIP-98.<\/li>\n<li>Collegare la lettura di un messaggio da un argomento all'invio di un altro messaggio in un altro argomento. Ancora una volta, l'architettura di Kafka dipende da molte macchine indipendenti che operano come un unico bus e non si fanno tentativi per nascondere questa realt\u00e0. Ad esempio, non esistono componenti API che consentano di colmare <i>Consumatore <\/i>e <i>Produttore <\/i>in una transazione. In JMS questo \u00e8 garantito da un oggetto <i>Sessione<\/i>, da cui vengono creati <i>MessageProducers <\/i>e <i>MessageConsumers<\/i>.<\/li>\n<\/ul>\n<p>\nSe non possiamo fare affidamento sulle transazioni, come possiamo garantire una semantica pi\u00f9 vicina a quella fornita dai tradizionali sistemi di messaggistica?<\/p>\n<p>Se esiste la possibilit\u00e0 che lo spostamento del consumer possa aumentare prima che il messaggio venga elaborato, ad esempio, durante un guasto del consumer, il consumer non ha modo di sapere se il suo gruppo di consumer ha perso messaggi quando gli viene assegnata la partizione. Pertanto, una delle strategie consiste nel riportare indietro (rewind) lo spostamento alla posizione precedente. L'API del consumer Kafka fornisce i seguenti metodi per questo:<\/p>\n<pre><code class=\"java\">void seek(TopicPartition partition, long offset);\nvoid seekToBeginning(Collection  partitions);<\/code><\/pre>\n<p>\nMetodo <i>seek ()<\/i> pu\u00f2 essere utilizzato con il metodo <br \/>\n<i>offsetsForTimes (Map timestampsToSearch)<\/i> per tornare a uno stato in un momento specifico del passato.<\/p>\n<p>L'uso di questo approccio implica che, con alta probabilit\u00e0, alcuni messaggi gi\u00e0 elaborati saranno letti e trattati di nuovo. Per evitare questo, possiamo utilizzare la lettura idempotente, come descritto nel Capitolo 4, per tenere traccia dei messaggi gi\u00e0 visualizzati ed escludere i duplicati.<\/p>\n<p>In alternativa, il codice del tuo consumatore pu\u00f2 essere semplice se \u00e8 consentita la perdita o la duplicazione dei messaggi. Quando consideriamo gli scenari in cui Kafka \u00e8 comunemente utilizzato, come l'elaborazione di eventi di log, metriche, tracciamento dei clic, ecc., comprendiamo che la perdita di messaggi singoli avr\u00e0 probabilmente un impatto minimo sulle applicazioni circostanti. In tali casi, i valori predefiniti sono perfettamente accettabili. D'altra parte, se la tua applicazione deve gestire pagamenti, devi prestare attenzione a ogni singolo messaggio. Tutto dipende dal contesto.<\/p>\n<p>Osservazioni personali mostrano che con l'aumento dell'intensit\u00e0 dei messaggi, il valore di ogni singolo messaggio diminuisce. I messaggi di grande volume diventano generalmente preziosi se considerati in forma aggregata.<\/p>\n<h2>Alta disponibilit\u00e0<\/h2>\n<p>\nL'approccio di Kafka all'alta disponibilit\u00e0 \u00e8 notevolmente diverso da quello di ActiveMQ. Kafka \u00e8 progettata su cluster orizzontalmente scalabili, in cui tutte le istanze del broker ricevono e distribuiscono i messaggi simultaneamente.<\/p>\n<p>Un cluster Kafka \u00e8 composto da pi\u00f9 istanze di broker che lavorano su server diversi. Kafka \u00e8 stata progettata per funzionare su hardware autonomo standard, dove ogni nodo ha il proprio storage dedicato. L'uso di storage di rete (SAN) non \u00e8 raccomandato, poich\u00e9 pi\u00f9 nodi di calcolo possono competere per gli intervalli di tempo dello storage e creare conflitti.<i>I<\/i>\u00e8<\/p>\n<p>Kafka \u00e8 <i>sempre attivo<\/i> sistema. Molti grandi utenti di Kafka non spengono mai i loro cluster, e il software effettua sempre aggiornamenti tramite un riavvio sequenziale. Ci\u00f2 \u00e8 possibile grazie alla garanzia di compatibilit\u00e0 con la versione precedente per i messaggi e le interazioni tra broker.<\/p>\n<p>I broker sono connessi al cluster di server <noindex><a rel=\"nofollow\" href=\"http:\/\/zookeeper.apache.org\">ZooKeeper<\/a><\/noindex>, che funge da registro delle configurazioni e viene utilizzato per coordinare i ruoli di ciascun broker. ZooKeeper \u00e8 a sua volta un sistema distribuito che garantisce alta disponibilit\u00e0 tramite la replicazione delle informazioni stabilendo un <i>quorum<\/i>.<\/p>\n<p>In un caso base, un topic viene creato nel cluster Kafka con le seguenti propriet\u00e0:<\/p>\n<ul>\n<li>Numero di partizioni. Come discusso in precedenza, il valore esatto utilizzato qui dipende dal livello desiderato di lettura parallela.<\/li>\n<li>Il fattore di replica determina quante istanze del broker nel cluster devono contenere i log per questa partizione.<\/li>\n<\/ul>\n<p>\nUtilizzando ZooKeepers per la coordinazione, Kafka cerca di distribuire equamente le nuove partizioni tra i broker nel cluster. Questo avviene attraverso un'istanza che funge da Controller.<\/p>\n<p>nel runtime <i>per ogni partizione del topic<\/i> <i>Controller <\/i>assegna ai broker i ruoli di <i>leader <\/i>(leader, master, principale) e <i>seguaci <\/i>(followers, schiavi, subordinati). Il broker che agisce come leader per una data partizione \u00e8 responsabile della ricezione di tutti i messaggi inviati dai produttori e della distribuzione dei messaggi ai consumatori. Quando si inviano messaggi a una partizione del topic, questi vengono replicati su tutti i nodi del broker che fungono da seguaci per quella partizione. Ogni nodo che contiene i log per la partizione \u00e8 chiamato <i>replica<\/i>. Un broker pu\u00f2 fungere da leader per alcune partizioni e da seguace per altre.<\/p>\n<p>Un seguace che contiene tutti i messaggi conservati dal leader \u00e8 chiamato <i>replica sincronizzata<\/i> (replica in stato sincronizzato, in-sync replica). Se il broker che funge da leader per una partizione si disconnette, qualsiasi broker che \u00e8 in uno stato aggiornato o sincronizzato per quella partizione pu\u00f2 assumere il ruolo di leader. Questo design \u00e8 incredibilmente resiliente.<\/p>\n<p>Una parte della configurazione del produttore \u00e8 il parametro <i>acks<\/i>, che definisce quante repliche devono confermare (acknowledge) la ricezione di un messaggio prima che il flusso dell'applicazione continui a inviare: 0, 1 o tutte. Se \u00e8 impostato il valore <i>all<\/i>, quando viene ricevuto il messaggio, il leader invier\u00e0 una conferma (confirmation) al produttore non appena riceve le conferme (acknowledgements) della registrazione da diverse repliche (inclusa se stessa), definite dalla configurazione del topic <i>min.insync.replicas<\/i> (di default 1). Se il messaggio non pu\u00f2 essere replicato con successo, il produttore lancer\u00e0 un'eccezione per l'applicazione (<i>NotEnoughReplicas<\/i> o <i>NotEnoughReplicasAfterAppend<\/i>).<\/p>\n<p>Nella configurazione tipica, viene creato un topic con un fattore di replica 3 (1 leader, 2 follower per ogni partizione) e il parametro <i>min.insync.replicas<\/i> \u00e8 impostato su 2. In questo caso, il cluster permette che uno dei broker che gestiscono la partizione del topic possa disattivarsi senza influire sulle applicazioni client.<\/p>\n<p>Questo ci riporta al compromesso gi\u00e0 noto tra prestazioni e affidabilit\u00e0. La replicazione richiede tempo aggiuntivo per l'attesa delle conferme (acknowledgments) dai follower. Tuttavia, poich\u00e9 viene eseguita in parallelo, la replicazione, almeno su tre nodi, ha prestazioni pari a quella su due (ignorando l'aumento dell'utilizzo della larghezza di banda di rete).<\/p>\n<p>Utilizzando questo schema di replicazione, Kafka evita abilmente la necessit\u00e0 di garantire la scrittura fisica di ogni messaggio su disco tramite l'operazione <i>sync ()<\/i>. Ogni messaggio inviato dal produttore verr\u00e0 registrato nel log della partizione, ma, come discusso nel Capitolo 2, la registrazione su disco viene inizialmente eseguita nel buffer del sistema operativo. Se questo messaggio \u00e8 replicato su un'altra istanza di Kafka e risiede nella sua memoria, la perdita del leader non implica che il messaggio stesso sia andato perso: pu\u00f2 essere preso da una replica sincronizzata.<br \/>\nRinuncia alla necessit\u00e0 di eseguire l'operazione <i>sync ()<\/i> significa che Kafka pu\u00f2 accettare messaggi alla velocit\u00e0 con cui pu\u00f2 registrarli in memoria. E viceversa, pi\u00f9 a lungo si pu\u00f2 evitare il flush della memoria su disco, meglio \u00e8. Per questo motivo, non \u00e8 raro che ai broker Kafka venga assegnata una memoria di 64 GB o pi\u00f9. Tale utilizzo di memoria consente a un'istanza di Kafka di operare facilmente a velocit\u00e0 migliaia di volte superiori rispetto a un tradizionale broker di messaggi.<\/p>\n<p>Kafka pu\u00f2 anche essere configurato per applicare l'operazione <i>sync ()<\/i> ai pacchetti di messaggi. Poich\u00e9 tutto in Kafka \u00e8 orientato al lavoro con pacchetti, questo funziona effettivamente piuttosto bene per molti scenari di utilizzo ed \u00e8 uno strumento utile per gli utenti che richiedono garanzie molto forti. Gran parte delle prestazioni pure di Kafka \u00e8 legata ai messaggi inviati al broker in forma di pacchetti e al fatto che questi messaggi vengano letti dal broker in blocchi sequenziali con <noindex><a rel=\"nofollow\" href=\"http:\/\/www.linuxjournal.com\/article\/6345\">zero-copy<\/a><\/noindex> operazioni (operazioni in cui non si svolge il compito di copiare dati da un'area di memoria a un'altra). Quest'ultimo rappresenta un grande guadagno in termini di prestazioni e risorse ed \u00e8 possibile solo grazie all'uso della struttura dati di registro sottostante che definisce lo schema di partizione.<\/p>\n<p>Nel cluster Kafka, \u00e8 possibile ottenere prestazioni molto pi\u00f9 elevate rispetto all'uso di un singolo broker Kafka, poich\u00e9 le partizioni del topic possono essere scalate orizzontalmente su pi\u00f9 macchine separate.<\/p>\n<h2>Risultati<\/h2>\n<p>\nIn questo capitolo abbiamo esaminato come l'architettura di Kafka ripensa le relazioni tra i client e i broker, per garantire una pipeline di messaggistica incredibilmente resiliente, con una capacit\u00e0 superiore di molte volte rispetto a un broker di messaggi tradizionale. Abbiamo discusso le funzionalit\u00e0 che utilizza per raggiungere questo obiettivo e abbiamo brevemente esaminato l'architettura delle applicazioni che forniscono queste funzionalit\u00e0. Nel capitolo successivo affronteremo le sfide comuni che devono affrontare le applicazioni basate sulla messaggistica e discuteremo le strategie per risolverle. Concluderemo il capitolo delineando come pensare alle tecnologie di messaggistica in generale, in modo da poter valutare la loro idoneit\u00e0 per i vostri casi d'uso.<\/p>\n<p>Parte precedentemente tradotta: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">Comprendere i broker di messaggi. Studio della meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 1.<\/a><\/noindex><\/p>\n<p><b> Tradotto da: <noindex><a rel=\"nofollow\" href=\"http:\/\/tele.gg\/middle_java\">tele.gg\/middle_java<\/a><\/noindex><\/b><\/p>\n<p><i>Continua&#8230;<\/i><\/p>\n<p class=\"for_users_only_msg\">Solo gli utenti registrati possono partecipare al sondaggio. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Accedi<\/a><\/noindex>, per favore.<\/p>\n<h2 class=\"default-block__polling-title\">Kafka \u00e8 utilizzato nella vostra organizzazione?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    S\u00ec<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    No<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    In passato s\u00ec, ora no<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Pianifichiamo di usarlo<\/p>\n<\/li>\n<\/ul>\n<p>    Hanno votato 38 utenti. 8 utenti si sono astenuti.<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466585\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u043d\u0438\u0433\u0438: \u00abUnderstanding Message Brokers\u00bb, \u0430\u0432\u0442\u043e\u0440: Jakub Korab, \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e: O&#8217;Reilly Media, Inc., \u0434\u0430\u0442\u0430 \u0438\u0437\u0434\u0430\u043d\u0438\u044f: June 2017, ISBN: 9781492049296. \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c: \u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c ActiveMQ \u0438 Kafka. \u0413\u043b\u0430\u0432\u0430 1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0413\u041b\u0410\u0412\u0410 3 Kafka Kafka \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0432 LinkedIn \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438 [&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-38172","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u043d\u0438\u0433\u0438: \u00abUnderstanding Message Brokers\u00bb, \u0430\u0432\u0442\u043e\u0440: Jakub Korab, \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e: O&#039;Reilly Media, Inc., \u0434\u0430\u0442\u0430 \u0438\u0437\u0434\u0430\u043d\u0438\u044f: June 2017, ISBN: 9781492049296. \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c: \u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c ActiveMQ \u0438 Kafka. \u0413\u043b\u0430\u0432\u0430 1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0413\u041b\u0410\u0412\u0410 3 Kafka Kafka \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0432 LinkedIn \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438\" \/>\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\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\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\udd47\u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c ActiveMQ \u0438 Kafka. \u0413\u043b\u0430\u0432\u0430 3. Kafka | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u043d\u0438\u0433\u0438: \u00abUnderstanding Message Brokers\u00bb, \u0430\u0432\u0442\u043e\u0440: Jakub Korab, \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e: O&#039;Reilly Media, Inc., \u0434\u0430\u0442\u0430 \u0438\u0437\u0434\u0430\u043d\u0438\u044f: June 2017, ISBN: 9781492049296. \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c: \u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c ActiveMQ \u0438 Kafka. \u0413\u043b\u0430\u0432\u0430 1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0413\u041b\u0410\u0412\u0410 3 Kafka Kafka \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0432 LinkedIn \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka\" \/>\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-10-31T19:22:05+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:22:05+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\udd47Comprendere i broker di messaggi. Studio della meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 3. Kafka | ProHoster","description":"Continua la traduzione di un breve libro: \u00abUnderstanding Message Brokers\u00bb, autore: Jakub Korab, editore: O'Reilly Media, Inc., data di pubblicazione: Giugno 2017, ISBN: 9781492049296. Parte tradotta in precedenza: Comprendere i broker di messaggi. Studio della meccanica dello scambio di messaggi tramite ActiveMQ e Kafka. Capitolo 1. Introduzione CAPITOLO 3 Kafka Kafka \u00e8 stato sviluppato in LinkedIn per superare alcune limitazioni dei tradizionali broker di messaggi e","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka","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\udd47\u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c ActiveMQ \u0438 Kafka. \u0413\u043b\u0430\u0432\u0430 3. Kafka | ProHoster","og:description":"\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u043d\u0438\u0433\u0438: \u00abUnderstanding Message Brokers\u00bb, \u0430\u0432\u0442\u043e\u0440: Jakub Korab, \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e: O'Reilly Media, Inc., \u0434\u0430\u0442\u0430 \u0438\u0437\u0434\u0430\u043d\u0438\u044f: June 2017, ISBN: 9781492049296. \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c: \u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c ActiveMQ \u0438 Kafka. \u0413\u043b\u0430\u0432\u0430 1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0413\u041b\u0410\u0412\u0410 3 Kafka Kafka \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0432 LinkedIn \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka","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-10-31T19:22:05+00:00","article:modified_time":"2019-10-31T19:22:05+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"38172","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-23 20:46:00","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 15:34:26","updated":"2026-01-23 20:46:00"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/38172","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=38172"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/38172\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=38172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=38172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=38172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}