{"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\/da\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka","title":{"rendered":"Forst\u00e5else af meddelelsesbrokere. Unders\u00f8gelse af mekanikken bag meddelelser gennem ActiveMQ og Kafka. Kapitel 3. Kafka","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Forts\u00e6ttelse af overs\u00e6ttelsen af en lille bog:<br \/>\n\u00abForst\u00e5else af beskedbrokers\u00bb<br \/>\nforfatter: Jakub Korab, forlag: O'Reilly Media, Inc., udgivelsesdato: juni 2017, ISBN: 9781492049296.<\/p>\n<p>Den tidligere oversatte del: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">Forst\u00e5else af beskedbrokers. Unders\u00f8gelse af mekanikken bag beskedudveksling ved hj\u00e6lp af ActiveMQ og Kafka. Kapitel 1. Introduktion<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>KAPITEL 3<\/h2>\n<p><\/p>\n<h2>Kafka<\/h2>\n<p>\nKafka blev udviklet hos LinkedIn for at omg\u00e5 nogle af begr\u00e6nsningerne ved traditionelle beskedbrokers og for at undg\u00e5 behovet for at konfigurere flere beskedbrokers til forskellige 'point-to-point' interaktioner, som beskrevet i denne bog i afsnittet 'Vertikal og horisontal skalering' p\u00e5 side 28. Brugsituationerne hos LinkedIn var prim\u00e6rt baseret p\u00e5 ensrettet absorption af meget store datam\u00e6ngder, s\u00e5som klik p\u00e5 sider og adgangslogfiler, samtidig med at disse data kunne anvendes af flere systemer uden at p\u00e5virke ydeevnen for producenter eller andre forbrugere. Faktisk er form\u00e5let med Kafka at opn\u00e5 den arkitektur for beskedudveksling, som beskrives i Universal Data Pipeline.<\/p>\n<p>I betragtning af dette endelige m\u00e5l opstod der naturligt ogs\u00e5 andre krav. Kafka skal:<\/p>\n<ul>\n<li>V\u00e6re ekstremt hurtig<\/li>\n<li>Tilbyde h\u00f8j gennemstr\u00f8mning ved behandling af beskeder<\/li>\n<li>Underst\u00f8tte 'Udgiver-Abonnent' og 'Point-Point' modeller<\/li>\n<li>Ikke blive langsommere ved tilf\u00f8jelse af forbrugere. For eksempel forringes ydeevnen for b\u00e5de k\u00f8er og emner i ActiveMQ, n\u00e5r antallet af forbrugere stiger ved modtageren<\/li>\n<li>V\u00e6re horisontalt skalerbar; hvis en broker, der gemmer (persisterer) beskeder, kun kan g\u00f8re det med maksimal diskhastighed, giver det mening at overskride \u00e9n instans af en broker for at \u00f8ge ydeevnen<\/li>\n<li>Adskille adgangen til opbevaring og genfindelse af beskeder<\/li>\n<\/ul>\n<p>\nFor at opn\u00e5 alt dette har Kafka vedtaget en arkitektur, der omdefinerer rollerne og ansvaret for klienter og message brokers. JMS-modellen er meget broker-orienteret, hvor den er ansvarlig for distributionen af meddelelser, mens klienterne blot skal bekymre sig om at sende og modtage meddelelser. Kafka, derimod, er klient-orienteret, idet klienten p\u00e5tager sig mange af de funktioner, som en traditionel broker normalt ville have, s\u00e5som retf\u00e6rdig distribution af relevante meddelelser blandt forbrugerne, mens den f\u00e5r en ekstremt hurtig og skalerbar broker til geng\u00e6ld. For folk, der har arbejdet med traditionelle message systems, kr\u00e6ver arbejdet med Kafka fundamentale \u00e6ndringer i perspektivet.<br \/>\nDenne ingeni\u00f8rretning har f\u00f8rt til oprettelsen af en message broker-infrastruktur, der er i stand til at \u00f8ge throughput med flere st\u00f8rrelsesordner sammenlignet med en almindelig broker. Som vi vil se, er denne tilgang forbundet med kompromiser, hvilket betyder, at Kafka ikke er egnet til bestemte typer belastninger og installeret software.<\/p>\n<h3>Unified recipient model<\/h3>\n<p>\nFor at opfylde de krav, der er beskrevet ovenfor, har Kafka kombineret publish-subscribe og point-to-point messaging i en enkelt type recipient \u2014 <i>topic<\/i>. Dette forvirrer folk, der har arbejdet med messaging-systemer, hvor ordet \"topic\" refererer til en broadcast-mekanisme, hvor det (fra emnet) at l\u00e6se ikke er p\u00e5lideligt (is nondurable). Kafka-emner b\u00f8r betragtes som en hybrid type recipient, i overensstemmelse med definitionen givet i introduktionen til denne bog.<\/p>\n<blockquote><p>I resten af dette kapitel, medmindre vi specifikt angiver andet, vil termen \"topic\" referere til Kafka-topic.<\/p><\/blockquote>\n<p>\nFor fuldt ud at forst\u00e5, hvordan topics adf\u00e6rd, og hvilke garantier de giver, skal vi f\u00f8rst se p\u00e5, hvordan de er implementeret i Kafka.<br \/>\n<i>Hvert topic i Kafka har sin egen log.<\/i><br \/>\nProducenter, der sender beskeder til Kafka, skriver til denne journal, mens forbrugere l\u00e6ser fra journalen ved hj\u00e6lp af pegere, der konstant bev\u00e6ger sig fremad. Periodisk sletter Kafka de \u00e6ldste dele af journalen, uanset om beskederne i disse dele er blevet l\u00e6st eller ej. En central del af designet i Kafka er, at broker ikke bekymrer sig om, hvorvidt beskeder er blevet l\u00e6st eller ej - det er klientens ansvar.<\/p>\n<blockquote><p>Termen \"journal\" og \"peger\" findes ikke i <noindex><a rel=\"nofollow\" href=\"https:\/\/kafka.apache.org\/documentation.html\">Kafka-dokumentationen<\/a><\/noindex>. Disse velkendte termer bruges her for at hj\u00e6lpe forst\u00e5elsen.<\/p><\/blockquote>\n<p>\nDenne model er helt anderledes end ActiveMQ, hvor beskeder fra alle k\u00f8er gemmes i \u00e9n journal, og brokeren markerer beskeder som slettede efter, at de er blevet l\u00e6st.<br \/>\nLad os nu dykke lidt dybere ned og se n\u00e6rmere p\u00e5 emnets journal.<br \/>\nKafka-journalen best\u00e5r af flere partitioner (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/tm\/w2\/yf\/tmw2yf3lanppqtrumxoidotplhi.png\">Figur 3-1<\/a><\/noindex>). Kafka garanterer streng r\u00e6kkef\u00f8lge i hver partition. Det betyder, at beskeder, der skrives til en partition i en bestemt r\u00e6kkef\u00f8lge, vil blive l\u00e6st i samme r\u00e6kkef\u00f8lge. Hver partition implementeres som en cyklisk (rolling) journalfil, der indeholder <i>et subset <\/i>(subset) af alle beskeder sendt til emnet af dets producenter. Det oprettede emne indeholder som standard \u00e9n partition. Ideen med partitioner er den centrale id\u00e9 i Kafka for horisontal skalering.<\/p>\n<p><img decoding=\"async\" alt=\"Forst\u00e5else af meddelelsesbrokere. Unders\u00f8gelse af mekanikken bag meddelelser gennem ActiveMQ og Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/39f41ebcb73ec247656c0dea438158a9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figur 3-1. Kafka-partitioner<\/i><\/p>\n<p>N\u00e5r en producent sender en besked til et Kafka-emne, bestemmer han, hvilken partition beskeden skal sendes til. Dette vil vi se n\u00e6rmere p\u00e5 senere.<\/p>\n<h2>L\u00e6sning af beskeder<\/h2>\n<p>\nKlienten, der \u00f8nsker at l\u00e6se beskeder, styrer en navngivet peger, kaldet <i>forbrugergruppe (consumer group)<\/i>, der peger p\u00e5 <i>offset<\/i> for beskeden i partitionen. Offset er en position med et stigende nummer, der begynder fra 0 i starten af partitionen. Denne forbrugergruppe, som refereres til i API'et via en brugerdefineret identifikation group_id, svarer til <i>\u00e9n logisk forbruger eller system<\/i>.<\/p>\n<p>De fleste systemer, der bruger meddelelsesudveksling, l\u00e6ser data fra adressaten ved hj\u00e6lp af flere instanser og tr\u00e5de til parallel behandling af beskeder. Derfor vil der normalt v\u00e6re mange instanser af forbrugere, der deler den samme forbrugergruppe.<\/p>\n<p>Problemet med at l\u00e6se kan pr\u00e6senteres p\u00e5 f\u00f8lgende m\u00e5de:<\/p>\n<ul>\n<li>Et emne har flere partitioner<\/li>\n<li>Mange forbrugergrupper kan bruge emnet samtidigt<\/li>\n<li>En forbrugergruppe kan have flere separate instanser<\/li>\n<\/ul>\n<p>\nDette er et ikke-trivielt \"mange til mange\" problem. For at forst\u00e5, hvordan Kafka h\u00e5ndterer forholdet mellem forbrugergrupper, forbrugerinstanser og partitioner, lad os overveje en r\u00e6kke scenarier med gradvist stigende kompleksitet for l\u00e6sning.<\/p>\n<h3>Forbrugere og forbrugergrupper<\/h3>\n<p>\nLad os tage udgangspunkt i et emne med \u00e9n partition (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/6z\/tz\/dh\/6ztzdhqmjweck-z15htxb2xbe28.png\">Figur 3-2<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Forst\u00e5else af meddelelsesbrokere. Unders\u00f8gelse af mekanikken bag meddelelser gennem ActiveMQ og Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/46c92e6bd38774dfef3be4bd198bf35d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figur 3-2. Forbruger l\u00e6ser fra partitionen<\/i><\/p>\n<p>N\u00e5r en forbrugerinstans tilsluttes til dette emne med sit eget group_id, tildeles den en partition til at l\u00e6se fra og et offset i denne partition. Placeringen af dette offset konfigureres i klienten som en pegepind til den seneste position (den nyeste meddelelse) eller den tidligste position (den \u00e6ldste meddelelse). Forbrugeren anmoder om (polls) meddelelser fra emnet, hvilket resulterer i, at de l\u00e6ses sekventielt fra loggen.<br \/>\nPositionen for offset'et commits regelm\u00e6ssigt tilbage til Kafka og gemmes som meddelelser i det interne emne <i>_consumer_offsets<\/i>. L\u00e6ste meddelelser slettes ikke, i mods\u00e6tning til en almindelig broker, og klienten kan spole (rewind) offset'et for at genbehandle allerede viste meddelelser.<\/p>\n<p>N\u00e5r en anden logisk forbruger tilsluttes med et andet group_id, h\u00e5ndterer den en anden pegepind, som ikke er afh\u00e6ngig af den f\u00f8rste (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/qe\/v1\/yk\/qev1yktga3s-g1gqlynylbe3n9w.png\">Figur 3-3<\/a><\/noindex>). P\u00e5 denne m\u00e5de fungerer Kafka-emnet som en k\u00f8, hvor der eksisterer en forbruger og som et almindeligt udgiver-abonnent (pub-sub) emne, hvor flere forbrugere er tilmeldt, med den ekstra fordel, at alle meddelelser bevares og kan behandles flere gange.<\/p>\n<p><img decoding=\"async\" alt=\"Forst\u00e5else af meddelelsesbrokere. Unders\u00f8gelse af mekanikken bag meddelelser gennem ActiveMQ og Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/e9e8b9063ef7367005254d36abb47f4f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figur 3-3. To forbrugere i forskellige forbrugergrupper l\u00e6ser fra en partition<\/i><\/p>\n<h3>Forbrugere i forbrugergruppen<\/h3>\n<p>\nN\u00e5r en forbrugerinstans l\u00e6ser data fra partitionen, har den fuld kontrol over pegepinden og behandler meddelelserne, som beskrevet i den foreg\u00e5ende sektion.<br \/>\nHvis flere forbrugere er tilsluttet et emne med den samme group_id til \u00e9n partition, vil den instans, der tilslutter sig sidst, f\u00e5 kontrol over pegeren, og fra det tidspunkt vil den modtage alle meddelelser (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/0j\/ao\/f2\/0jaof2mdwg3cqvmwemhtxkrltuq.png\">Figur 3-4<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Forst\u00e5else af meddelelsesbrokere. Unders\u00f8gelse af mekanikken bag meddelelser gennem ActiveMQ og Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/ec6af819445dad4028f65449a735ae22.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figur 3-4. To forbrugere i samme gruppe forbrugere l\u00e6ser fra \u00e9n partition<\/i><\/p>\n<p>Denne behandlingsmetode, hvor antallet af forbrugere overstiger antallet af partitioner, kan betragtes som en form for monopol-forbruger. Dette kan v\u00e6re nyttigt, hvis du har brug for \u00abaktivt-passiv\u00bb (eller \u00abvarm-lun\u00bb) klustering af dine forbrugerinstanser, selvom parallel drift af flere forbrugere (\u00abaktivt-aktiv\u00bb eller \u00abvarm-varm\u00bb) er meget mere typisk end forbrugere i ventemodus.<\/p>\n<blockquote><p>Den beskrevne meddelelsesfordelingsadf\u00e6rd kan v\u00e6re overraskende i forhold til, hvordan en almindelig JMS-k\u00f8 opf\u00f8rer sig. I denne model vil meddelelser, der sendes til k\u00f8en, blive j\u00e6vnt fordelt mellem to forbrugere.<\/p><\/blockquote>\n<p>\nOfte, n\u00e5r vi opretter flere forbrugerinstanser, g\u00f8r vi dette enten for parallel behandling af meddelelser, eller for at \u00f8ge l\u00e6sehastigheden, eller for at forbedre stabiliteten af l\u00e6seprocessen. Da kun \u00e9n forbrugerinstans kan l\u00e6se data fra en partition p\u00e5 samme tid, hvordan opn\u00e5s dette i Kafka?<\/p>\n<p>En af m\u00e5derne at g\u00f8re dette p\u00e5 er at bruge \u00e9n forbrugerinstans til at l\u00e6se alle meddelelser og videregive dem til et tr\u00e5dpool. Selvom denne tilgang \u00f8ger behandlingsgennemstr\u00f8mningen, \u00f8ger den kompleksiteten af forbrugernes logik og g\u00f8r ikke noget for at forbedre stabiliteten i l\u00e6sesystemet. Hvis \u00e9n forbrugerinstans g\u00e5r offline p\u00e5 grund af str\u00f8mafbrydelse eller en lignende h\u00e6ndelse, stopper l\u00e6sningen.<\/p>\n<p>Den kanoniske metode til at l\u00f8se dette problem i Kafka er at bruge flere partitioner.<i>O<\/i>Partitionering<\/p>\n<h3>Partitioner er den prim\u00e6re mekanisme til at parallelisere l\u00e6sning og skalere emnet ud over en enkelt brokers kapacitet. For bedre at forst\u00e5 det, lad os overveje et scenarie, hvor der findes et emne med to partitioner, og \u00e9n forbruger abonnerer p\u00e5 dette emne (<\/h3>\n<p>\nFigur 3-5<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/en\/9g\/ct\/en9gct0o017cqp8buawguwlscty.png\">Figur 3-5<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Forst\u00e5else af meddelelsesbrokere. Unders\u00f8gelse af mekanikken bag meddelelser gennem ActiveMQ og Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/cc766bf69af22698aacc3f1ac70b067f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figur 3-5. En forbruger l\u00e6ser fra flere partitioner<\/i><\/p>\n<p>I dette scenarie f\u00e5r forbrugeren kontrol over pointerne, der svarer til hans group_id i begge partitioner, og begynder at l\u00e6se meddelelser fra begge partitioner.<br \/>\nN\u00e5r der tilf\u00f8jes en ekstra forbruger til den samme group_id i dette emne, tildeler Kafka en af partitionerne fra den f\u00f8rste til den anden forbruger. Hver instans af forbrugeren vil derefter l\u00e6se fra \u00e9n partition af emnet (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/8b\/a0\/um\/8ba0umn2yzr9yy3vztonhdfiub0.png\">Figur 3-6<\/a><\/noindex>).<\/p>\n<p>For at sikre parallel behandling af meddelelser i 20 tr\u00e5de, har du brug for mindst 20 partitioner. Hvis der er f\u00e6rre partitioner, vil du have forbrugere, der ikke har noget at arbejde med, hvilket tidligere er beskrevet i diskussionen om monopol-forbrugere.<\/p>\n<p><img decoding=\"async\" alt=\"Forst\u00e5else af meddelelsesbrokere. Unders\u00f8gelse af mekanikken bag meddelelser gennem ActiveMQ og Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/a3c4001e4a5b92d53b6f529b2633254a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figur 3-6. To forbrugere i den samme gruppe af forbrugere l\u00e6ser fra forskellige partitioner<\/i><\/p>\n<p>Denne konfiguration reducerer betydeligt kompleksiteten af Kafka-brokerens arbejde sammenlignet med den meddelelsesfordeling, der kr\u00e6ves for at underst\u00f8tte JMS-k\u00f8er. Her er der ikke behov for at bekymre sig om f\u00f8lgende punkter:<\/p>\n<ul>\n<li>Hvilken forbruger der skal modtage den n\u00e6ste meddelelse, baseret p\u00e5 rund-robin fordeling, den nuv\u00e6rende kapacitet af forudl\u00e6sning buffers eller tidligere meddelelser (som for JMS-meddelelsesgrupper).<\/li>\n<li>Hvilke meddelelser der er sendt til hvilke forbrugere, og om de skal leveres igen i tilf\u00e6lde af fejl.<\/li>\n<\/ul>\n<p>\nAlt, hvad Kafka-brokeren skal g\u00f8re, er at overf\u00f8re meddelelser til forbrugeren, n\u00e5r sidstn\u00e6vnte anmoder om dem.<\/p>\n<p>Imidlertid forsvinder kravene til parallel l\u00e6sning og genlevering af fejlede meddelelser ikke - ansvaret for dem overg\u00e5r blot fra broker til klient. Det betyder, at de skal tages i betragtning i din kode.<\/p>\n<h2>Afsendelse af meddelelser<\/h2>\n<p>\nAnsvarligheden for at beslutte, hvilken partition en meddelelse skal sendes til, p\u00e5hviler producenten af denne meddelelse. For at forst\u00e5 mekanismen, hvormed dette g\u00f8res, er det f\u00f8rst n\u00f8dvendigt at overveje, hvad vi faktisk sender.<\/p>\n<p>Mens vi i JMS bruger en meddelelsesstruktur med metadata (overskrifter og egenskaber) og en krop, der indeholder nyttelasten (payload), er en meddelelse i Kafka <i>et par \"n\u00f8gle-v\u00e6rdi\"<\/i>. Belastningen af meddelelsen sendes som v\u00e6rdi (value). N\u00f8glen, derimod, bruges hovedsageligt til partitionering og skal indeholde <i>forretningslogik-specifik n\u00f8gle<\/i>, s\u00e5 relaterede meddelelser kan placeres i den samme partition.<\/p>\n<p>I Kapitel 2 diskuterede vi scenariet for online v\u00e6ddem\u00e5l, hvor relaterede h\u00e6ndelser skal behandles i orden af en enkelt forbruger:<\/p>\n<ol>\n<li>Brugerkontoen er opsat.<\/li>\n<li>Pengene inds\u00e6ttes p\u00e5 kontoen.<\/li>\n<li>Der placeres et v\u00e6ddem\u00e5l, som tr\u00e6kker penge fra kontoen.<\/li>\n<\/ol>\n<p>\nHvis hver h\u00e6ndelse repr\u00e6senterer en meddelelse sendt til emnet, vil den naturlige n\u00f8gle i dette tilf\u00e6lde v\u00e6re kontoen identificator.<br \/>\nN\u00e5r en meddelelse sendes ved hj\u00e6lp af Kafka Producer API, sendes den til partitioneringsfunktionen, som, baseret p\u00e5 meddelelsen og den nuv\u00e6rende tilstand af Kafka-klyngen, returnerer identifikatoren for den partition, hvor meddelelsen skal sendes. Denne funktion er implementeret i Java gennem interface Partitioner.<\/p>\n<p>Dette interface ser s\u00e5ledes ud:<\/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>\nImplementeringen af Partitioner til at bestemme partitionen bruger som standard en hash-algoritme (general-purpose hashing algorithm over the key) eller round-robin, hvis n\u00f8glen ikke er angivet. Denne standardv\u00e6rdi fungerer godt i de fleste tilf\u00e6lde. Men i fremtiden kan du \u00f8nske at skrive din egen.<\/p>\n<h3>Skrive din egen partitioneringsstrategi<\/h3>\n<p>\nLad os overveje et eksempel, hvor du vil sende metadata sammen med belastningen af meddelelsen. Belastningen i vores eksempel er en instruktion til at foretage en indbetaling til spillekontoen. Instruktionen er det, vi gerne vil sikre os ikke \u00e6ndres under transmission og vil v\u00e6re sikre p\u00e5, at kun et betroet overordnet system kan initiere denne instruktion. I s\u00e5 fald aftaler de sender og modtager systemer at bruge en signatur til at validere meddelelsens autenticitet.<br \/>\nI almindelig JMS definerer vi blot egenskaben \"meddelelsessignatur\" og tilf\u00f8jer den til meddelelsen. Imidlertid giver Kafka os ikke en mekanisme til at transmittere metadata \u2014 kun n\u00f8gle og v\u00e6rdi.<\/p>\n<p>Da v\u00e6rdien er nyttelasten af en bankoverf\u00f8rsel, hvis integritet vi \u00f8nsker at bevare, har vi ikke andet valg end at definere datask strukturen til brug i n\u00f8glen. Antager vi, at vi har brug for en konto-id til partitionering, da alle meddelelser relateret til kontoen skal behandles i r\u00e6kkef\u00f8lge, vil vi finde p\u00e5 f\u00f8lgende JSON-struktur:<\/p>\n<pre><code class=\"json\">{\n  \"signature\": \"541661622185851c248b41bf0cea7ad0\",\n  \"accountId\": \"10007865234\"\n}<\/code><\/pre>\n<p>\nDa v\u00e6rdien af signaturen vil variere afh\u00e6ngigt af nyttelasten, vil standard hash-strategi for Partitioner ikke p\u00e5lideligt gruppere relaterede meddelelser. Derfor skal vi skrive vores egen strategi, der analyserer denne n\u00f8gle og partitionerer v\u00e6rdien af accountId.<\/p>\n<blockquote><p>Kafka inkluderer kontrolsummer for at opdage beskadigede meddelelser i lageret og har et komplet udvalg af sikkerhedsfunktioner. Selv under disse omst\u00e6ndigheder kan der dog opst\u00e5 branche-specifikke krav som n\u00e6vnt ovenfor.<\/p><\/blockquote>\n<p>\nDen brugerdefinerede partitioneringsstrategi skal sikre, at alle relaterede meddelelser placeres i den samme partition. Selvom det virker enkelt, kan kravet kompliceres af vigtigheden af at opretholde r\u00e6kkef\u00f8lgen af relaterede meddelelser og hvor fast antallet af partitioner er i emnet.<\/p>\n<p>Antallet af partitioner i emnet kan \u00e6ndre sig over tid, da de kan tilf\u00f8jes, hvis trafikken overstiger de oprindelige forventninger. S\u00e5ledes kan meddelelsens n\u00f8gler v\u00e6re knyttet til den partition, de oprindeligt blev sendt til, hvilket indeb\u00e6rer en del af staten, der skal fordeles mellem producenter.<\/p>\n<p>En anden faktor, som b\u00f8r tages i betragtning, er j\u00e6vn fordeling af meddelelser mellem partitionerne. Generelt er n\u00f8glerne ikke j\u00e6vnt fordelt over meddelelserne, og hash-funktioner garanterer ikke en retf\u00e6rdig fordeling af meddelelser for et lille antal n\u00f8gler.<br \/>\nDet er vigtigt at bem\u00e6rke, at uanset hvordan du beslutter at opdele meddelelserne, kan selve partitioneringen have brug for at blive genbrugt.<\/p>\n<p>Lad os overveje kravet til datasynkronisering mellem Kafka-klynger p\u00e5 forskellige geografiske placeringer. Til dette form\u00e5l leveres Kafka med et kommandolinjev\u00e6rkt\u00f8j kaldet MirrorMaker, som bruges til at l\u00e6se meddelelser fra \u00e9n klynge og overf\u00f8re dem til en anden.<\/p>\n<p>MirrorMaker skal forst\u00e5 n\u00f8glerne til det replikerede emne for at opretholde den relative r\u00e6kkef\u00f8lge mellem meddelelserne under replikering mellem klynger, da antallet af partitioner for dette emne muligvis ikke stemmer overens i de to klynger.<\/p>\n<p>Brugerdefinerede partitioneringsstrategier ses relativt sj\u00e6ldent, da de standardm\u00e6ssige hashing- eller cykliske strategier fungerer tilfredsstillende i de fleste scenarier. Men hvis du har brug for strenge garantier for r\u00e6kkef\u00f8lgen, eller hvis du skal udtr\u00e6kke metadata fra nyttelasterne, s\u00e5 er partitionering noget, som du b\u00f8r se n\u00e6rmere p\u00e5.<\/p>\n<p>Fordelene ved skalerbarhed og ydeevne i Kafka skyldes, at nogle af de traditionelle brokeropgaver overflyttes til klienten. I dette tilf\u00e6lde tr\u00e6ffes der en beslutning om at distribuere potentielt relaterede meddelelser til flere forbrugere, der arbejder parallelt.<\/p>\n<blockquote><p>JMS-brokere skal ogs\u00e5 tage s\u00e5danne krav i betragtning. Interessant nok kr\u00e6ver den mekanisme, der sender relaterede meddelelser til den samme forbruger, implementeret via JMS Message Groups (en variant af balanceringsstrategien sticky load balancing (SLB)), ogs\u00e5 at afsenderen markerer meddelelserne som relaterede. I tilf\u00e6lde af JMS er brokeren ansvarlig for at sende denne gruppe af relaterede meddelelser til \u00e9n forbruger blandt mange og overdrage ejerskabet af gruppen, hvis forbrugeren falder af.<\/p><\/blockquote>\n<p><\/p>\n<h2>Aftaler fra producenter<\/h2>\n<p>\nPartitionering er ikke det eneste, der skal overvejes, n\u00e5r man sender meddelelser. Lad os se p\u00e5 metoderne send() i Producer-klassen i Java API:<\/p>\n<pre><code class=\"java\">Future  send(ProducerRecord  record);\nFuture  send(ProducerRecord  record, Callback callback);<\/code><\/pre>\n<p>\nDet er vigtigt at bem\u00e6rke, at begge metoder returnerer Future, hvilket indikerer, at sendingsoperationen ikke udf\u00f8res straks. Som et resultat skrives meddelelsen (ProducerRecord) til sendingsbufferen for hver aktiv partition og sendes til broker i baggrunden via Kafka-klientbiblioteket. Selvom dette g\u00f8r arbejdet utrolig hurtigt, betyder det, at et uerfarent skrevet program kan miste meddelelser, hvis dets proces standses.<\/p>\n<p>Som altid er der en m\u00e5de at g\u00f8re sendingsoperationen mere p\u00e5lidelig p\u00e5 bekostning af ydeevnen. St\u00f8rrelsen p\u00e5 denne buffer kan indstilles til 0, og sendende applikationsflow vil blive tvunget til at vente, indtil overf\u00f8rslen af meddelelsen til brokeren er afsluttet, som f\u00f8lger:<\/p>\n<pre><code class=\"java\">RecordMetadata metadata = producer.send(record).get();<\/code><\/pre>\n<p><\/p>\n<h2>Igen om l\u00e6sning af meddelelser<\/h2>\n<p>\nL\u00e6sning af meddelelser har yderligere kompleksiteter, som det er n\u00f8dvendigt at overveje. I mods\u00e6tning til JMS API, som kan starte en meddelelseslytter (message listener) som svar p\u00e5 modtagne meddelelser, er interface <i>Consumer <\/i>Kafka kun polling. Lad os se n\u00e6rmere p\u00e5 metoden <i>poll ()<\/i>, der anvendes til dette form\u00e5l:<\/p>\n<pre><code class=\"java\">ConsumerRecords  poll(long timeout);<\/code><\/pre>\n<p>\nReturv\u00e6rdien af metoden er en containerstruktur, der indeholder flere objekter <i>ConsumerRecord <\/i>fra potentielt flere partitioner. <i>ConsumerRecord <\/i>Selve objektet fungerer som en holder for n\u00f8gle-v\u00e6rdi par med tilh\u00f8rende metadata, s\u00e5som den partition, som den er hentet fra.<\/p>\n<p>Som diskuteret i Kapitel 2, skal vi konstant huske, hvad der sker med meddelelserne efter deres succesfulde eller mislykkede behandling, for eksempel hvis klienten ikke kan behandle meddelelsen, eller hvis den afbryder arbejdet. I JMS blev dette h\u00e5ndteret gennem bekr\u00e6ftelsesmode (acknowledgement mode). Brokeren sletter enten de succesfuldt behandlede meddelelser eller genleverer de ubehandlede eller fejlede (forudsat at transaktioner blev anvendt). <br \/>\nKafka fungerer helt anderledes. Meddelelser slettes ikke i broker efter l\u00e6sningen, og ansvaret for, hvad der sker ved fejl, ligger hos den kode, der l\u00e6ser.<\/p>\n<p>Som vi allerede har n\u00e6vnt, er en gruppe konsumenter knyttet til offset i loggen. Positionen i loggen, der er knyttet til dette offset, svarer til den n\u00e6ste meddelelse, der vil blive udsendt som svar p\u00e5 <i>poll ()<\/i>Det afg\u00f8rende tidspunkt ved l\u00e6sning er det tidspunkt, hvor denne offset \u00f8ges.<\/p>\n<p>N\u00e5r vi vender tilbage til den tidligere n\u00e6vnte l\u00e6semodel, best\u00e5r behandlingen af meddelelsen af tre faser:<\/p>\n<ol>\n<li>Hente meddelelsen til l\u00e6sning.<\/li>\n<li>Behandle meddelelsen.<\/li>\n<li>Bekr\u00e6fte meddelelsen.<\/li>\n<\/ol>\n<p>\nKafka-consumeren leveres med en konfigurationsmulighed <i>enable.auto.commit<\/i>. Dette er ofte en anvendt standardindstilling, som det ofte er tilf\u00e6ldet med indstillinger, der indeholder ordet 'auto'.<\/p>\n<p>F\u00f8r Kafka 0.10 sendte en klient, der brugte denne parameter, offset for den sidst l\u00e6ste meddelelse ved n\u00e6ste kald <i>poll ()<\/i> efter behandling. Det bet\u00f8d, at enhver meddelelse, der allerede var blevet hentet, kunne behandles igen, hvis klienten allerede havde behandlet dem, men blev uventet stoppet f\u00f8r kaldet. <i>poll ()<\/i>. Da broker ikke gemmer nogen tilstand vedr\u00f8rende, hvor mange gange en besked er blevet l\u00e6st, vil den n\u00e6ste forbruger, der henter denne besked, ikke vide, at der skete noget forkert. Denne adf\u00e6rd var pseudo-transaktionel. Offset blev kun forpligtet i tilf\u00e6lde af en vellykket behandling af beskeden, men hvis klienten afbr\u00f8d, sendte broker den samme besked til en anden klient. Denne adf\u00e6rd svarede til garantien for beskedlevering \u00ab<i>mindst \u00e9n gang<\/i>&#171;.<\/p>\n<p>I Kafka 0.10 blev klientkoden \u00e6ndret, s\u00e5 kommit blev periodisk initieret af klientbiblioteket, i overensstemmelse med indstillingen <i>auto.commit.interval.ms<\/i>. Denne adf\u00e6rd ligger et sted mellem tilstandene JMS AUTO_ACKNOWLEDGE og DUPS_OK_ACKNOWLEDGE. Ved brug af autocommit kunne meddelelserne bekr\u00e6ftes uanset om de faktisk var blevet behandlet \u2014 dette kunne ske i tilf\u00e6lde af en langsom consumer. Hvis consumeren gik ned, blev meddelelser hentet af den n\u00e6ste consumer fra den kommitterede position, hvilket kunne f\u00f8re til, at meddelelser blev sprunget over. I s\u00e5 fald mistede Kafka ikke meddelelserne; den l\u00e6sende kode behandlede dem simpelthen ikke.<\/p>\n<p>Denne tilstand har de samme perspektiver som i version 0.9: meddelelser kan blive behandlet, men i tilf\u00e6lde af et fejl kan offset muligvis ikke blive kommitteret, hvilket potentielt kan f\u00f8re til duplikeret levering. Jo flere meddelelser du henter under udf\u00f8relsen <i>poll ()<\/i>, jo st\u00f8rre er dette problem.<\/p>\n<p>Som diskuteret i afsnittet \"L\u00e6sning af meddelelser fra k\u00f8en\" p\u00e5 side 21, findes der ikke noget begreb om engangslevering af meddelelser i messagesystemet, n\u00e5r man tager hensyn til fejlsituationer.<\/p>\n<p>I Kafka er der to m\u00e5der at bekr\u00e6fte (committe) offset p\u00e5: automatisk og manuelt. I begge tilf\u00e6lde kan meddelelser behandles flere gange, hvis en meddelelse er blevet behandlet, men der opstod en fejl f\u00f8r commit. Du kan ogs\u00e5 helt undlade at behandle en meddelelse, hvis commit er sket i baggrunden, og din kode blev afsluttet, f\u00f8r den begyndte behandlingen (m\u00e5ske i Kafka 0.9 og tidligere versioner).<\/p>\n<p>Du kan styre commit-processen for offset manuelt i Kafka konsumer API ved at indstille parameteren <i>enable.auto.commit<\/i> til false og eksplicit kalde en af f\u00f8lgende metoder:<\/p>\n<pre><code class=\"java\">void commitSync();\nvoid commitAsync();<\/code><\/pre>\n<p>\nHvis du str\u00e6ber efter at behandle meddelelsen \"mindst \u00e9n gang\", skal du manuelt committe offset ved hj\u00e6lp af <i>commitSync ()<\/i>, ved at udf\u00f8re denne kommando straks efter behandlingen af meddelelserne.<\/p>\n<p>Disse metoder tillader ikke at bekr\u00e6fte (acknowledged) meddelelser, f\u00f8r de er blevet behandlet, men de g\u00f8r ikke noget for at undg\u00e5 potentiel dobbeltbehandling, mens de samtidig skaber en illusion af transaktionalitet. Der er ingen transaktioner i Kafka. Klienten har ikke mulighed for at g\u00f8re f\u00f8lgende:<\/p>\n<ul>\n<li>Automatisk rulle tilbage (roll back) en mislykket meddelelse. Konsumerne skal selv h\u00e5ndtere undtagelser, der opst\u00e5r p\u00e5 grund af problematiske payloads og backend-afbrydelser, da de ikke kan stole p\u00e5, at meddelelser returneres af broker.<\/li>\n<li>Sende meddelelser til flere emner i en atomar operation. Som vi snart vil se, kan kontrol over forskellige emner og partitioner ligge p\u00e5 forskellige maskiner i Kafka-klusteret, som ikke koordinerer transaktioner ved afsendelse. P\u00e5 tidspunktet for denne artikel var der gjort en vis indsats for at g\u00f8re dette muligt med KIP-98.<\/li>\n<li>Knytte l\u00e6sningen af en meddelelse fra et emne til afsendelsen af en anden meddelelse til et andet emne. Igen afh\u00e6nger Kafka-arkitekturen af mange uafh\u00e6ngige maskiner, der fungerer som en bus, og der g\u00f8res ikke nogen fors\u00f8g p\u00e5 at skjule dette. For eksempel findes der ikke API-komponenter, der g\u00f8r det muligt at knytte <i>Konsumer <\/i>og <i>Producent <\/i>i transaktionen. I JMS sikres dette af objektet <i>Session<\/i>, hvorfra der oprettes <i>MessageProducers <\/i>og <i>MessageConsumers<\/i>.<\/li>\n<\/ul>\n<p>\nHvis vi ikke kan stole p\u00e5 transaktioner, hvordan kan vi s\u00e5 sikre en semantik, der er t\u00e6ttere p\u00e5 den, der leveres af traditionelle beskedudvekslingssystemer?<\/p>\n<p>Hvis der er en chance for, at forbrugerens offset kan stige, f\u00f8r meddelelsen er blevet behandlet, for eksempel under et forbrugerfejl, har forbrugeren ingen m\u00e5de at vide p\u00e5, om dens forbrugergruppe har overset meddelelser, n\u00e5r den bliver tildelt en partition. En af strategierne er derfor at spole (rewind) offsettet tilbage til en tidligere position. Kafka-forbrugerens API tilbyder f\u00f8lgende metoder til dette:<\/p>\n<pre><code class=\"java\">void seek(TopicPartition partition, long offset);\nvoid seekToBeginning(Collection  partitions);<\/code><\/pre>\n<p>\nMetoden <i>seek ()<\/i> kan bruges med metoden <br \/>\n<i>offsetsForTimes (Map timestampsToSearch)<\/i> til at spole tilbage til en tilstand p\u00e5 et bestemt tidspunkt i fortiden.<\/p>\n<p>Implicit betyder brugen af denne tilgang, at det sandsynligvis vil ske, at nogle meddelelser, der tidligere er blevet behandlet, vil blive l\u00e6st og behandlet igen. For at undg\u00e5 dette kan vi bruge idempotent l\u00e6sning, som beskrevet i Kapitel 4, til at holde styr p\u00e5 tidligere sete meddelelser og udelukke dubletter.<\/p>\n<p>Som et alternativ kan din forbrugers kode v\u00e6re simpel, hvis tab eller duplikering af meddelelser er acceptabelt. N\u00e5r vi overvejer brugsscenarier, som Kafka typisk bruges til, s\u00e5som behandling af loggener, metrics, kliksporing osv., forst\u00e5r vi, at tab af enkelte meddelelser sandsynligvis ikke vil have en betydelig indvirkning p\u00e5 de omkringliggende applikationer. I s\u00e5danne tilf\u00e6lde er standardv\u00e6rdier helt acceptable. P\u00e5 den anden side, hvis din applikation skal h\u00e5ndtere betalinger, skal du n\u00f8je passe p\u00e5 hver enkelt meddelelse. Det hele handler om konteksten.<\/p>\n<p>Personlige observationer viser, at med stigende intensitet af meddelelser, falder v\u00e6rdien af hver enkelt meddelelse. Store m\u00e6ngder meddelelser viser sig generelt at v\u00e6re v\u00e6rdifulde, n\u00e5r de betragtes i aggregeret form.<\/p>\n<h2>H\u00f8j tilg\u00e6ngelighed (High Availability)<\/h2>\n<p>\nKafkas tilgang til h\u00f8j tilg\u00e6ngelighed adskiller sig v\u00e6sentligt fra ActiveMQs tilgang. Kafka er bygget p\u00e5 horisontalt skalerbare klynger, hvor alle brokerinstanser modtager og distribuerer beskeder samtidigt.<\/p>\n<p>En Kafka-klynge best\u00e5r af flere brokerinstanser, der k\u00f8rer p\u00e5 forskellige servere. Kafka er designet til at arbejde p\u00e5 almindeligt autonomt hardware, hvor hver node har sit eget dedikerede lager. Anvendelse af netv\u00e6rkslager (SAN) frar\u00e5des, da flere beregningsnoder kan konkurrere om tidsintervallerne for lagring og skabe konflikter.<i>\u00c5<\/i>endet.<\/p>\n<p>Kafka er en <i>altid t\u00e6ndt<\/i> system. Mange store brugere af Kafka slukker aldrig for deres klynger, og softwaren sikrer altid opdatering ved sekventiel genstart. Dette opn\u00e5s ved at garantere bagudkompatibilitet for beskeder og interaktioner mellem brokers.<\/p>\n<p>Brokers er tilsluttet en klynge af servere <noindex><a rel=\"nofollow\" href=\"http:\/\/zookeeper.apache.org\">ZooKeeper<\/a><\/noindex>, som fungerer som en konfigurationsdatabse og bruges til at koordinere rollerne for hver broker. ZooKeeper selv er et distribueret system, der sikrer h\u00f8j tilg\u00e6ngelighed ved at replikere information ved at etablere <i>kvorum.<\/i>.<\/p>\n<p>I det grundl\u00e6ggende tilf\u00e6lde oprettes et emne i Kafka-klyngen med f\u00f8lgende egenskaber:<\/p>\n<ul>\n<li>Antallet af partitioner. Som n\u00e6vnt tidligere afh\u00e6nger den pr\u00e6cise v\u00e6rdi, der anvendes her, af det \u00f8nskede niveau for parallel l\u00e6sning.<\/li>\n<li>Replikationsfaktoren bestemmer, hvor mange brokerinstanser i klyngen der skal indeholde logfiler for denne partition.<\/li>\n<\/ul>\n<p>\nVed at bruge ZooKeeper til koordinering fors\u00f8ger Kafka at fordele nye partitioner retf\u00e6rdigt mellem brokers i klyngen. Dette g\u00f8res af \u00e9n instans, der fungerer som Controller.<\/p>\n<p>I runtime <i>tildeler hver partition af emnet<\/i> <i>Controller <\/i>brokerne roller som <i>leder <\/i>(leader, master, f\u00f8rende) og <i>medarbejdere. <\/i>(f\u00f8lgere, slaver, tilh\u00e6ngere). En broker, der fungerer som leder for den p\u00e5g\u00e6ldende partition, er ansvarlig for at modtage alle meddelelser sendt til ham af producenterne og for at distribuere meddelelserne til forbrugerne. N\u00e5r meddelelser sendes til partitionen af emnet, bliver de replikeret p\u00e5 alle broker-noder, der fungerer som f\u00f8lgere for denne partition. Hver node, der indeholder logs for partitionen, kaldes <i>en replika<\/i>. En broker kan fungere som leder for nogle partitioner og som f\u00f8lger for andre.<\/p>\n<p>En f\u00f8lger, der holder alle meddelelser gemt hos lederen, kaldes <i>en synkroniseret replika<\/i> (. replika, der er i synkroniseret tilstand, in-sync replica). Hvis broker, der fungerer som leder for partitionen, lukker ned, kan enhver broker, der er i \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c eller synkroniseret tilstand for denne partition, tage rollen som leder. Dette er et utroligt robust design.<\/p>\n<p>En del af konfigurationen for producenten er parameteren <i>acks<\/i>, som bestemmer, hvor mange replikaer der skal bekr\u00e6fte (acknowledge) modtagelsen af en meddelelse, f\u00f8r applikationsstr\u00f8mmen forts\u00e6tter med at sende: 0, 1 eller alle. Hvis v\u00e6rdien angives til <i>alle<\/i>, s\u00e5 vil lederen sende en bekr\u00e6ftelse (confirmation) tilbage til producenten, s\u00e5 snart han modtager bekr\u00e6ftelser (acknowledgements) for optegnelsen fra flere replikaer (inklusive sig selv), som er specificeret af topic-indstillingen <i>min.insync.replicas<\/i> (som standard 1). Hvis meddelelsen ikke kan replikeres med succes, vil producenten udl\u00f8se en undtagelse for applikationen (<i>NotEnoughReplicas<\/i> eller <i>NotEnoughReplicasAfterAppend<\/i>).<\/p>\n<p>I en typisk konfiguration oprettes der et emne med en replikeringsfaktor p\u00e5 3 (1 leder, 2 f\u00f8lgere for hver partition) og parameteren <i>min.insync.replicas<\/i> s\u00e6ttes til 2. I dette tilf\u00e6lde vil klustret tillade, at en af brokerne, der varetager partitionen af emnet, kan lukke ned uden at p\u00e5virke klientapplikationer.<\/p>\n<p>Det bringer os tilbage til det allerede velkendte kompromis mellem ydeevne og p\u00e5lidelighed. Replikering sker p\u00e5 bekostning af ekstra ventetid til bekr\u00e6ftelser (acknowledgments) fra f\u00f8lgerne. Selvom, da det udf\u00f8res parallelt, har replikering, som minimum p\u00e5 tre noder, samme ydeevne som p\u00e5 to (ignorerer den \u00f8gede brug af netv\u00e6rksb\u00e5ndbredde).<\/p>\n<p>Ved at bruge dette replikationsskema undg\u00e5r Kafka elegant behovet for at sikre fysisk optegnelse af hver besked p\u00e5 disk via operationen <i>sync ()<\/i>. Hver besked sendt af producenter vil blive opf\u00f8rt i partitionsjournalen, men som diskuteret i Kapitel 2, udf\u00f8res den indledende optegnelse i en fil i operativsystemets buffer. Hvis denne besked er blevet replikeret til en anden Kafka-instans og ligger i dens hukommelse, betyder tabet af lederen ikke, at selve beskeden er g\u00e5et tabt \u2014 en synkroniseret replika kan tage over.<br \/>\nAt give afkald p\u00e5 behovet for at udf\u00f8re operationen <i>sync ()<\/i> betyder, at Kafka kan modtage beskeder i det tempo, den kan optage dem i hukommelsen. Omvendt, jo l\u00e6ngere man kan undg\u00e5 at spole (flushing) hukommelsen til disk, desto bedre. Af denne grund er det ikke us\u00e6dvanligt, at Kafka-brokere tildeles 64 GB hukommelse eller mere. Denne hukommelsesbrug betyder, at \u00e9n Kafka-instans let kan operere med hastigheder, der er mange tusinde gange hurtigere end traditionelle meddelelsesbrokere.<\/p>\n<p>Kafka kan ogs\u00e5 konfigureres til at anvende operationen <i>sync ()<\/i> p\u00e5 beskedpakker. Da alt i Kafka er designet til at arbejde med pakker, fungerer dette faktisk ganske godt for mange anvendelsesscenarier og er et nyttigt v\u00e6rkt\u00f8j for brugere, der kr\u00e6ver meget st\u00e6rke garantier. Meget af Kafkas rene ydeevne er relateret til de beskeder, der sendes til brokeren i form af pakker, og til hvordan disse beskeder l\u00e6ses fra brokeren i sekventielle blokke ved hj\u00e6lp af <noindex><a rel=\"nofollow\" href=\"http:\/\/www.linuxjournal.com\/article\/6345\">zero-copy<\/a><\/noindex> operationer (operationer, hvor der ikke udf\u00f8res dataoverf\u00f8rsel fra \u00e9t hukommelsesomr\u00e5de til et andet). Det sidstn\u00e6vnte er en stor fordel med hensyn til ydeevne og ressourcer og er kun muligt takket v\u00e6re den underliggende datalogstruktur, der definerer partitionsskemaet.<\/p>\n<p>I et Kafka-kluster er det muligt at opn\u00e5 meget h\u00f8jere ydeevne end ved brug af \u00e9n Kafka-broker, da emnets partitioner kan skaleres horisontalt p\u00e5 mange separate maskiner.<\/p>\n<h2>Resum\u00e9<\/h2>\n<p>\nI dette kapitel har vi set p\u00e5, hvordan Kafka-arkitekturen genovervejer forholdet mellem klienter og broker for at sikre en utrolig robust messaging pipeline med en kapacitet, der er mange gange st\u00f8rre end en almindelig message broker. Vi har diskuteret den funktionalitet, den bruger for at n\u00e5 dette m\u00e5l, og kort ber\u00f8rt arkitekturen af de applikationer, der muligg\u00f8r denne funktionalitet. I det n\u00e6ste kapitel vil vi se p\u00e5 de generelle udfordringer, som messaging-baserede applikationer skal tackle, og diskutere strategier til at l\u00f8se dem. Vi afslutter kapitlet med at skitsere, hvordan man skal t\u00e6nke p\u00e5 messaging-teknologier generelt, s\u00e5 du kan vurdere deres egnethed til dine brugsscenarier.<\/p>\n<p>Den tidligere oversatte del: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">Forst\u00e5else af meddelelsesbrokere. Studere mekanikken bag meddelelsesudveksling gennem ActiveMQ og Kafka. Kapitel 1<\/a><\/noindex><\/p>\n<p><b> Overs\u00e6ttelsen er udf\u00f8rt: <noindex><a rel=\"nofollow\" href=\"http:\/\/tele.gg\/middle_java\">tele.gg\/middle_java<\/a><\/noindex><\/b><\/p>\n<p><i>Forts\u00e6ttelsen f\u00f8lger\u2026<\/i><\/p>\n<p class=\"for_users_only_msg\">Kun registrerede brugere kan deltage i unders\u00f8gelsen. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Log ind<\/a><\/noindex>, please.<\/p>\n<h2 class=\"default-block__polling-title\">Bruger din organisation Kafka?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Ja<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Nej<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Tidligere brugt, nu ikke l\u00e6ngere<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Planl\u00e6gger at bruge<\/p>\n<\/li>\n<\/ul>\n<p>    38 brugere har stemt. 8 brugere har undladt at stemme.<br \/>\n<br \/>Kilde: <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 5.0.3 - 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.\" \/>\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\/da\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\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.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/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\udd47Forst\u00e5else af message brokers. Unders\u00f8gelse af mekanikken i messaging gennem ActiveMQ og Kafka. Kapitel 3. Kafka | ProHoster","description":"Forts\u00e6ttelsen af overs\u00e6ttelsen af en lille bog: \u00abUnderstanding Message Brokers\u00bb, forfatter: Jakub Korab, udgiver: O'Reilly Media, Inc., udgivelsesdato: juni 2017, ISBN: 9781492049296. Den tidligere overs\u00e6ttelse.","canonical_url":"https:\/\/prohoster.info\/da\/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":"da_DK","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.","og:url":"https:\/\/prohoster.info\/da\/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","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/38172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=38172"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/38172\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=38172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=38172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=38172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}