{"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\/sv\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka","title":{"rendered":"F\u00f6rst\u00e5else f\u00f6r meddelandebrokers. En studie av meddelandeutbytet genom ActiveMQ och Kafka. Kapitel 3. Kafka","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Forts\u00e4ttning p\u00e5 \u00f6vers\u00e4ttningen av en liten bok:<br \/>\n\u00abUnderstanding Message Brokers\u00bb<br \/>\nf\u00f6rfattare: Jakub Korab, f\u00f6rlag: O'Reilly Media, Inc., utgivningsdatum: juni 2017, ISBN: 9781492049296.<\/p>\n<p>Tidigare \u00f6versatt del: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">F\u00f6rst\u00e5else av meddelandebrokers. En studie av meddelandeutbyte genom ActiveMQ och Kafka. Kapitel 1. Inledning<\/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 utvecklades av LinkedIn f\u00f6r att kringg\u00e5 vissa begr\u00e4nsningar hos traditionella meddelandebrokers och f\u00f6r att undvika behovet av att konfigurera flera meddelandebrokers f\u00f6r olika \"punkt-till-punkt\"-interaktioner, vilket beskrivs i denna bok i avsnittet om \"Vertikal och horisontell skalning\" p\u00e5 sida 28. Anv\u00e4ndningsscenarierna p\u00e5 LinkedIn baserades huvudsakligen p\u00e5 ensidig insamling av mycket stora datam\u00e4ngder, s\u00e5som klick p\u00e5 sidor och \u00e5tkomstloggar, samtidigt som dessa data till\u00e4t anv\u00e4ndning av flera system utan att p\u00e5verka prestandan hos producenter eller andra konsumenter. Faktum \u00e4r att anledningen till att Kafka existerar \u00e4r f\u00f6r att uppn\u00e5 den meddelandeutbytesarkitektur som beskrivs i Universal Data Pipeline.<\/p>\n<p>Med detta slutm\u00e5l i \u00e5tanke uppstod naturligtvis andra krav. Kafka m\u00e5ste:<\/p>\n<ul>\n<li>Var extremt snabb<\/li>\n<li>Erbjuda h\u00f6g kapacitet vid meddelandehantering<\/li>\n<li>St\u00f6tta 'Utgivare-Prenumerant'- och 'Punkt-Punkt'-modeller<\/li>\n<li>Inte saktas ner vid till\u00e4gg av konsumenter. Till exempel, prestandan f\u00f6r b\u00e5de k\u00f6er och \u00e4mnen i ActiveMQ f\u00f6rs\u00e4mras med \u00f6kat antal konsumenter p\u00e5 mottagarens sida<\/li>\n<li>Vara horisontellt skalbar; om en broker som lagrar (persisterar) meddelanden kan g\u00f6ra detta endast i maximal hastighet f\u00f6r disken, \u00e4r det meningsfullt att g\u00e5 bortom en enda brokerinstans f\u00f6r att \u00f6ka kapaciteten<\/li>\n<li>Avgr\u00e4nsa \u00e5tkomst till lagring och \u00e5tervinning av meddelanden<\/li>\n<\/ul>\n<p>\nF\u00f6r att uppn\u00e5 allt detta har Kafka antagit en arkitektur som omdefinierar rollerna och ansvaret f\u00f6r klienter och meddelandebrokers. JMS-modellen \u00e4r mycket inriktad p\u00e5 brokern, d\u00e4r denna ansvarar f\u00f6r distributionen av meddelanden, och klienterna beh\u00f6ver bara oroa sig f\u00f6r att skicka och ta emot meddelanden. Kafka, \u00e5 sin sida, \u00e4r klientcentrerad, d\u00e4r klienten tar p\u00e5 sig m\u00e5nga av de traditionella broker-funktionerna, s\u00e5som r\u00e4ttvis f\u00f6rdelning av relevanta meddelanden bland konsumenter, i utbyte mot att f\u00e5 en extremt snabb och skalbar broker. F\u00f6r m\u00e4nniskor som har arbetat med traditionella meddelandesystem kr\u00e4ver arbete med Kafka fundamentala f\u00f6r\u00e4ndringar i syns\u00e4ttet.<br \/>\nDenna ingenj\u00f6rsm\u00e4ssig inriktning har lett till skapandet av en meddelandeinfrastruktur som kan \u00f6ka genomstr\u00f6mningen med flera storleksordningar j\u00e4mf\u00f6rt med en vanlig broker. Som vi kommer att se medf\u00f6r detta tillv\u00e4gag\u00e5ngss\u00e4tt kompromisser som inneb\u00e4r att Kafka inte \u00e4r l\u00e4mplig f\u00f6r vissa typer av belastningar och installerad programvara.<\/p>\n<h3>Enhetlig mottagarmodell<\/h3>\n<p>\nF\u00f6r att uppfylla kraven som n\u00e4mnts ovan har Kafka kombinerat meddelandetyperna 'publikation-prenumeration' och 'punkt-till-punkt' inom en enda typ av mottagare - <i>\u00e4mnet<\/i>. Detta kan f\u00f6rvirra personer som har arbetat med meddelandesystem d\u00e4r termen '\u00e4mne' h\u00e4nvisar till en s\u00e4ndlistemechanism, fr\u00e5n vilken (fr\u00e5n \u00e4mnet) l\u00e4sning inte \u00e4r p\u00e5litlig (\u00e4r icke-varaktig). Kafka-\u00e4mnen b\u00f6r betraktas som en hybridtyp av mottagare, i enlighet med den definition som ges i inledningen till denna bok.<\/p>\n<blockquote><p>I resten av detta kapitel, om vi inte uttryckligen anger annat, kommer termen \"\u00e4mne\" att h\u00e4nvisa till Kafka-\u00e4mnet.<\/p><\/blockquote>\n<p>\nF\u00f6r att helt f\u00f6rst\u00e5 hur \u00e4mnen fungerar och vilka garantier de erbjuder, m\u00e5ste vi f\u00f6rst titta p\u00e5 hur de \u00e4r implementerade i Kafka.<br \/>\n<i>Varje \u00e4mne i Kafka har sin egen logg.<\/i><br \/>\nProducenter som skickar meddelanden till Kafka skriver till denna logg, medan konsumenter l\u00e4ser fr\u00e5n loggen med hj\u00e4lp av pekare som st\u00e4ndigt flyttas fram\u00e5t. Med j\u00e4mna mellanrum tar Kafka bort de \u00e4ldsta delarna av loggen, oavsett om meddelandena i dessa delar har l\u00e4sts eller inte. En central aspekt av Kafka-designen \u00e4r att brokern inte bryr sig om meddelandena har l\u00e4sts eller inte \u2014 det \u00e4r klientens ansvar.<\/p>\n<blockquote><p>Termerna \"logg\" och \"pekare\" f\u00f6rekommer inte i <noindex><a rel=\"nofollow\" href=\"https:\/\/kafka.apache.org\/documentation.html\">dokumentationen f\u00f6r Kafka<\/a><\/noindex>. Dessa v\u00e4lk\u00e4nda termer anv\u00e4nds h\u00e4r f\u00f6r att underl\u00e4tta f\u00f6rst\u00e5elsen.<\/p><\/blockquote>\n<p>\nDenna modell skiljer sig helt fr\u00e5n ActiveMQ, d\u00e4r meddelanden fr\u00e5n alla k\u00f6er lagras i en enda logg, och brokern markerar meddelanden som raderade efter att de har l\u00e4sts.<br \/>\nL\u00e5t oss nu dyka djupare ner och titta n\u00e4rmare p\u00e5 \u00e4mnets logg.<br \/>\nKafka-loggen best\u00e5r av flera partitioner (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/tm\/w2\/yf\/tmw2yf3lanppqtrumxoidotplhi.png\">Figur 3-1<\/a><\/noindex>). Kafka garanterar strikt ordning i varje partition. Det inneb\u00e4r att meddelanden som skrivs till en partition i en viss ordning kommer att l\u00e4sas i samma ordning. Varje partition implementeras som en cyklisk (rolling) loggfil som inneh\u00e5ller <i>ett delm\u00e4ngd <\/i>(subset) av alla meddelanden som skickats till \u00e4mnet av dess producenter. Det skapade \u00e4mnet inneh\u00e5ller som standard en partition. Id\u00e9n med partitioner \u00e4r en central id\u00e9 f\u00f6r Kafka f\u00f6r horisontell skalning.<\/p>\n<p><img decoding=\"async\" alt=\"F\u00f6rst\u00e5else f\u00f6r meddelandebrokers. En studie av meddelandeutbytet genom ActiveMQ och 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\u00e4r en producent skickar ett meddelande till ett Kafka-\u00e4mne best\u00e4mmer han vilken partition som meddelandet ska skickas till. Vi kommer att titta n\u00e4rmare p\u00e5 detta senare.<\/p>\n<h2>L\u00e4sa meddelanden<\/h2>\n<p>\nEn klient som vill l\u00e4sa meddelanden hanterar en namngiven pekare som kallas <i>konsumentgrupp (consumer group)<\/i>, som pekar p\u00e5 <i>offset<\/i> f\u00f6r meddelandet i partitionen. Offset \u00e4r en position med ett v\u00e4xande nummer som b\u00f6rjar vid 0 i b\u00f6rjan av partitionen. Denna konsumentgrupp, som refereras till i API:et via en anv\u00e4ndardefinierad identifierare group_id, motsvarar <i>en logisk konsument eller system<\/i>.<\/p>\n<p>De flesta system som anv\u00e4nder meddelandeutbyte l\u00e4ser data fr\u00e5n mottagaren genom flera instanser och fl\u00f6den f\u00f6r parallell meddelandehantering. P\u00e5 s\u00e5 s\u00e4tt kommer det vanligtvis finnas m\u00e5nga instanser av konsumenter som delar en och samma konsumentgrupp.<\/p>\n<p>Problemet med l\u00e4sning kan beskrivas p\u00e5 f\u00f6ljande s\u00e4tt:<\/p>\n<ul>\n<li>\u00c4mnet har flera partitioner<\/li>\n<li>Flera konsumentgrupper kan anv\u00e4nda \u00e4mnet samtidigt<\/li>\n<li>En konsumentgrupp kan ha flera separata instanser<\/li>\n<\/ul>\n<p>\nDetta \u00e4r ett icke-trivialt problem av \"m\u00e5nga till m\u00e5nga\". F\u00f6r att f\u00f6rst\u00e5 hur Kafka hanterar relationerna mellan konsumentgrupper, konsumentinstanser och partitioner, l\u00e5t oss \u00f6verv\u00e4ga en serie gradvis mer komplexa l\u00e4sningsscenarier.<\/p>\n<h3>Konsumenter och konsumentgrupper<\/h3>\n<p>\nL\u00e5t oss ta som utg\u00e5ngspunkt ett \u00e4mne med en partition (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/6z\/tz\/dh\/6ztzdhqmjweck-z15htxb2xbe28.png\">Figure 3-2<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"F\u00f6rst\u00e5else f\u00f6r meddelandebrokers. En studie av meddelandeutbytet genom ActiveMQ och Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/46c92e6bd38774dfef3be4bd198bf35d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figure 3-2. Konsumenten l\u00e4ser fr\u00e5n partitionen<\/i><\/p>\n<p>N\u00e4r en instans av konsumenten ansluter med sitt eget group_id till detta \u00e4mne tilldelas den en partition f\u00f6r l\u00e4sning och en offset i denna partition. Positionen f\u00f6r denna offset konfigureras i klienten, som en pekare till den senaste positionen (det nyaste meddelandet) eller den tidigaste positionen (det \u00e4ldsta meddelandet). Konsumenten beg\u00e4r (polls) meddelanden fr\u00e5n \u00e4mnet, vilket leder till sekventiell l\u00e4sning fr\u00e5n loggen.<br \/>\nOffsetpositionen kommitteras regelbundet tillbaka till Kafka och sparas som meddelanden i den interna \u00e4mnet <i>_consumer_offsets<\/i>. De l\u00e4sta meddelandena raderas inte, till skillnad fr\u00e5n en vanlig broker, och klienten kan spola tillbaka (rewind) offseten f\u00f6r att bearbeta redan visade meddelanden igen.<\/p>\n<p>N\u00e4r en andra logisk konsument ansluter, med en annan group_id, hanterar den en andra pekare som inte \u00e4r beroende av den f\u00f6rsta (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/qe\/v1\/yk\/qev1yktga3s-g1gqlynylbe3n9w.png\">Figure 3-3<\/a><\/noindex>). P\u00e5 s\u00e5 s\u00e4tt fungerar Kafka-\u00e4mnet som en k\u00f6, d\u00e4r det finns en konsument och, som ett vanligt pub-sub-\u00e4mne, d\u00e4r flera konsumenter \u00e4r prenumererade, med den extra f\u00f6rdelen att alla meddelanden sparas och kan bearbetas flera g\u00e5nger.<\/p>\n<p><img decoding=\"async\" alt=\"F\u00f6rst\u00e5else f\u00f6r meddelandebrokers. En studie av meddelandeutbytet genom ActiveMQ och Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/e9e8b9063ef7367005254d36abb47f4f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figure 3-3. Tv\u00e5 konsumenter i olika konsumentgrupper l\u00e4ser fr\u00e5n en partition<\/i><\/p>\n<h3>Konsumenter i konsumentgruppen<\/h3>\n<p>\nN\u00e4r en instans av en konsument l\u00e4ser data fr\u00e5n en partition kontrollerar den helt pekaren och behandlar meddelandena som beskrivs i f\u00f6reg\u00e5ende avsnitt.<br \/>\nOm flera instanser av konsumenter har anslutits med samma group_id till en topic med en partition, kommer den instans som ansl\u00f6t sig sist att f\u00e5 kontroll \u00f6ver pekaren och fr\u00e5n och med nu ta emot alla meddelanden (<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=\"F\u00f6rst\u00e5else f\u00f6r meddelandebrokers. En studie av meddelandeutbytet genom ActiveMQ och Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/ec6af819445dad4028f65449a735ae22.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figur 3-4. Tv\u00e5 konsumenter i samma konsumentgrupp l\u00e4ser fr\u00e5n en partition<\/i><\/p>\n<p>Denna bearbetningsl\u00e4ge, d\u00e4r antalet konsumentinstanser \u00f6verstiger antalet partitioner, kan ses som en typ av monopolistisk konsumtion. Detta kan vara anv\u00e4ndbart om du beh\u00f6ver en \"aktiv-passiv\" (eller \"het-varm\") klusterbildning av dina konsumentinstanser, \u00e4ven om parallell drift av flera konsumenter (\"aktiv-aktiv\" eller \"het-het\") \u00e4r mycket mer typiskt \u00e4n inaktiva konsumenter.<\/p>\n<blockquote><p>S\u00e5dant meddelandef\u00f6rdelande beteende, som beskrivits ovan, kan verka f\u00f6rv\u00e5nande i j\u00e4mf\u00f6relse med hur en typisk JMS-k\u00f6 beter sig. I den h\u00e4r modellen kommer meddelanden som skickas till k\u00f6er att f\u00f6rdelas j\u00e4mnt mellan tv\u00e5 konsumenter.<\/p><\/blockquote>\n<p>\nMest vanligt n\u00e4r vi skapar flera instanser av konsumenter g\u00f6r vi det antingen f\u00f6r parallell bearbetning av meddelanden, f\u00f6r att \u00f6ka l\u00e4shastigheten, eller f\u00f6r att \u00f6ka l\u00e4sningssystemets motst\u00e5ndskraft. Eftersom endast en instans av en konsument kan l\u00e4sa data fr\u00e5n en partition samtidigt, hur uppn\u00e5s detta i Kafka?<\/p>\n<p>Ett s\u00e4tt att g\u00f6ra detta \u00e4r att anv\u00e4nda en instans av en konsument f\u00f6r att l\u00e4sa alla meddelanden och vidarebefordra dem till en tr\u00e5dpool. \u00c4ven om denna metod \u00f6kar bearbetningens genomstr\u00f6mning, \u00f6kar den logikens komplexitet f\u00f6r konsumenterna och g\u00f6r inget f\u00f6r att \u00f6ka systemets l\u00e4sresiliens. Om en instans av konsumenten st\u00e4ngs av p\u00e5 grund av str\u00f6mavbrott eller en liknande h\u00e4ndelse, stoppas l\u00e4sningen.<\/p>\n<p>Det kanoniska s\u00e4ttet att l\u00f6sa detta problem i Kafka \u00e4r att anv\u00e4nda fler partitioner.<i>Till<\/i>flera partitioner.<\/p>\n<h3>Partitionering<\/h3>\n<p>\nPartitioner \u00e4r den huvudsakliga mekanismen f\u00f6r att parallellisera l\u00e4sningen och skala \u00e4mnen ut\u00f6ver kapaciteten hos en enda brokerinstans. F\u00f6r att b\u00e4ttre f\u00f6rst\u00e5 detta, l\u00e5t oss \u00f6verv\u00e4ga ett scenario d\u00e4r det finns ett \u00e4mne med tv\u00e5 partitioner och en konsument prenumererar p\u00e5 detta \u00e4mne (<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=\"F\u00f6rst\u00e5else f\u00f6r meddelandebrokers. En studie av meddelandeutbytet genom ActiveMQ och 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 konsument l\u00e4ser fr\u00e5n flera partitioner<\/i><\/p>\n<p>I detta scenario f\u00e5r konsumenten kontroll \u00f6ver pekarna som motsvarar hans group_id i b\u00e5da partitionerna och b\u00f6rjar l\u00e4sa meddelanden fr\u00e5n b\u00e5da partitionerna.<br \/>\nN\u00e4r en extra konsument l\u00e4ggs till f\u00f6r samma group_id, omf\u00f6rdelar Kafka (reallocates) en av partitionerna fr\u00e5n den f\u00f6rsta till den andra konsumenten. D\u00e4refter kommer varje konsumentinstans att l\u00e4sa fr\u00e5n en partition av \u00e4mnet (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/8b\/a0\/um\/8ba0umn2yzr9yy3vztonhdfiub0.png\">Figur 3-6<\/a><\/noindex>).<\/p>\n<p>F\u00f6r att m\u00f6jligg\u00f6ra bearbetning av meddelanden parallellt i 20 tr\u00e5dar beh\u00f6ver du minst 20 partitioner. Om det finns f\u00e4rre partitioner kommer du att ha konsumenter som inte har n\u00e5got att arbeta med, vilket tidigare beskrevs i diskussionen om monopolkonsumenter.<\/p>\n<p><img decoding=\"async\" alt=\"F\u00f6rst\u00e5else f\u00f6r meddelandebrokers. En studie av meddelandeutbytet genom ActiveMQ och Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/a3c4001e4a5b92d53b6f529b2633254a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Figur 3-6. Tv\u00e5 konsumenter i samma konsumentgrupp l\u00e4ser fr\u00e5n olika partitioner<\/i><\/p>\n<p>Detta schema minskar avsev\u00e4rt komplexiteten i hur Kafka-brokern arbetar j\u00e4mf\u00f6rt med den meddelandef\u00f6rdelning som kr\u00e4vs f\u00f6r att st\u00f6dja JMS-k\u00f6er. H\u00e4r beh\u00f6ver man inte bekymra sig om f\u00f6ljande punkter:<\/p>\n<ul>\n<li>Vilken konsument som ska f\u00e5 n\u00e4sta meddelande baserat p\u00e5 rund-robin-f\u00f6rdelning, nuvarande kapacitet hos buffertarna f\u00f6r f\u00f6rhandsupph\u00e4mtning eller tidigare meddelanden (som f\u00f6r JMS meddelandegrupper).<\/li>\n<li>Vilka meddelanden som har skickats till vilka konsumenter och om de ska levereras igen i h\u00e4ndelse av ett fel.<\/li>\n<\/ul>\n<p>\nAllt som broker Kafka beh\u00f6ver g\u00f6ra \u00e4r att konsekvent \u00f6verf\u00f6ra meddelanden till konsumenten n\u00e4r den senare beg\u00e4r dem.<\/p>\n<p>Dock f\u00f6rsvinner inte kraven p\u00e5 parallell l\u00e4sning och omleverans av misslyckade meddelanden \u2014 ansvaret f\u00f6r dessa \u00f6verg\u00e5r bara fr\u00e5n brokern till klienten. Detta inneb\u00e4r att de beh\u00f6ver beaktas i din kod.<\/p>\n<h2>Skicka meddelanden<\/h2>\n<p>\nAnsvarsfr\u00e5gan f\u00f6r beslutet om vilken partition ett meddelande ska skickas till faller p\u00e5 producenten av det meddelandet. F\u00f6r att f\u00f6rst\u00e5 den mekanism som detta g\u00f6rs med, beh\u00f6ver vi f\u00f6rst titta p\u00e5 vad vi faktiskt skickar.<\/p>\n<p>Medan vi i JMS anv\u00e4nder en meddelandestruktur med metadata (huvuden och egenskaper) och en kropp som inneh\u00e5ller nyttolasten (payload), \u00e4r meddelandet i Kafka <i>ett par \"nyckel-v\u00e4rde\"<\/i>. Nyttolasten av meddelandet skickas som v\u00e4rde (value). Nyckeln anv\u00e4nds \u00e5 sin sida fr\u00e4mst f\u00f6r partitionering och b\u00f6r inneh\u00e5lla <i>en nyckel specifik f\u00f6r aff\u00e4rslogiken<\/i>, f\u00f6r att placera relaterade meddelanden i samma partition.<\/p>\n<p>I kapitel 2 diskuterade vi scenariot med online-betting n\u00e4r relaterade h\u00e4ndelser m\u00e5ste bearbetas i ordning av en konsument:<\/p>\n<ol>\n<li>Anv\u00e4ndarkontot \u00e4r inst\u00e4llt.<\/li>\n<li>Pengarna s\u00e4tts in p\u00e5 kontot.<\/li>\n<li>En insats g\u00f6rs, vilket drar pengar fr\u00e5n kontot.<\/li>\n<\/ol>\n<p>\nOm varje h\u00e4ndelse representerar ett meddelande som skickas till en topic, skulle den naturliga nyckeln i detta fall vara kontots identifierare.<br \/>\nN\u00e4r ett meddelande skickas med Kafka Producer API, \u00f6verl\u00e4mnas det till partitioneringsfunktionen, som, med h\u00e4nsyn till meddelandet och det aktuella tillst\u00e5ndet i Kafka-klustret, returnerar identifieraren f\u00f6r den partition d\u00e4r meddelandet ska skickas. Denna funktion implementeras i Java genom gr\u00e4nssnittet Partitioner.<\/p>\n<p>Detta gr\u00e4nssnitt ser ut som f\u00f6ljer:<\/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 av Partitioner f\u00f6r att best\u00e4mma partitionen anv\u00e4nder standardalgoritmen f\u00f6r nyckelhackning (general-purpose hashing algorithm over the key) eller rond-robin, om nyckeln inte anges. Detta standardv\u00e4rde fungerar bra i de flesta fall. Men i framtiden kanske du vill skriva din egen.<\/p>\n<h3>Skriva en egen partitioneringsstrategi<\/h3>\n<p>\nL\u00e5t oss \u00f6verv\u00e4ga ett exempel d\u00e4r du vill skicka metadata tillsammans med nyttolasten av meddelandet. Nyttolasten i v\u00e5rt exempel \u00e4r en instruktion f\u00f6r att s\u00e4tta in pengar p\u00e5 spelkontot. Instruktionen \u00e4r n\u00e5got som vi vill garantera att inte modifieras vid \u00f6verf\u00f6ring och vi vill vara s\u00e4kra p\u00e5 att endast ett betrott \u00f6verordnat system kan initiera denna instruktion. I detta fall \u00f6verenskommer s\u00e4ndande och mottagande system om att anv\u00e4nda en signatur f\u00f6r att verifiera meddelandets \u00e4kthet.<br \/>\nI ett vanligt JMS definierar vi helt enkelt egenskapen \"meddelandesignatur\" och l\u00e4gger till den i meddelandet. D\u00e4remot tillhandah\u00e5ller Kafka ingen mekanism f\u00f6r att skicka metadata \u2014 endast nyckel och v\u00e4rde.<\/p>\n<p>Eftersom v\u00e4rdet \u00e4r nyttolasten f\u00f6r en bank\u00f6verf\u00f6ring (bank transfer payload), vars integritet vi vill bevara, har vi inget annat val \u00e4n att definiera datakonstruktionen som ska anv\u00e4ndas i nyckeln. F\u00f6rutsatt att vi beh\u00f6ver ett konto-ID f\u00f6r partionering, eftersom alla meddelanden som r\u00f6r kontot m\u00e5ste behandlas i ordning, kommer vi att konstruera f\u00f6ljande JSON-struktur:<\/p>\n<pre><code class=\"json\">{\n  \"signature\": \"541661622185851c248b41bf0cea7ad0\",\n  \"accountId\": \"10007865234\"\n}<\/code><\/pre>\n<p>\nEftersom v\u00e4rdet av signaturen kommer att variera beroende p\u00e5 nyttolasten, kommer standardhashningsstrategin f\u00f6r Partitioner-gr\u00e4nssnittet inte att p\u00e5 ett tillf\u00f6rlitligt s\u00e4tt gruppera relaterade meddelanden. D\u00e4rf\u00f6r beh\u00f6ver vi skriva en egen strategi som analyserar denna nyckel och partitionerar v\u00e4rdet av accountId.<\/p>\n<blockquote><p>Kafka inkluderar kontrollsummor f\u00f6r att uppt\u00e4cka skador p\u00e5 meddelanden i lagret och har en full upps\u00e4ttning s\u00e4kerhetsfunktioner. Trots detta dyker det ibland upp specifika branschkrav, som exemplifierat ovan.<\/p><\/blockquote>\n<p>\nDen anpassade partitioneringsstrategin m\u00e5ste garantera att alla relaterade meddelanden hamnar i samma partition. \u00c4ven om detta verkar enkelt kan kravet kompliceras av vikten av att ordna relaterade meddelanden och hur fast antal partitioner som finns i \u00e4mnet.<\/p>\n<p>Antalet partitioner i ett \u00e4mne kan f\u00f6r\u00e4ndras \u00f6ver tid, eftersom de kan l\u00e4ggas till om trafiken \u00f6verskrider de ursprungliga f\u00f6rv\u00e4ntningarna. D\u00e4rf\u00f6r kan meddelandenycklar vara kopplade till den partition som de ursprungligen skickades till, vilket implicerar en del av tillst\u00e5ndet som m\u00e5ste f\u00f6rdelas mellan producenter-instansarna.<\/p>\n<p>En annan faktor att ta h\u00e4nsyn till \u00e4r even distributionen av meddelanden mellan partitioner. Generellt f\u00f6rdelas nycklar inte j\u00e4mnt bland meddelandena, och hash-funktioner garanterar inte en r\u00e4ttvis f\u00f6rdelning av meddelanden f\u00f6r ett litet antal nycklar.<br \/>\nDet \u00e4r viktigt att notera att oavsett hur du v\u00e4ljer att dela meddelanden, kan avgr\u00e4nsaren beh\u00f6va anv\u00e4ndas om igen.<\/p>\n<p>L\u00e5t oss \u00f6verv\u00e4ga kravet p\u00e5 datareplication mellan Kafka-kluster p\u00e5 olika geografiska platser. F\u00f6r detta \u00e4ndam\u00e5l levereras Kafka med ett kommandoradsverktyg som heter MirrorMaker, vilket anv\u00e4nds f\u00f6r att l\u00e4sa meddelanden fr\u00e5n ett kluster och \u00f6verf\u00f6ra dem till ett annat.<\/p>\n<p>MirrorMaker m\u00e5ste f\u00f6rst\u00e5 nycklarna f\u00f6r det replikerade \u00e4mnet f\u00f6r att bibeh\u00e5lla ordningen mellan meddelanden vid replikering mellan kluster, eftersom antalet partitioner f\u00f6r detta \u00e4mne kan variera mellan de tv\u00e5 klustren.<\/p>\n<p>Anpassade partitioneringsstrategier f\u00f6rekommer relativt s\u00e4llan, eftersom de standardm\u00e4ssiga hash- eller cykelf\u00f6rdelningarna fungerar framg\u00e5ngsrikt i de flesta scenarier. Men om du beh\u00f6ver strikta garantier f\u00f6r ordning eller om du m\u00e5ste extrahera metadata fr\u00e5n nyttolaster, \u00e4r partitionering n\u00e5got du b\u00f6r titta n\u00e4rmare p\u00e5.<\/p>\n<p>F\u00f6rdelarna med Kafka:s skalbarhet och prestanda beror p\u00e5 att vissa uppgifter f\u00f6r en traditionell broker flyttas till klienten. I detta fall g\u00f6rs beslutet att f\u00f6rdela potentiellt relaterade meddelanden till flera konsumenter som arbetar parallellt.<\/p>\n<blockquote><p>JMS-brokers m\u00e5ste ocks\u00e5 hantera s\u00e5dana krav. Intressant nog kr\u00e4ver mekanismen f\u00f6r att skicka relaterade meddelanden till samma konsument, som realiseras genom JMS Message Groups (en typ av strategi f\u00f6r klibbig belastningsbalansering), att avs\u00e4ndaren markerar meddelanden som relaterade. I JMS:s fall ansvarar brokern f\u00f6r att skicka den gruppen av relaterade meddelanden till en konsument av flera och \u00f6verf\u00f6ra \u00e4gander\u00e4tten till gruppen om konsumenten avbryts.<\/p><\/blockquote>\n<p><\/p>\n<h2>\u00d6verenskommelser f\u00f6r producenter<\/h2>\n<p>\nPartionering \u00e4r inte det enda att t\u00e4nka p\u00e5 n\u00e4r man skickar meddelanden. L\u00e5t oss titta p\u00e5 metoderna 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 b\u00f6r noteras att b\u00e5da metoderna returnerar Future, vilket indikerar att s\u00e4ndningsoperationen inte utf\u00f6rs omedelbart. Resultatet blir att meddelandet (ProducerRecord) skrivs till s\u00e4ndningsbufferten f\u00f6r varje aktiv partition och \u00f6verf\u00f6rs till m\u00e4klaren av en bakgrundstr\u00e5d i Kafka-klientbiblioteket. \u00c4ven om detta g\u00f6r arbetet otroligt snabbt, betyder det att ett oprofessionellt skrivet program kan f\u00f6rlora meddelanden om dess process stoppas.<\/p>\n<p>Som alltid finns det ett s\u00e4tt att g\u00f6ra s\u00e4ndningsoperationen mer p\u00e5litlig genom att kompromissa med prestandan. Storleken p\u00e5 denna buffert kan st\u00e4llas in till 0, vilket tvingar s\u00e4ndande applikationsstr\u00f6m att v\u00e4nta tills \u00f6verf\u00f6ringen av meddelandet till m\u00e4klaren \u00e4r slutf\u00f6rd, p\u00e5 f\u00f6ljande s\u00e4tt:<\/p>\n<pre><code class=\"java\">RecordMetadata metadata = producer.send(record).get();<\/code><\/pre>\n<p><\/p>\n<h2>Mer om att l\u00e4sa meddelanden<\/h2>\n<p>\nAtt l\u00e4sa meddelanden har ytterligare utmaningar som \u00e4r v\u00e4rda att \u00f6verv\u00e4ga. Till skillnad fr\u00e5n JMS API, som kan starta en meddelandelistor (message listener) som svar p\u00e5 inkommande meddelanden, s\u00e5 anv\u00e4nder gr\u00e4nssnittet <i>Consumer <\/i>Kafka anv\u00e4nder endast polling. L\u00e5t oss titta n\u00e4rmare p\u00e5 metoden <i>poll ()<\/i>, som anv\u00e4nds f\u00f6r detta \u00e4ndam\u00e5l:<\/p>\n<pre><code class=\"java\">ConsumerRecords  poll(long timeout);<\/code><\/pre>\n<p>\nReturv\u00e4rdet av metoden \u00e4r en beh\u00e5llarstruktur som inneh\u00e5ller flera objekt <i>ConsumerRecord <\/i>fr\u00e5n potentiellt flera partitioner. <i>ConsumerRecord <\/i>\u00e4r sj\u00e4lv en objektbeh\u00e5llare f\u00f6r ett nyckel-v\u00e4rde-par med motsvarande metadata, s\u00e5som partitionen det har h\u00e4mtats fr\u00e5n.<\/p>\n<p>Som diskuterades i kapitel 2 m\u00e5ste vi st\u00e4ndigt h\u00e5lla i \u00e5tanke vad som h\u00e4nder med meddelandena efter att de har har hanterats framg\u00e5ngsrikt eller misslyckats, till exempel om klienten inte kan bearbeta meddelandet eller om den kraschar. I JMS hanterades detta genom bekr\u00e4ftelsel\u00e4ge (acknowledgement mode). M\u00e4klaren tar antingen bort det framg\u00e5ngsrikt hanterade meddelandet eller omdistribuerar det ohanterade eller misslyckade (under f\u00f6ruts\u00e4ttning att transaktioner har anv\u00e4nts). <br \/>\nKafka fungerar helt annorlunda. Meddelanden tas inte bort fr\u00e5n m\u00e4klaren efter att de har l\u00e4sts och ansvaret f\u00f6r vad som h\u00e4nder vid ett fel ligger p\u00e5 den l\u00e4sande koden.<\/p>\n<p>Som vi redan har n\u00e4mnt \u00e4r en konsumentgrupp kopplad till en f\u00f6rskjutning i loggen. Positionen i loggen kopplad till denna f\u00f6rskjutning motsvarar n\u00e4sta meddelande som kommer att ges som svar. <i>poll ()<\/i>Tidpunkten n\u00e4r denna f\u00f6rskjutning \u00f6kar \u00e4r avg\u00f6rande f\u00f6r l\u00e4sning.<\/p>\n<p>\u00c5terv\u00e4nder vi till l\u00e4sningsmodellen som diskuterats tidigare, best\u00e5r bearbetningen av meddelandet av tre steg:<\/p>\n<ol>\n<li>Extrahera meddelandet f\u00f6r l\u00e4sning.<\/li>\n<li>Bearbeta meddelandet.<\/li>\n<li>Bekr\u00e4fta meddelandet.<\/li>\n<\/ol>\n<p>\nKafka-konsumenten levereras med en konfigurationsalternativ <i>enable.auto.commit<\/i>. Detta \u00e4r en ofta anv\u00e4nd standardinst\u00e4llning, som vanligtvis \u00e4r fallet med inst\u00e4llningar som inneh\u00e5ller ordet 'auto'.<\/p>\n<p>Fram till Kafka 0.10 skickade klienten som anv\u00e4nde denna parameter f\u00f6rskjutningen av det senaste l\u00e4sta meddelandet vid n\u00e4sta anrop <i>poll ()<\/i> efter bearbetning. Det betydde att eventuella meddelanden som redan hade extraherats (fetched) kunde behandlas p\u00e5 nytt om klienten redan hade bearbetat dem men ov\u00e4ntat st\u00e4ngdes av innan anropet. <i>poll ()<\/i>. Eftersom m\u00e4klaren inte sparar n\u00e5got tillst\u00e5nd om hur m\u00e5nga g\u00e5nger ett meddelande har l\u00e4sts, kommer n\u00e4sta konsument som h\u00e4mtar detta meddelande inte att veta att n\u00e5got d\u00e5ligt har intr\u00e4ffat. Detta beteende var pseudotransaktionellt. F\u00f6rskjutningen bekr\u00e4ftades endast vid framg\u00e5ngsrik behandling av meddelandet, men om klienten avbr\u00f6t arbetet skickade m\u00e4klaren samma meddelande till en annan klient. Detta beteende motsvarade garantin f\u00f6r meddelandedelivering \"<i>minst en g\u00e5ng<\/i>&#171;.<\/p>\n<p>I Kafka 0.10 \u00e4ndrades klientkoden s\u00e5 att bekr\u00e4ftelsen nu startades periodiskt av klientbiblioteket, i enlighet med inst\u00e4llningen <i>auto.commit.interval.ms<\/i>. Detta beteende ligger n\u00e5gonstans mellan l\u00e4gena JMS AUTO_ACKNOWLEDGE och DUPS_OK_ACKNOWLEDGE. Vid anv\u00e4ndning av autocommit kunde meddelanden bekr\u00e4ftas oavsett om de faktiskt hade bearbetats - detta kunde intr\u00e4ffa vid en l\u00e5ngsam konsument. Om konsumenten st\u00e4ngdes av, extraherades meddelandena av n\u00e4sta konsument, som b\u00f6rjade fr\u00e5n den bekr\u00e4ftade positionen, vilket kunde leda till att meddelanden gick f\u00f6rlorade. I detta fall f\u00f6rlorade Kafka inte meddelanden, koden som l\u00e4ste dem bearbetade helt enkelt inte dem.<\/p>\n<p>Detta l\u00e4ge har samma perspektiv som i version 0.9: meddelanden kan bearbetas, men vid ett fel kan f\u00f6rskjutningen kanske inte ha bekr\u00e4ftats, vilket potentiellt kan leda till dubblerad leverans. Ju fler meddelanden du extraherar samtidigt <i>poll ()<\/i>, desto st\u00f6rre \u00e4r detta problem.<\/p>\n<p>Som diskuterats i avsnittet \"L\u00e4sa meddelanden fr\u00e5n k\u00f6n\" p\u00e5 sida 21, finns det inget begrepp som eng\u00e5ngsleverans av ett meddelande i meddelandesystemet, med tanke p\u00e5 felhanteringsl\u00e4gen.<\/p>\n<p>I Kafka finns det tv\u00e5 s\u00e4tt att registrera (committa) en offset: automatiskt och manuellt. I b\u00e5da fallen kan meddelanden behandlas flera g\u00e5nger om ett meddelande har bearbetats, men ett fel intr\u00e4ffade innan det blev committat. Du kan \u00e4ven helt l\u00e5ta bli att behandla ett meddelande om commit \u00e4gde rum i bakgrunden och din kod har avslutats innan den p\u00e5b\u00f6rjade behandlingen (m\u00f6jligen i Kafka 0.9 och tidigare versioner).<\/p>\n<p>Du kan styra processen f\u00f6r manuell commit av offset i Kafka-konsumerarens API genom att st\u00e4lla in parameter <i>enable.auto.commit<\/i> till false och expl\u00edcit anropa en av f\u00f6ljande metoder:<\/p>\n<pre><code class=\"java\">void commitSync();\nvoid commitAsync();<\/code><\/pre>\n<p>\nOm du str\u00e4var efter att behandla ett meddelande \"\u00e5tmintone en g\u00e5ng\" m\u00e5ste du committa offset manuellt med <i>commitSync ()<\/i>, genom att k\u00f6ra detta kommando omedelbart efter att ha behandlat meddelandena.<\/p>\n<p>Dessa metoder till\u00e5ter inte bekr\u00e4ftelse (acknowledged) av meddelanden innan de har behandlats, men de g\u00f6r inget f\u00f6r att f\u00f6rhindra potentiell dubbelbehandling, samtidigt som de skapar en illusion av transaktionalitet. Det finns inga transaktioner i Kafka. Klienten har inte m\u00f6jlighet att g\u00f6ra f\u00f6ljande:<\/p>\n<ul>\n<li>Automatiskt rulla tillbaka (roll back) ett misslyckat meddelande. Konsumenter m\u00e5ste sj\u00e4lva hantera undantag som uppst\u00e5r p\u00e5 grund av problematiska payloads och backend-avbrott, eftersom de inte kan lita p\u00e5 att broker levererar meddelanden p\u00e5 nytt.<\/li>\n<li>Skicka meddelanden till flera \u00e4mnen som en enda atom\u00e4r operation. Som vi snart kommer att se, kan kontrollen \u00f6ver olika \u00e4mnen och partitioner befinna sig p\u00e5 olika maskiner i Kafka-klustret, som inte koordinerar transaktioner vid avs\u00e4ndning. Vid tidpunkten f\u00f6r denna artikels skrivande har det gjorts viss forskning f\u00f6r att m\u00f6jligg\u00f6ra detta med hj\u00e4lp av KIP-98.<\/li>\n<li>Koppla l\u00e4sning av ett meddelande fr\u00e5n ett \u00e4mne med att skicka ett annat meddelande till ett annat \u00e4mne. \u00c5terigen, Kafka-arkitekturen \u00e4r beroende av m\u00e5nga oberoende maskiner som fungerar som en enda buss och g\u00f6r inga f\u00f6rs\u00f6k att d\u00f6lja detta. Till exempel finns det inga API-komponenter som till\u00e5ter att koppla ihop <i>Konsument <\/i>och <i>Producent <\/i>i transaktionen. I JMS s\u00e4kerst\u00e4lls detta av objektet <i>Session<\/i>, fr\u00e5n vilket de skapas <i>MessageProducers <\/i>och <i>MessageConsumers<\/i>.<\/li>\n<\/ul>\n<p>\nOm vi inte kan lita p\u00e5 transaktioner, hur kan vi s\u00e4kerst\u00e4lla en semantik som \u00e4r n\u00e4rmare den som traditionella meddelandesystem erbjuder?<\/p>\n<p>Om det finns en m\u00f6jlighet att konsumentens offset kan \u00f6ka f\u00f6re meddelandet har behandlats, till exempel vid ett konsumentfel, s\u00e5 finns det inget s\u00e4tt f\u00f6r konsumenten att veta om hans konsumentgrupp har missat meddelanden n\u00e4r den tilldelas en partition. En av strategierna \u00e4r d\u00e4rf\u00f6r att spola tillbaka offset till en tidigare position. Kafka-konsumentens API tillhandah\u00e5ller f\u00f6ljande metoder f\u00f6r detta:<\/p>\n<pre><code class=\"java\">void seek(TopicPartition partition, long offset);\nvoid seekToBeginning(Collection  partitions);<\/code><\/pre>\n<p>\nMetod <i>seek ()<\/i> kan anv\u00e4ndas med metoden <br \/>\n<i>offsetsForTimes (Map timestampsToSearch)<\/i> f\u00f6r att spola tillbaka till ett tillst\u00e5nd vid en specifik tidpunkt i det f\u00f6rflutna.<\/p>\n<p>Implicit betyder anv\u00e4ndningen av denna metod att det ganska troligt \u00e4r att vissa meddelanden som har behandlats tidigare kommer att l\u00e4sas och behandlas igen. F\u00f6r att undvika detta kan vi anv\u00e4nda idempotent l\u00e4sning, som beskrivs i Kapitlet 4, f\u00f6r att sp\u00e5ra tidigare visade meddelanden och utesluta dubbletter.<\/p>\n<p>Som ett alternativ kan koden f\u00f6r din konsument vara enkel om f\u00f6rlust eller dubblett av meddelanden \u00e4r acceptabel. N\u00e4r vi \u00f6verv\u00e4ger anv\u00e4ndningsscenarier d\u00e4r Kafka vanligtvis anv\u00e4nds, som logg-, metrik- och klicksp\u00e5rning, f\u00f6rst\u00e5r vi att f\u00f6rlust av enskilda meddelanden s\u00e4llan har en betydande p\u00e5verkan p\u00e5 omgivande applikationer. I s\u00e5dana fall \u00e4r standardv\u00e4rden helt acceptabla. \u00c5 andra sidan, om din applikation beh\u00f6ver \u00f6verf\u00f6ra betalningar m\u00e5ste du noga se till varje enskilt meddelande. Allt beror p\u00e5 sammanhanget.<\/p>\n<p>Personliga observationer visar att med \u00f6kande meddelandeintensitet minskar v\u00e4rdet av varje enskilt meddelande. Stora m\u00e4ngder meddelanden blir vanligtvis v\u00e4rdefulla om de betraktas i aggregerad form.<\/p>\n<h2>H\u00f6g tillg\u00e4nglighet (High Availability)<\/h2>\n<p>\nKafkas tillv\u00e4gag\u00e5ngss\u00e4tt f\u00f6r h\u00f6g tillg\u00e4nglighet skiljer sig v\u00e4sentligt fr\u00e5n ActiveMQ:s. Kafka \u00e4r designad f\u00f6r att fungera p\u00e5 horisontellt skalbara kluster d\u00e4r alla broker-exemplar tar emot och distribuerar meddelanden samtidigt.<\/p>\n<p>Ett Kafka-kluster best\u00e5r av flera broker-exemplar som k\u00f6rs p\u00e5 olika servrar. Kafka \u00e4r utformad f\u00f6r att fungera p\u00e5 vanlig autonom h\u00e5rdvara d\u00e4r varje nod har sin egen dedikerade lagring. Anv\u00e4ndning av n\u00e4tverkslagring (SAN) rekommenderas inte, eftersom flera ber\u00e4kningsnoder kan konkurrera om lagringens tidsintervall och skapa konflikter.<i>\u00d6<\/i>lagra intervall och skapa konflikter.<\/p>\n<p>Kafka \u00e4r en <i>alltid aktiv<\/i> system. M\u00e5nga stora anv\u00e4ndare av Kafka st\u00e4nger aldrig ner sina kluster och mjukvaran s\u00e4kerst\u00e4ller alltid uppdatering genom sekventiell omstart. Detta uppn\u00e5s genom att garantera bak\u00e5tkompatibilitet f\u00f6r meddelanden och interaktioner mellan broker-exemplaren.<\/p>\n<p>Brokers \u00e4r anslutna till ett kluster av servrar <noindex><a rel=\"nofollow\" href=\"http:\/\/zookeeper.apache.org\">ZooKeeper<\/a><\/noindex>, som fungerar som ett register f\u00f6r konfigurationsinformation och anv\u00e4nds f\u00f6r att koordinera rollerna f\u00f6r varje broker. ZooKeeper \u00e4r sj\u00e4lv en distribuerad system som s\u00e4kerst\u00e4ller h\u00f6g tillg\u00e4nglighet genom att replikera information genom att uppr\u00e4tta <i>kvorum.<\/i>.<\/p>\n<p>I grundfall skapas en topic i Kafka-klustret med f\u00f6ljande egenskaper:<\/p>\n<ul>\n<li>Antal partitioner. Som diskuterats tidigare beror det exakta v\u00e4rdet som anv\u00e4nds h\u00e4r p\u00e5 \u00f6nskad niv\u00e5 av parallell l\u00e4sning.<\/li>\n<li>Replikationsfaktorn definierar hur m\u00e5nga broker-exemplar i klustret som ska inneh\u00e5lla loggar f\u00f6r denna partition.<\/li>\n<\/ul>\n<p>\nGenom att anv\u00e4nda ZooKeeper f\u00f6r koordinering f\u00f6rs\u00f6ker Kafka r\u00e4ttvist f\u00f6rdela nya partitioner mellan broker-exemplaren i klustret. Detta g\u00f6rs av ett exemplar som fungerar som kontroller.<\/p>\n<p>Vid k\u00f6rning <i>f\u00f6r varje partition av en topic<\/i> <i>Kontroller <\/i>tilldelar en broker roller <i>ledare <\/i>(leader, master, huvud) och <i>f\u00f6ljare. <\/i>(f\u00f6ljare, slavar, underordnade). En broker som fungerar som ledare f\u00f6r denna partition ansvarar f\u00f6r att ta emot alla meddelanden som skickas till honom av producenter och sprida meddelanden till konsumenterna. N\u00e4r meddelanden skickas till en partitions\u00e4mne replikeras de p\u00e5 alla broker-noder som fungerar som f\u00f6ljare f\u00f6r denna partition. Varje nod som har loggar f\u00f6r partitionen kallas <i>replik<\/i>. En broker kan fungera som ledare f\u00f6r vissa partitioner och som f\u00f6ljare f\u00f6r andra.<\/p>\n<p>F\u00f6ljaren som inneh\u00e5ller alla meddelanden som lagras hos ledaren kallas <i>synkroniserad replik<\/i> (in-sync replica). Om en broker som fungerar som ledare f\u00f6r en partition st\u00e4ngs av, kan vilken broker som helst som \u00e4r i uppdaterat eller synkroniserat tillst\u00e5nd f\u00f6r denna partition ta \u00f6ver rollen som ledare. Detta \u00e4r en otroligt robust design.<\/p>\n<p>En del av producentens konfiguration \u00e4r parametern <i>acks<\/i>, som best\u00e4mmer hur m\u00e5nga repliker som m\u00e5ste bekr\u00e4fta (acknowledge) mottagandet av meddelandet innan applikationsstr\u00f6mmen forts\u00e4tter med att skicka: 0, 1 eller alla. Om v\u00e4rdet <i>all<\/i>anges, kommer ledaren att skicka en bekr\u00e4ftelse (confirmation) tillbaka till producenten s\u00e5 snart den f\u00e5r bekr\u00e4ftelser (acknowledgements) f\u00f6r skrivningen fr\u00e5n fler repliker (inklusive sig sj\u00e4lv), som anges av inst\u00e4llningen f\u00f6r \u00e4mnet <i>min.insync.replicas<\/i> (standard \u00e4r 1). Om meddelandet inte kan replikeras framg\u00e5ngsrikt kommer producenten att utl\u00f6sa ett undantag f\u00f6r applikationen (<i>NotEnoughReplicas<\/i> eller <i>NotEnoughReplicasAfterAppend<\/i>).<\/p>\n<p>I en typisk konfiguration skapas ett \u00e4mne med en replikeringsfaktor p\u00e5 3 (1 ledare, 2 f\u00f6ljare f\u00f6r varje partition) och parametern <i>min.insync.replicas<\/i> st\u00e4ller in v\u00e4rdet 2. I detta fall kommer klustret att till\u00e5ta att en av brokerna som hanterar \u00e4mnespartitionen kan st\u00e4ngas av utan att p\u00e5verka klientapplikationerna.<\/p>\n<p>Det h\u00e4r f\u00f6r oss tillbaka till den bekanta kompromissen mellan prestanda och tillf\u00f6rlitlighet. Replikering sker genom ytterligare v\u00e4ntetid f\u00f6r bekr\u00e4ftelser (acknowledgments) fr\u00e5n efterf\u00f6ljare. Men eftersom det g\u00f6rs parallellt, har replikering, \u00e5tminstone \u00f6ver tre noder, samma prestanda som med tv\u00e5 (ignorerar \u00f6kat n\u00e4tverksbandbredd).<\/p>\n<p>Genom att anv\u00e4nda detta replikering schema undviker Kafka smidigt behovet av att s\u00e4kerst\u00e4lla fysisk skrivning av varje meddelande till disk via operationen <i>sync ()<\/i>. Varje meddelande som skickas av producenten kommer att skrivas till partitionens logg, men som diskuterat i Kapitel 2, utf\u00f6rs skrivningen till fil initialt i operativsystemets buffer. Om detta meddelande replikerats till en annan instans av Kafka och finns i dess minne, betyder f\u00f6rlust av ledaren inte att sj\u00e4lva meddelandet har g\u00e5tt f\u00f6rlorat - det kan tas \u00f6ver av en synkroniserad replik.<br \/>\nAvst\u00e5ndet fr\u00e5n att beh\u00f6va utf\u00f6ra operationen <i>sync ()<\/i> betyder att Kafka kan ta emot meddelanden i den takt den kan skriva dem i minnet. Och tv\u00e4rtom, ju l\u00e4ngre man kan undvika att t\u00f6mma (flushing) minnet till disk, desto b\u00e4ttre. Av denna anledning \u00e4r det inte ovanligt att Kafka-brokers f\u00e5r 64 GB minne eller mer. Denna minnesanv\u00e4ndning inneb\u00e4r att en instans av Kafka kan arbeta i hastigheter som \u00e4r tusentals g\u00e5nger snabbare \u00e4n en traditionell meddelandebroker.<\/p>\n<p>Kafka kan ocks\u00e5 konfigureras f\u00f6r att till\u00e4mpa operationen <i>sync ()<\/i> p\u00e5 meddelandepaket. Eftersom allt i Kafka \u00e4r inriktat p\u00e5 att arbeta med paket fungerar detta faktiskt ganska bra f\u00f6r m\u00e5nga anv\u00e4ndningsfall och \u00e4r ett nyttigt verktyg f\u00f6r anv\u00e4ndare som kr\u00e4ver mycket starka garantier. St\u00f6rsta delen av Kafkas rena prestanda relaterar till meddelanden som skickas till brokern i form av paket och att dessa meddelanden l\u00e4ses fr\u00e5n brokern i sekventiella block med hj\u00e4lp av <noindex><a rel=\"nofollow\" href=\"http:\/\/www.linuxjournal.com\/article\/6345\">zero-copy<\/a><\/noindex> operationer (med operationer d\u00e4r uppgiften att kopiera data fr\u00e5n ett minne till ett annat inte utf\u00f6rs). Detta \u00e4r en stor vinst n\u00e4r det g\u00e4ller prestanda och resurser och \u00e4r m\u00f6jligt tack vare anv\u00e4ndningen av den underliggande loggdatastrukturen, som definierar partitionsschemat.<\/p>\n<p>I en Kafka-kluster \u00e4r det m\u00f6jligt att uppn\u00e5 mycket h\u00f6gre prestanda \u00e4n med en enda Kafka-broker, eftersom partitionerna i en topic kan skalas horisontellt \u00f6ver flera separata maskiner.<\/p>\n<h2>Sammanfattning<\/h2>\n<p>\nI detta kapitel har vi unders\u00f6kt hur Kafka-arkitekturen omformulerar relationerna mellan klienter och brokers f\u00f6r att s\u00e4kerst\u00e4lla en oerh\u00f6rt robust meddelandekanal, med en bandbredd som \u00e4r m\u00e5nga g\u00e5nger h\u00f6gre \u00e4n en vanlig meddelandebroker. Vi har diskuterat de funktioner som den anv\u00e4nder f\u00f6r att uppn\u00e5 detta m\u00e5l, och kortfattat betraktat arkitekturen f\u00f6r de applikationer som tillhandah\u00e5ller dessa funktioner. I n\u00e4sta kapitel kommer vi att diskutera vanliga problem som meddelandebaserade applikationer m\u00e5ste hantera, och vi kommer att diskutera strategier f\u00f6r att l\u00f6sa dessa. Vi avslutar kapitlet med att skissa p\u00e5 hur man resonerar kring meddelandeteknologier i allm\u00e4nhet, s\u00e5 att du kan bed\u00f6ma deras l\u00e4mplighet f\u00f6r dina anv\u00e4ndningsscenarier.<\/p>\n<p>Tidigare \u00f6versatt del: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">F\u00f6rst\u00e5else av meddelandebrokers. Studera mekaniken f\u00f6r meddelandeutbyte med ActiveMQ och Kafka. Kapitel 1<\/a><\/noindex><\/p>\n<p><b> \u00d6vers\u00e4ttning utf\u00f6rd av: <noindex><a rel=\"nofollow\" href=\"http:\/\/tele.gg\/middle_java\">tele.gg\/middle_java<\/a><\/noindex><\/b><\/p>\n<p><i>Forts\u00e4ttning f\u00f6ljer\u2026<\/i><\/p>\n<p class=\"for_users_only_msg\">Endast registrerade anv\u00e4ndare kan delta i omr\u00f6stningen. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Logga in<\/a><\/noindex>, tack.<\/p>\n<h2 class=\"default-block__polling-title\">Anv\u00e4nds Kafka i din organisation?<\/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>                    Ingen<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Anv\u00e4ndes tidigare, g\u00f6r det inte nu<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Planerar att anv\u00e4nda<\/p>\n<\/li>\n<\/ul>\n<p>    38 anv\u00e4ndare r\u00f6stade. 8 anv\u00e4ndare avstod.<br \/>\n<br \/>K\u00e4lla: <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.4 - 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\/sv\/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.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sv_SE\" \/>\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\/sv\/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\udd47F\u00f6rst\u00e5else f\u00f6r meddelandebrockers. Studera mekaniken f\u00f6r meddelandeutbyte genom ActiveMQ och Kafka. Kapitel 3. Kafka | ProHoster","description":"Forts\u00e4ttning p\u00e5 \u00f6vers\u00e4ttningen av den lilla boken: 'Understanding Message Brokers', f\u00f6rfattare: Jakub Korab, utgivare: O'Reilly Media, Inc., utgivningsdatum: juni 2017, ISBN: 9781492049296. Tidigare \u00f6versatt.","canonical_url":"https:\/\/prohoster.info\/sv\/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":"sv_SE","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\/sv\/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\/sv\/wp-json\/wp\/v2\/posts\/38172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=38172"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/38172\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=38172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=38172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=38172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}