{"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\/pl\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka","title":{"rendered":"Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci za pomoc\u0105 ActiveMQ i Kafka. Rozdzia\u0142 3. Kafka","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Kontynuacja t\u0142umaczenia ma\u0142ej ksi\u0105\u017cki:<br \/>\n\u201eZrozumienie broker\u00f3w wiadomo\u015bci\u201d,<br \/>\nautor: Jakub Korab, wydawnictwo: O'Reilly Media, Inc., data wydania: czerwiec 2017, ISBN: 9781492049296.<\/p>\n<p>Poprzednia przet\u0142umaczona cz\u0119\u015b\u0107: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci za pomoc\u0105 ActiveMQ i Kafka. Rozdzia\u0142 1. Wprowadzenie<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>ROZDZIA\u0141 3<\/h2>\n<p><\/p>\n<h2>Kafka<\/h2>\n<p>\nKafka zosta\u0142a stworzona w LinkedIn, aby obej\u015b\u0107 pewne ograniczenia tradycyjnych broker\u00f3w wiadomo\u015bci i unikn\u0105\u0107 konieczno\u015bci konfiguracji wielu broker\u00f3w wiadomo\u015bci dla r\u00f3\u017cnych interakcji \u201epunkt-punkt\u201d, co jest opisane w tej ksi\u0105\u017cce w rozdziale \u201ePionowe i poziome skalowanie\u201d na stronie 28. Scenariusze u\u017cycia w LinkedIn opiera\u0142y si\u0119 g\u0142\u00f3wnie na jednokierunkowym gromadzeniu bardzo du\u017cych ilo\u015bci danych, takich jak klikni\u0119cia na stronach i logi dost\u0119pu, jednocze\u015bnie umo\u017cliwiaj\u0105c wielokrotne korzystanie z tych danych przez r\u00f3\u017cne systemy, bez wp\u0142ywu na wydajno\u015b\u0107 producent\u00f3w lub innych konsument\u00f3w. Faktycznie, przyczyn\u0105 istnienia Kafka jest uzyskanie takiej architektury wymiany wiadomo\u015bci, jak\u0105 opisuje Universal Data Pipeline.<\/p>\n<p>Maj\u0105c na uwadze ten ostateczny cel, naturalnie powsta\u0142y tak\u017ce inne wymagania. Kafka musi:<\/p>\n<ul>\n<li>By\u0107 niezwykle szybka<\/li>\n<li>Zapewnia\u0107 du\u017c\u0105 przepustowo\u015b\u0107 przy obs\u0142udze wiadomo\u015bci<\/li>\n<li>Obs\u0142ugiwa\u0107 modele \u201eWydawca-Subskrybent\u201d i \u201ePunkt-Punkt\u201d<\/li>\n<li>Nie zwalnia\u0107 przy dodawaniu konsument\u00f3w. Na przyk\u0142ad wydajno\u015b\u0107 zar\u00f3wno kolejek, jak i temat\u00f3w w ActiveMQ pogarsza si\u0119, gdy ro\u015bnie liczba konsument\u00f3w na adresacie<\/li>\n<li>By\u0107 poziomo skalowalna; je\u015bli jeden broker, kt\u00f3ry przechowuje (persists) wiadomo\u015bci, mo\u017ce to robi\u0107 tylko z maksymaln\u0105 pr\u0119dko\u015bci\u0105 dysku, to dla zwi\u0119kszenia wydajno\u015bci ma sens rozwa\u017cy\u0107 wi\u0119cej ni\u017c jedn\u0105 instancj\u0119 brokera<\/li>\n<li>Dzieli\u0107 dost\u0119p do przechowywania i ponownego wydobywania wiadomo\u015bci<\/li>\n<\/ul>\n<p>\nAby osi\u0105gn\u0105\u0107 to wszystko, w Kafka przyj\u0119to architektur\u0119, kt\u00f3ra przedefiniowa\u0142a role i obowi\u0105zki klient\u00f3w oraz broker\u00f3w wymiany wiadomo\u015bci. Model JMS jest bardzo ukierunkowany na brokera, kt\u00f3ry odpowiada za dystrybucj\u0119 wiadomo\u015bci, a klienci maj\u0105 si\u0119 martwi\u0107 tylko o wysy\u0142anie i odbieranie wiadomo\u015bci. Z drugiej strony, Kafka jest ukierunkowana na klienta, przy czym klient przejmuje wiele funkcji tradycyjnego brokera, takich jak sprawiedliwy podzia\u0142 odpowiednich wiadomo\u015bci w\u015br\u00f3d konsument\u00f3w, w zamian zyskuj\u0105c niezwykle szybki i skalowalny broker. Dla os\u00f3b, kt\u00f3re pracowa\u0142y z tradycyjnymi systemami wymiany wiadomo\u015bci, praca z Kafka wymaga fundamentalnych zmian w perspektywie.<br \/>\nTo in\u017cynieryjne podej\u015bcie doprowadzi\u0142o do stworzenia infrastruktury wymiany wiadomo\u015bci, kt\u00f3ra potrafi znacznie zwi\u0119kszy\u0107 przepustowo\u015b\u0107 w por\u00f3wnaniu do zwyk\u0142ego brokera. Jak si\u0119 przekonamy, podej\u015bcie to wi\u0105\u017ce si\u0119 z kompromisami, kt\u00f3re oznaczaj\u0105, \u017ce Kafka nie nadaje si\u0119 do okre\u015blonych typ\u00f3w obci\u0105\u017ce\u0144 i oprogramowania systemowego.<\/p>\n<h3>Ujednolicona model adresata<\/h3>\n<p>\nAby spe\u0142ni\u0107 powy\u017csze wymagania, Kafka po\u0142\u0105czy\u0142a wymian\u0119 wiadomo\u015bci typu \u201epublikacja-subskrypcja\u201d i \u201epunkt-punkt\u201d w ramach jednego rodzaju adresata \u2014 <i>tematu<\/i>. To dezorientuje ludzi, kt\u00f3rzy pracowali z systemami wymiany wiadomo\u015bci, gdzie s\u0142owo \u201etemat\u201d odnosi si\u0119 do mechanizmu rozg\u0142aszania, z kt\u00f3rego (z tematu) odczyt nie jest niezawodny (is nondurable). Tematy w Kafka nale\u017cy traktowa\u0107 jako hybrydowy typ adresata, zgodnie z definicj\u0105 podan\u0105 we wprowadzeniu do tej ksi\u0105\u017cki.<\/p>\n<blockquote><p>W pozosta\u0142ej cz\u0119\u015bci tego rozdzia\u0142u, o ile nie wska\u017cemy inaczej, termin \u201etemat\u201d b\u0119dzie odnosi\u0142 si\u0119 do tematu Kafka.<\/p><\/blockquote>\n<p>\nAby w pe\u0142ni zrozumie\u0107, jak zachowuj\u0105 si\u0119 tematy i jakie gwarancje daj\u0105, musimy najpierw przyjrze\u0107 si\u0119 temu, jak s\u0105 one zaimplementowane w Kafka.<br \/>\n<i>Ka\u017cdy temat w Kafka ma swoj\u0105 w\u0142asn\u0105 dziennik.<\/i><br \/>\nProducenci wysy\u0142aj\u0105cy wiadomo\u015bci do Kafki zapisuj\u0105 je w tym dzienniku, a konsumenci odczytuj\u0105 z dziennika za pomoc\u0105 wska\u017anik\u00f3w, kt\u00f3re ci\u0105gle przesuwaj\u0105 si\u0119 do przodu. Okresowo Kafka usuwa najstarsze cz\u0119\u015bci dziennika, niezale\u017cnie od tego, czy wiadomo\u015bci w tych cz\u0119\u015bciach zosta\u0142y odczytane, czy nie. Centralnym elementem projektu Kafki jest to, \u017ce broker nie dba o to, czy wiadomo\u015bci zosta\u0142y odczytane, czy nie \u2014 to odpowiedzialno\u015b\u0107 klienta.<\/p>\n<blockquote><p>Terminy \u201edziennik\u201d i \u201ewska\u017anik\u201d nie wyst\u0119puj\u0105 w <noindex><a rel=\"nofollow\" href=\"https:\/\/kafka.apache.org\/documentation.html\">dokumentacji Kafki<\/a><\/noindex>. Te dobrze znane terminy s\u0105 u\u017cywane tutaj, aby u\u0142atwi\u0107 zrozumienie.<\/p><\/blockquote>\n<p>\nTen model r\u00f3\u017cni si\u0119 diametralnie od ActiveMQ, gdzie wiadomo\u015bci ze wszystkich kolejek s\u0105 przechowywane w jednym dzienniku, a broker oznacza wiadomo\u015bci jako usuni\u0119te po ich odczytaniu.<br \/>\nTeraz zanurzmy si\u0119 nieco g\u0142\u0119biej i przyjrzyjmy si\u0119 dziennikowi tematu bardziej szczeg\u00f3\u0142owo.<br \/>\nDziennik Kafki sk\u0142ada si\u0119 z kilku partycji (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/tm\/w2\/yf\/tmw2yf3lanppqtrumxoidotplhi.png\">Rysunek 3-1<\/a><\/noindex>). Kafka zapewnia \u015bcis\u0142\u0105 kolejno\u015b\u0107 w ka\u017cdej partycji. Oznacza to, \u017ce wiadomo\u015bci zapisane w partycji w okre\u015blonej kolejno\u015bci b\u0119d\u0105 odczytywane w tej samej kolejno\u015bci. Ka\u017cda partycja jest realizowana jako cykliczny (rolling) plik dziennika, kt\u00f3ry zawiera <i>podzbi\u00f3r <\/i>(subset) wszystkich wiadomo\u015bci wys\u0142anych do tematu przez jego producent\u00f3w. Tworzony temat zawiera domy\u015blnie jedn\u0105 partycj\u0119. Idea partycji to centralny pomys\u0142 Kafki na poziome skalowanie.<\/p>\n<p><img decoding=\"async\" alt=\"Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci za pomoc\u0105 ActiveMQ i Kafka. Rozdzia\u0142 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/39f41ebcb73ec247656c0dea438158a9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rysunek 3-1. Partycje Kafki<\/i><\/p>\n<p>Kiedy producent wysy\u0142a wiadomo\u015b\u0107 do tematu Kafki, decyduje, do kt\u00f3rej partycji j\u0105 wys\u0142a\u0107. Przyjrzymy si\u0119 temu bardziej szczeg\u00f3\u0142owo p\u00f3\u017aniej.<\/p>\n<h2>Odczyt wiadomo\u015bci<\/h2>\n<p>\nKlient, kt\u00f3ry chce odczyta\u0107 wiadomo\u015bci, zarz\u0105dza nazwanym wska\u017anikiem, nazywanym <i>grupa konsument\u00f3w (consumer group)<\/i>, kt\u00f3ry wskazuje na <i>offset<\/i> wiadomo\u015bci w partycji. Offset to pozycja z rosn\u0105cym numerem, kt\u00f3ra zaczyna si\u0119 od 0 na pocz\u0105tku partycji. Ta grupa konsument\u00f3w, na kt\u00f3r\u0105 odnosi si\u0119 w API za pomoc\u0105 zdefiniowanego przez u\u017cytkownika identyfikatora group_id, odpowiada <i>jednemu logicznemu konsumentowi lub systemowi<\/i>.<\/p>\n<p>Wi\u0119kszo\u015b\u0107 system\u00f3w wykorzystuj\u0105cych wymian\u0119 wiadomo\u015bci odczytuje dane od nadawcy za pomoc\u0105 wielu instancji i w\u0105tk\u00f3w do r\u00f3wnoleg\u0142ego przetwarzania wiadomo\u015bci. Zazwyczaj zatem b\u0119dzie wiele instancji konsument\u00f3w wsp\u00f3\u0142dziel\u0105cych t\u0119 sam\u0105 grup\u0119 konsument\u00f3w.<\/p>\n<p>Problem odczytu mo\u017cna przedstawi\u0107 w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n<ul>\n<li>Temat ma kilka partycji<\/li>\n<li>Z tego samego tematu mo\u017ce korzysta\u0107 jednocze\u015bnie wiele grup konsument\u00f3w<\/li>\n<li>Grupa konsument\u00f3w mo\u017ce mie\u0107 kilka osobnych instancji<\/li>\n<\/ul>\n<p>\nTo nie jest trywialny problem 'wielu do wielu'. Aby zrozumie\u0107, jak Kafka radzi sobie z relacjami mi\u0119dzy grupami konsument\u00f3w, instancjami konsument\u00f3w i partycjami, rozwa\u017cmy szereg stopniowo komplikuj\u0105cych si\u0119 scenariuszy odczytu.<\/p>\n<h3>Konsumenci i grupy konsument\u00f3w<\/h3>\n<p>\nWe\u017amy jako punkt wyj\u015bcia temat z jedn\u0105 partycj\u0105 (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/6z\/tz\/dh\/6ztzdhqmjweck-z15htxb2xbe28.png\">Rysunek 3-2<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci za pomoc\u0105 ActiveMQ i Kafka. Rozdzia\u0142 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/46c92e6bd38774dfef3be4bd198bf35d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rysunek 3-2. Konsument odczytuje z partycji<\/i><\/p>\n<p>Gdy instancja konsumenta \u0142\u0105czy si\u0119 ze swoim w\u0142asnym group_id do tego tematu, przypisywana jest jej partycja do odczytu oraz offset w tej partycji. Pozycja tego offsetu jest konfigurowana w kliencie jako wska\u017anik na najnowsz\u0105 pozycj\u0119 (najnowsza wiadomo\u015b\u0107) lub najwcze\u015bniejsz\u0105 pozycj\u0119 (najstarsza wiadomo\u015b\u0107). Konsument zadaje (polls) zapytania o wiadomo\u015bci z tematu, co prowadzi do ich sekwencyjnego odczytu z dziennika.<br \/>\nPozycja offsetu jest regularnie zatwierdzana z powrotem do Kafki i przechowywana jako wiadomo\u015bci wewn\u0119trznego tematu <i>_consumer_offsets<\/i>. Odczytane wiadomo\u015bci wci\u0105\u017c nie s\u0105 usuwane, w przeciwie\u0144stwie do zwyk\u0142ego brokera, a klient mo\u017ce przeskoczy\u0107 (rewind) offset, aby ponownie przetworzy\u0107 ju\u017c ogl\u0105dane wiadomo\u015bci.<\/p>\n<p>Gdy \u0142\u0105czy si\u0119 drugi logiczny konsument, korzystaj\u0105c z innego group_id, zarz\u0105dza on drugim wska\u017anikiem, kt\u00f3ry nie zale\u017cy od pierwszego (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/qe\/v1\/yk\/qev1yktga3s-g1gqlynylbe3n9w.png\">Rysunek 3-3<\/a><\/noindex>). W ten spos\u00f3b temat Kafki dzia\u0142a jak kolejka, w kt\u00f3rej istnieje jeden konsument, oraz jak zwyk\u0142y temat publikator-subskrybent (pub-sub), na kt\u00f3ry subskrybuje wiele konsument\u00f3w, z dodatkow\u0105 korzy\u015bci\u0105, \u017ce wszystkie wiadomo\u015bci s\u0105 przechowywane i mog\u0105 by\u0107 przetwarzane wiele razy.<\/p>\n<p><img decoding=\"async\" alt=\"Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci za pomoc\u0105 ActiveMQ i Kafka. Rozdzia\u0142 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/e9e8b9063ef7367005254d36abb47f4f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rysunek 3-3. Dwaj konsumenci w r\u00f3\u017cnych grupach konsument\u00f3w odczytuj\u0105 z jednej partycji<\/i><\/p>\n<h3>Konsumenci w grupie konsument\u00f3w<\/h3>\n<p>\nGdy jeden egzemplarz konsumenta odczytuje dane z partycji, ma pe\u0142n\u0105 kontrol\u0119 nad wska\u017anikiem i przetwarza wiadomo\u015bci, jak opisano w poprzedniej sekcji.<br \/>\nJe\u015bli kilka egzemplarzy konsument\u00f3w zosta\u0142o pod\u0142\u0105czonych z tym samym group_id do tematu z jedn\u0105 partycj\u0105, to egzemplarz, kt\u00f3ry po\u0142\u0105czy\u0142 si\u0119 ostatni, przejmie kontrol\u0119 nad wska\u017anikiem i od tego momentu b\u0119dzie otrzymywa\u0142 wszystkie wiadomo\u015bci (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/0j\/ao\/f2\/0jaof2mdwg3cqvmwemhtxkrltuq.png\">Rysunek 3-4<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci za pomoc\u0105 ActiveMQ i Kafka. Rozdzia\u0142 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/ec6af819445dad4028f65449a735ae22.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rysunek 3-4. Dwaj konsumenci w tej samej grupie konsument\u00f3w odczytuj\u0105 z jednej partycji<\/i><\/p>\n<p>Ten tryb przetwarzania, w kt\u00f3rym liczba egzemplarzy konsument\u00f3w przekracza liczb\u0119 partycji, mo\u017cna traktowa\u0107 jako form\u0119 monopolnego konsumenta. Mo\u017ce to by\u0107 przydatne, je\u015bli potrzebujesz \u201etrybu aktywno-pasywnego\u201d (lub \u201egor\u0105cego-ciep\u0142ego\u201d) klasteryzacji swoich egzemplarzy konsument\u00f3w, chocia\u017c r\u00f3wnoleg\u0142a praca kilku konsument\u00f3w (\u201eaktywnie-aktywny\u201d lub \u201egor\u0105cy-gor\u0105cy\u201d) jest znacznie bardziej typowa ni\u017c konsumenci w trybie oczekiwania.<\/p>\n<blockquote><p>Takie zachowanie dystrybucji wiadomo\u015bci, opisane powy\u017cej, mo\u017ce by\u0107 zaskakuj\u0105ce w por\u00f3wnaniu do tego, jak dzia\u0142a zwyk\u0142a kolejka JMS. W tym modelu wiadomo\u015bci wysy\u0142ane do kolejki b\u0119d\u0105 r\u00f3wnomiernie dystrybuowane mi\u0119dzy dwoma konsumentami.<\/p><\/blockquote>\n<p>\nNajcz\u0119\u015bciej, gdy tworzymy kilka egzemplarzy konsument\u00f3w, robimy to albo dla r\u00f3wnoleg\u0142ego przetwarzania wiadomo\u015bci, albo dla zwi\u0119kszenia pr\u0119dko\u015bci odczytu, albo dla zwi\u0119kszenia odporno\u015bci procesu odczytu. Poniewa\u017c tylko jeden egzemplarz konsumenta mo\u017ce jednocze\u015bnie odczytywa\u0107 dane z partycji, jak to osi\u0105ga si\u0119 w Kafce?<\/p>\n<p>Jednym ze sposob\u00f3w realizacji tego celu jest u\u017cycie jednego egzemplarza konsumenta do odczytania wszystkich wiadomo\u015bci i przekazania ich do puli w\u0105tk\u00f3w. Chocia\u017c podej\u015bcie to zwi\u0119ksza przepustowo\u015b\u0107 przetwarzania, zwi\u0119ksza r\u00f3wnie\u017c z\u0142o\u017cono\u015b\u0107 logiki konsument\u00f3w i nic nie robi, aby poprawi\u0107 odporno\u015b\u0107 systemu odczytu. Je\u015bli jeden egzemplarz konsumenta zostanie od\u0142\u0105czony z powodu awarii zasilania lub podobnego zdarzenia, to odczyt zostaje przerwany.<\/p>\n<p>Kanonizowanym sposobem rozwi\u0105zania tego problemu w Kafce jest u\u017cycie b<i>o<\/i>wi\u0119kszej liczby partycji.<\/p>\n<h3>Partycjonowanie<\/h3>\n<p>\nPartycje s\u0105 podstawowym mechanizmem r\u00f3wnoleg\u0142ego odczytu i skalowania tematu poza przepustowo\u015b\u0107 pojedynczego brokera. Aby lepiej zrozumie\u0107 t\u0119 koncepcj\u0119, rozwa\u017cmy sytuacj\u0119, w kt\u00f3rej istnieje temat z dwoma partycjami, a do tego tematu subskrybuje jeden konsument (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/en\/9g\/ct\/en9gct0o017cqp8buawguwlscty.png\">Rysunek 3-5<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci za pomoc\u0105 ActiveMQ i Kafka. Rozdzia\u0142 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/cc766bf69af22698aacc3f1ac70b067f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rysunek 3-5. Jeden konsument odczytuje z kilku partycji<\/i><\/p>\n<p>W tym scenariuszu konsument ma kontrol\u0119 nad wska\u017anikami odpowiadaj\u0105cymi jego group_id w obu partycjach i zaczyna odczytywa\u0107 wiadomo\u015bci z obu partycji.<br \/>\nKiedy do tego tematu dodawany jest dodatkowy konsument dla tego samego group_id, Kafka ponownie przydziela (reallocate) jedn\u0105 z partycji z pierwszego na drugi konsument. Nast\u0119pnie ka\u017cdy egzemplarz konsumenta b\u0119dzie odczytywa\u0142 z jednej partycji tematu (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/8b\/a0\/um\/8ba0umn2yzr9yy3vztonhdfiub0.png\">Rysunek 3-6<\/a><\/noindex>).<\/p>\n<p>Aby zapewni\u0107 przetwarzanie wiadomo\u015bci r\u00f3wnolegle w 20 w\u0105tkach, potrzebujesz co najmniej 20 partycji. Je\u015bli partycji jest mniej, pozostan\u0105 konsumenty, kt\u00f3re nie b\u0119d\u0105 mia\u0142y nad czym pracowa\u0107, co zosta\u0142o wcze\u015bniej om\u00f3wione w kontek\u015bcie monopolowych konsument\u00f3w.<\/p>\n<p><img decoding=\"async\" alt=\"Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci za pomoc\u0105 ActiveMQ i Kafka. Rozdzia\u0142 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/a3c4001e4a5b92d53b6f529b2633254a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rysunek 3-6. Dw\u00f3ch konsument\u00f3w w tej samej grupie konsument\u00f3w odczytuje z r\u00f3\u017cnych partycji<\/i><\/p>\n<p>Ten schemat znacznie zmniejsza z\u0142o\u017cono\u015b\u0107 dzia\u0142ania brokera Kafka w por\u00f3wnaniu do dystrybucji wiadomo\u015bci wymaganej do obs\u0142ugi kolejki JMS. Nie trzeba martwi\u0107 si\u0119 o nast\u0119puj\u0105ce kwestie:<\/p>\n<ul>\n<li>Kt\u00f3ry konsument powinien otrzyma\u0107 nast\u0119pn\u0105 wiadomo\u015b\u0107, opieraj\u0105c si\u0119 na rozdziale okr\u0119\u017cnym (round-robin), bie\u017c\u0105cej pojemno\u015bci bufor\u00f3w wst\u0119pnego odczytu lub poprzednich wiadomo\u015bciach (jak w grupach wiadomo\u015bci JMS).<\/li>\n<li>Jakie wiadomo\u015bci zosta\u0142y wys\u0142ane do jakich konsument\u00f3w i czy powinny by\u0107 dostarczone ponownie w przypadku awarii.<\/li>\n<\/ul>\n<p>\nWszystko, co broker Kafka musi zrobi\u0107, to kolejno przekazywa\u0107 wiadomo\u015bci konsumentowi, gdy ostatni je \u017c\u0105da.<\/p>\n<p>Jednak\u017ce wymagania dotycz\u0105ce r\u00f3wnoleg\u0142ego odczytu i ponownego wysy\u0142ania nieudanych wiadomo\u015bci wci\u0105\u017c istniej\u0105 \u2014 odpowiedzialno\u015b\u0107 za nie przechodzi po prostu z brokera na klienta. Oznacza to, \u017ce musz\u0105 by\u0107 uwzgl\u0119dnione w Twoim kodzie.<\/p>\n<h2>Wysy\u0142anie wiadomo\u015bci<\/h2>\n<p>\nOdpowiedzialno\u015b\u0107 za decyzj\u0119, do kt\u00f3rej partycji wys\u0142a\u0107 wiadomo\u015b\u0107, spoczywa na producencie tej wiadomo\u015bci. Aby zrozumie\u0107 mechanizm, za pomoc\u0105 kt\u00f3rego to robi si\u0119, najpierw nale\u017cy rozwa\u017cy\u0107, co tak naprawd\u0119 wysy\u0142amy.<\/p>\n<p>Podczas gdy w JMS u\u017cywamy struktury wiadomo\u015bci z metadanymi (nag\u0142\u00f3wkami i w\u0142a\u015bciwo\u015bciami) oraz cia\u0142em zawieraj\u0105cym \u0142adunek u\u017cyteczny (payload), w Kafka wiadomo\u015b\u0107 to <i>para \u201eklucz-warto\u015b\u0107\u201d<\/i>. \u0141adunek wiadomo\u015bci jest wysy\u0142any jako warto\u015b\u0107 (value). Klucz, z drugiej strony, u\u017cywany jest g\u0142\u00f3wnie do partycjonowania i powinien zawiera\u0107 <i>specyficzny dla logiki biznesowej klucz<\/i>, aby umie\u015bci\u0107 powi\u0105zane wiadomo\u015bci w tej samej partycji.<\/p>\n<p>W Rozdziale 2 omawiali\u015bmy scenariusz zak\u0142ad\u00f3w online, w kt\u00f3rym powi\u0105zane zdarzenia musz\u0105 by\u0107 przetwarzane w porz\u0105dku przez jednego konsumenta:<\/p>\n<ol>\n<li>Konto u\u017cytkownika jest skonfigurowane.<\/li>\n<li>Pieni\u0105dze s\u0105 wp\u0142acane na konto.<\/li>\n<li>Sk\u0142adany jest zak\u0142ad, kt\u00f3ry wyci\u0105ga pieni\u0105dze z konta.<\/li>\n<\/ol>\n<p>\nJe\u015bli ka\u017cde zdarzenie jest wiadomo\u015bci\u0105 wysy\u0142an\u0105 do tematu, w tym przypadku naturalnym kluczem b\u0119dzie identyfikator konta.<br \/>\nGdy wiadomo\u015b\u0107 jest wysy\u0142ana za pomoc\u0105 Kafka Producer API, jest przekazywana do funkcji partycjonowania, kt\u00f3ra, bior\u0105c pod uwag\u0119 wiadomo\u015b\u0107 i aktualny stan klastra Kafka, zwraca identyfikator partycji, do kt\u00f3rej powinno zosta\u0107 wys\u0142ane to wiadomo\u015b\u0107. Ta funkcja jest zaimplementowana w Javie przez interfejs Partitioner.<\/p>\n<p>Ten interfejs wygl\u0105da nast\u0119puj\u0105co:<\/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>\nImplementacja Partitioner do okre\u015blenia partycji u\u017cywa domy\u015blnie algorytmu haszowania klucza (og\u00f3lny algorytm haszowania na podstawie klucza) lub algorytmu round-robin, je\u015bli klucz nie jest podany. Ta warto\u015b\u0107 domy\u015blna dzia\u0142a dobrze w wi\u0119kszo\u015bci przypadk\u00f3w. Jednak w przysz\u0142o\u015bci mo\u017cesz chcie\u0107 napisa\u0107 swoj\u0105 w\u0142asn\u0105.<\/p>\n<h3>Pisanie w\u0142asnej strategii partycjonowania<\/h3>\n<p>\nRozwa\u017cmy przyk\u0142ad, w kt\u00f3rym chcesz wys\u0142a\u0107 metadane razem z \u0142adunkiem u\u017cytecznym wiadomo\u015bci. \u0141adunek w naszym przyk\u0142adzie to instrukcja deponowania na konto do gry. Instrukcja to co\u015b, co chcieliby\u015bmy zagwarantowa\u0107, \u017ce nie zostanie zmodyfikowane podczas przesy\u0142ania i chcemy mie\u0107 pewno\u015b\u0107, \u017ce tylko zaufany zewn\u0119trzny system mo\u017ce zainicjowa\u0107 t\u0119 instrukcj\u0119. W takim przypadku systemy wysy\u0142aj\u0105ce i odbieraj\u0105ce uzgadniaj\u0105 u\u017cycie podpisu w celu weryfikacji autentyczno\u015bci wiadomo\u015bci.<br \/>\nW standardowym JMS po prostu definiujemy w\u0142a\u015bciwo\u015b\u0107 \u201epodpis wiadomo\u015bci\u201d i dodajemy j\u0105 do wiadomo\u015bci. Jednak Kafka nie zapewnia nam mechanizmu do przesy\u0142ania metadanych - tylko klucz i warto\u015b\u0107.<\/p>\n<p>Poniewa\u017c warto\u015b\u0107 to \u0142adunek u\u017cyteczny przelewu bankowego (bank transfer payload), kt\u00f3rego integralno\u015b\u0107 chcemy zachowa\u0107, nie mamy innego wyj\u015bcia poza zdefiniowanie struktury danych do u\u017cycia w kluczu. Zak\u0142adaj\u0105c, \u017ce potrzebujemy identyfikatora konta do partycjonowania, poniewa\u017c wszystkie wiadomo\u015bci zwi\u0105zane z kontem musz\u0105 by\u0107 przetwarzane w odpowiedniej kolejno\u015bci, wymy\u015blimy nast\u0119puj\u0105c\u0105 struktur\u0119 JSON:<\/p>\n<pre><code class=\"json\">{\n  \"signature\": \"541661622185851c248b41bf0cea7ad0\",\n  \"accountId\": \"10007865234\"\n}<\/code><\/pre>\n<p>\nPoniewa\u017c warto\u015b\u0107 podpisu b\u0119dzie si\u0119 r\u00f3\u017cni\u0107 w zale\u017cno\u015bci od \u0142adunku, domy\u015blna strategia haszowania interfejsu Partitioner nie b\u0119dzie skutecznie grupowa\u0107 powi\u0105zanych wiadomo\u015bci. Dlatego musimy napisa\u0107 w\u0142asn\u0105 strategi\u0119, kt\u00f3ra b\u0119dzie analizowa\u0107 ten klucz i partycjonowa\u0107 (partition) warto\u015b\u0107 accountId.<\/p>\n<blockquote><p>Kafka zawiera sumy kontrolne w celu wykrywania uszkodzenia wiadomo\u015bci w magazynie i ma pe\u0142ny zestaw funkcji zabezpiecze\u0144. Mimo to czasami pojawiaj\u0105 si\u0119 specyficzne wymagania bran\u017cowe, jak to wymienione powy\u017cej.<\/p><\/blockquote>\n<p>\nNiestandardowa strategia partycjonowania musi gwarantowa\u0107, \u017ce wszystkie powi\u0105zane wiadomo\u015bci trafi\u0105 do jednej partycji. Cho\u0107 wydaje si\u0119 to proste, wymaganie to mo\u017ce by\u0107 skomplikowane z uwagi na znaczenie uporz\u0105dkowania powi\u0105zanych wiadomo\u015bci i to, jak sztywna jest liczba partycji w temacie.<\/p>\n<p>Liczba partycji w temacie mo\u017ce zmienia\u0107 si\u0119 w czasie, poniewa\u017c mo\u017cna je doda\u0107, je\u015bli ruch przekracza pocz\u0105tkowe oczekiwania. W ten spos\u00f3b klucze wiadomo\u015bci mog\u0105 by\u0107 zwi\u0105zane z partycj\u0105, do kt\u00f3rej pierwotnie zosta\u0142y wys\u0142ane, co sugeruje cz\u0119\u015b\u0107 stanu, kt\u00f3ry powinien by\u0107 rozdzielony mi\u0119dzy instancje producenta.<\/p>\n<p>Innym czynnikiem, kt\u00f3ry nale\u017cy wzi\u0105\u0107 pod uwag\u0119, jest sprawiedliwo\u015b\u0107 rozk\u0142adu wiadomo\u015bci mi\u0119dzy partycje. Z regu\u0142y klucze nie s\u0105 rozdzielane r\u00f3wnomiernie w wiadomo\u015bciach, a funkcje haszuj\u0105ce nie gwarantuj\u0105 sprawiedliwego rozk\u0142adu wiadomo\u015bci dla ma\u0142ego zestawu kluczy.<br \/>\nWa\u017cne jest, aby zwr\u00f3ci\u0107 uwag\u0119 na to, \u017ce niezale\u017cnie od tego, jak postanowisz podzieli\u0107 wiadomo\u015bci, separator mo\u017ce by\u0107 konieczny do ponownego u\u017cycia.<\/p>\n<p>Rozwa\u017cmy wym\u00f3g replikacji danych pomi\u0119dzy klastrami Kafka w r\u00f3\u017cnych lokalizacjach geograficznych. W tym celu Kafka dostarcza narz\u0119dzie wiersza polece\u0144 o nazwie MirrorMaker, kt\u00f3re s\u0142u\u017cy do odczytywania wiadomo\u015bci z jednego klastra i przesy\u0142ania ich do drugiego.<\/p>\n<p>MirrorMaker musi rozumie\u0107 klucze replikowanego tematu, aby zachowa\u0107 wzgl\u0119dn\u0105 kolejno\u015b\u0107 wiadomo\u015bci podczas replikacji mi\u0119dzy klastrami, poniewa\u017c liczba partycji dla tego tematu mo\u017ce by\u0107 r\u00f3\u017cna w obu klastrach.<\/p>\n<p>W\u0142asne strategie partycjonowania wyst\u0119puj\u0105 stosunkowo rzadko, poniewa\u017c domy\u015blne metody, takie jak haszowanie lub cykliczne przypisanie, skutecznie dzia\u0142aj\u0105 w wi\u0119kszo\u015bci scenariuszy. Jednak je\u015bli potrzebujesz \u015bcis\u0142ych gwarancji porz\u0105dkowania lub musisz wydoby\u0107 metadane z \u0142adunk\u00f3w, partycjonowanie to co\u015b, na co warto zwr\u00f3ci\u0107 wi\u0119ksz\u0105 uwag\u0119.<\/p>\n<p>Zalety skalowalno\u015bci i wydajno\u015bci Kafki wynikaj\u0105 z przeniesienia niekt\u00f3rych obowi\u0105zk\u00f3w tradycyjnego brokera na klienta. W takim przypadku podejmuje si\u0119 decyzj\u0119 o rozdzieleniu potencjalnie zwi\u0105zanych wiadomo\u015bci mi\u0119dzy kilkoma konsumuj\u0105cymi, dzia\u0142aj\u0105cymi r\u00f3wnolegle.<\/p>\n<blockquote><p>Brokerzy JMS r\u00f3wnie\u017c musz\u0105 radzi\u0107 sobie z takimi wymaganiami. Co ciekawe, mechanizm przesy\u0142ania zwi\u0105zanych wiadomo\u015bci do tego samego konsumenta, zrealizowany za pomoc\u0105 grup wiadomo\u015bci JMS (rodzaj strategii balansowania obci\u0105\u017cenia typu sticky load balancing (SLB)), wymaga r\u00f3wnie\u017c, aby nadawca oznacza\u0142 wiadomo\u015bci jako powi\u0105zane. W przypadku JMS broker odpowiada za przesy\u0142anie tej grupy zwi\u0105zanych wiadomo\u015bci do jednego z wielu konsument\u00f3w oraz za przekazywanie praw w\u0142asno\u015bci grupy, je\u015bli konsument si\u0119 roz\u0142\u0105czy.<\/p><\/blockquote>\n<p><\/p>\n<h2>Ustalenia dotycz\u0105ce producenta<\/h2>\n<p>\nPartycjonowanie to nie jedyne, co nale\u017cy wzi\u0105\u0107 pod uwag\u0119 przy wysy\u0142aniu wiadomo\u015bci. Przyjrzyjmy si\u0119 metodom send() klasy Producer w API Java:<\/p>\n<pre><code class=\"java\">Future  send(ProducerRecord  record);\nFuture  send(ProducerRecord  record, Callback callback);<\/code><\/pre>\n<p>\nNale\u017cy od razu zauwa\u017cy\u0107, \u017ce obie metody zwracaj\u0105 Future, co wskazuje, \u017ce operacja wysy\u0142ania nie jest wykonywana natychmiastowo. W rezultacie wiadomo\u015b\u0107 (ProducerRecord) jest zapisywana w buforze wysy\u0142ania dla ka\u017cdej aktywnej partycji i przekazywana brokerowi w tle przez bibliotek\u0119 klienta Kafka. Cho\u0107 czyni to prac\u0119 niezwykle szybk\u0105, oznacza to, \u017ce \u017ale napisane aplikacje mog\u0105 traci\u0107 wiadomo\u015bci, je\u015bli ich proces zostanie zatrzymany.<\/p>\n<p>Jak zawsze, istnieje spos\u00f3b, aby uczyni\u0107 operacj\u0119 wysy\u0142ania bardziej niezawodn\u0105 kosztem wydajno\u015bci. Rozmiar tego bufora mo\u017cna ustawi\u0107 na 0, a w\u0105tek aplikacji wysy\u0142aj\u0105cej b\u0119dzie musia\u0142 poczeka\u0107, a\u017c przesy\u0142anie wiadomo\u015bci do brokera zostanie zako\u0144czone w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n<pre><code class=\"java\">RecordMetadata metadata = producer.send(record).get();<\/code><\/pre>\n<p><\/p>\n<h2>Jeszcze raz o odczytywaniu wiadomo\u015bci<\/h2>\n<p>\nOdczytywanie wiadomo\u015bci ma dodatkowe z\u0142o\u017cono\u015bci, nad kt\u00f3rymi trzeba si\u0119 zastanowi\u0107. W przeciwie\u0144stwie do API JMS, kt\u00f3re mo\u017ce uruchomi\u0107 nas\u0142uchiwacz wiadomo\u015bci (message listener) w odpowiedzi na otrzymanie wiadomo\u015bci, interfejs <i>Consumer <\/i>Kafka tylko polluje (polling). Przyjrzyjmy si\u0119 bli\u017cej metodzie <i>poll ()<\/i>, u\u017cywanej do tego celu:<\/p>\n<pre><code class=\"java\">ConsumerRecords  poll(long timeout);<\/code><\/pre>\n<p>\nWarto\u015bci\u0105 zwracan\u0105 przez metod\u0119 jest struktura kontenerowa zawieraj\u0105ca wiele obiekt\u00f3w <i>ConsumerRecord <\/i>z potencjalnie wielu partycji. <i>ConsumerRecord <\/i>jest sam w sobie obiektem przechowuj\u0105cym par\u0119 klucz-warto\u015b\u0107 z odpowiednimi metadanymi, takimi jak partycja, z kt\u00f3rej zosta\u0142 pobrany.<\/p>\n<p>Jak om\u00f3wiono w Rozdziale 2, musimy nieustannie pami\u0119ta\u0107, co dzieje si\u0119 z wiadomo\u015bciami po ich pomy\u015blnym lub niepomy\u015blnym przetworzeniu, na przyk\u0142ad je\u015bli klient nie mo\u017ce przetworzy\u0107 wiadomo\u015bci lub je\u015bli przerywa dzia\u0142anie. W JMS by\u0142o to obs\u0142ugiwane za pomoc\u0105 trybu potwierdzenia (acknowledgement mode). Broker albo usuni\u0119je pomy\u015blnie przetworzon\u0105 wiadomo\u015b\u0107, albo ponownie dostarcza nieprzetworzon\u0105 lub zepsut\u0105 (pod warunkiem, \u017ce u\u017cyto transakcji). <br \/>\nKafka dzia\u0142a zupe\u0142nie inaczej. Wiadomo\u015bci nie s\u0105 usuwane w brokerze po odczytaniu, a odpowiedzialno\u015b\u0107 za to, co dzieje si\u0119 w przypadku awarii, spoczywa na samym kodzie odczytuj\u0105cym.<\/p>\n<p>Jak ju\u017c wspomniano, grupa konsument\u00f3w jest zwi\u0105zana z przesuni\u0119ciem w dzienniku. Pozycja w dzienniku zwi\u0105zana z tym przesuni\u0119ciem odpowiada nast\u0119pnej wiadomo\u015bci, kt\u00f3ra zostanie wydana w odpowiedzi na <i>poll ()<\/i>Decyduj\u0105ce znaczenie w trakcie czytania ma moment, w kt\u00f3rym to przesuni\u0119cie wzrasta.<\/p>\n<p>Wracaj\u0105c do modelu czytania, rozwa\u017canego wcze\u015bniej, przetwarzanie komunikatu sk\u0142ada si\u0119 z trzech etap\u00f3w:<\/p>\n<ol>\n<li>Wyodr\u0119bni\u0107 komunikat do przeczytania.<\/li>\n<li>Przetworzy\u0107 komunikat.<\/li>\n<li>Potwierdzi\u0107 komunikat.<\/li>\n<\/ol>\n<p>\nKonsument Kafka jest wyposa\u017cony w opcj\u0119 konfiguracyjn\u0105 <i>enable.auto.commit<\/i>. To cz\u0119sto u\u017cywane ustawienie domy\u015blne, jak to zwykle bywa w przypadku ustawie\u0144 zawieraj\u0105cych s\u0142owo \u201eauto\u201d.<\/p>\n<p>Do wersji Kafka 0.10 klient, kt\u00f3ry u\u017cywa\u0142 tego parametru, przesy\u0142a\u0142 przesuni\u0119cie ostatnio przeczytanego komunikatu przy nast\u0119pnym wywo\u0142aniu <i>poll ()<\/i> po przetworzeniu. Oznacza\u0142o to, \u017ce wszelkie komunikaty, kt\u00f3re ju\u017c zosta\u0142y wyodr\u0119bnione (fetched), mog\u0142y by\u0107 przetwarzane ponownie, je\u015bli klient je ju\u017c przetworzy\u0142, ale zosta\u0142 niespodziewanie zniszczony przed wywo\u0142aniem <i>poll ()<\/i>. Poniewa\u017c broker nie przechowuje \u017cadnego stanu dotycz\u0105cego tego, ile razy wiadomo\u015b\u0107 zosta\u0142a przeczytana, nast\u0119pny konsument, kt\u00f3ry pobiera t\u0119 wiadomo\u015b\u0107, nie b\u0119dzie wiedzia\u0142, \u017ce mia\u0142o miejsce co\u015b z\u0142ego. To zachowanie by\u0142o pseudo-transakcyjne. Przesuni\u0119cie by\u0142o zatwierdzane tylko w przypadku pomy\u015blnego przetworzenia wiadomo\u015bci, ale je\u015bli klient przerwa\u0142 prac\u0119, broker ponownie wysy\u0142a\u0142 t\u0119 sam\u0105 wiadomo\u015b\u0107 innemu klientowi. To zachowanie odpowiada\u0142o gwarancji dostarczania wiadomo\u015bci \u201e<i>co najmniej raz<\/i>&#171;.<\/p>\n<p>W wersji Kafka 0.10 kod klienta zosta\u0142 zmieniony w taki spos\u00f3b, \u017ce zatwierdzanie sta\u0142o si\u0119 okresowo uruchamiane przez bibliotek\u0119 klienta, zgodnie z ustawieniem <i>auto.commit.interval.ms<\/i>. To zachowanie znajduje si\u0119 gdzie\u015b pomi\u0119dzy trybami JMS AUTO_ACKNOWLEDGE a DUPS_OK_ACKNOWLEDGE. Przy u\u017cyciu automatycznego zatwierdzenia komunikaty mog\u0142y by\u0107 potwierdzane niezale\u017cnie od tego, czy zosta\u0142y faktycznie przetworzone \u2014 mog\u0142o to wyst\u0105pi\u0107 w przypadku wolnego konsumenta. Je\u015bli konsument przerywa\u0142 dzia\u0142anie, komunikaty by\u0142y wyodr\u0119bniane przez kolejnego konsumenta, zaczynaj\u0105c od zatwierdzonej pozycji, co mog\u0142o prowadzi\u0107 do pomini\u0119cia komunikatu. W takim przypadku Kafka nie traci\u0142a komunikat\u00f3w, kod odczytuj\u0105cy po prostu ich nie przetwarza\u0142.<\/p>\n<p>Ten tryb ma te same perspektywy, co w wersji 0.9: komunikaty mog\u0105 by\u0107 przetwarzane, ale w przypadku awarii przesuni\u0119cie mo\u017ce nie by\u0107 zatwierdzone, co potencjalnie mo\u017ce prowadzi\u0107 do podw\u00f3jnego dostarczenia. Im wi\u0119cej komunikat\u00f3w wyodr\u0119bniasz podczas wykonywania <i>poll ()<\/i>, tym wi\u0119kszy jest ten problem.<\/p>\n<p>Jak om\u00f3wiono w rozdziale \u201eOdczytywanie wiadomo\u015bci z kolejki\u201d na str. 21, w systemie wymiany wiadomo\u015bci nie ma poj\u0119cia jednorazowej dostawy wiadomo\u015bci, je\u015bli uwzgl\u0119dni\u0107 tryby awarii.<\/p>\n<p>W Kafka istniej\u0105 dwa sposoby na zarejestrowanie (zatwierdzenie) przesuni\u0119cia (offsetu): automatycznie i r\u0119cznie. W obu przypadkach wiadomo\u015bci mog\u0105 by\u0107 przetwarzane wielokrotnie, je\u015bli wiadomo\u015b\u0107 zosta\u0142a przetworzona, ale wyst\u0105pi\u0142 b\u0142\u0105d przed zatwierdzeniem. Mo\u017cesz tak\u017ce w og\u00f3le nie przetwarza\u0107 wiadomo\u015bci, je\u015bli zatwierdzenie nast\u0105pi\u0142o w tle, a tw\u00f3j kod zako\u0144czy\u0142 si\u0119 zanim zacz\u0105\u0142 przetwarzanie (mo\u017cliwe w Kafka 0.9 i wcze\u015bniejszych wersjach).<\/p>\n<p>Mo\u017cna r\u0119cznie zarz\u0105dza\u0107 procesem zatwierdzania offsetu w API konsumenta Kafka, ustawiaj\u0105c parametr <i>enable.auto.commit<\/i> na warto\u015b\u0107 false i jawnie wywo\u0142uj\u0105c jedn\u0105 z nast\u0119puj\u0105cych metod:<\/p>\n<pre><code class=\"java\">void commitSync();\nvoid commitAsync();<\/code><\/pre>\n<p>\nJe\u015bli chcesz przetworzy\u0107 wiadomo\u015b\u0107 \u201eprzynajmniej raz\u201d, musisz r\u0119cznie zatwierdzi\u0107 offset za pomoc\u0105 <i>commitSync ()<\/i>, wykonuj\u0105c t\u0119 komend\u0119 zaraz po przetworzeniu wiadomo\u015bci.<\/p>\n<p>Te metody nie pozwalaj\u0105 na potwierdzanie (acknowledged) wiadomo\u015bci, zanim zostan\u0105 przetworzone, ale nic nie robi\u0105, aby unikn\u0105\u0107 potencjalnego podw\u00f3jnego przetworzenia, tworz\u0105c jednocze\u015bnie wra\u017cenie transakcyjno\u015bci. W Kafka nie ma transakcji. Klient nie ma mo\u017cliwo\u015bci wykonania nast\u0119puj\u0105cych czynno\u015bci:<\/p>\n<ul>\n<li>Automatycznie cofn\u0105\u0107 (roll back) nieudane wiadomo\u015bci. Konsumenci musz\u0105 samodzielnie radzi\u0107 sobie z wyj\u0105tkami wynikaj\u0105cymi z problematycznych \u0142adunk\u00f3w i roz\u0142\u0105cze\u0144 backendu, poniewa\u017c nie mog\u0105 polega\u0107 na ponownej dostawie wiadomo\u015bci przez brokera.<\/li>\n<li>Wysy\u0142a\u0107 wiadomo\u015bci do kilku temat\u00f3w w jednej atomowej operacji. Jak wkr\u00f3tce zobaczymy, kontrola nad r\u00f3\u017cnymi tematami i partycjami mo\u017ce znajdowa\u0107 si\u0119 na r\u00f3\u017cnych maszynach w klastrze Kafka, kt\u00f3re nie koordynuj\u0105 transakcji przy wysy\u0142aniu. W momencie pisania tego artyku\u0142u wykonano pewn\u0105 prac\u0119, aby to umo\u017cliwi\u0107 dzi\u0119ki KIP-98.<\/li>\n<li>Powi\u0105za\u0107 odczyt jednej wiadomo\u015bci z jednego tematu z wys\u0142aniem innej wiadomo\u015bci do innego tematu. Jeszcze raz, architektura Kafka opiera si\u0119 na wielu niezale\u017cnych maszynach dzia\u0142aj\u0105cych jak jeden szynowy system i nie podejmuje si\u0119 \u017cadnych pr\u00f3b ukrycia tego. Na przyk\u0142ad nie ma komponent\u00f3w API, kt\u00f3re pozwala\u0142yby powi\u0105za\u0107 <i>Konsument <\/i>i <i>Producent <\/i>w transakcji. W JMS zapewnia to obiekt <i>Sesja<\/i>, z kt\u00f3rego s\u0105 tworzone <i>MessageProducers <\/i>i <i>MessageConsumers<\/i>.<\/li>\n<\/ul>\n<p>\nJe\u015bli nie mo\u017cemy polega\u0107 na transakcjach, jak mo\u017cemy zapewni\u0107 semantyk\u0119, bli\u017csz\u0105 tej, kt\u00f3r\u0105 oferuj\u0105 tradycyjne systemy wymiany wiadomo\u015bci?<\/p>\n<p>Je\u015bli istnieje prawdopodobie\u0144stwo, \u017ce offset konsumenta mo\u017ce wzrosn\u0105\u0107 zanim wiadomo\u015b\u0107 zostanie przetworzona, np. podczas awarii konsumenta, to konsument nie ma sposobu, aby dowiedzie\u0107 si\u0119, czy jego grupa konsument\u00f3w pomin\u0119\u0142a wiadomo\u015bci, gdy przypisano jej partycj\u0119. W ten spos\u00f3b jedna ze strategii polega na przewini\u0119ciu offsetu do poprzedniej pozycji. API konsumenta Kafka oferuje nast\u0119puj\u0105ce metody do tego:<\/p>\n<pre><code class=\"java\">void seek(TopicPartition partition, long offset);\nvoid seekToBeginning(Collection  partitions);<\/code><\/pre>\n<p>\nMetoda <i>seek ()<\/i> mo\u017ce by\u0107 u\u017cywana z metod\u0105 <br \/>\n<i>offsetsForTimes (Map timestampsToSearch)<\/i> aby przewin\u0105\u0107 do stanu w okre\u015blonym momencie w przesz\u0142o\u015bci.<\/p>\n<p>Niejawnie, u\u017cycie tego podej\u015bcia oznacza, \u017ce jest bardzo prawdopodobne, i\u017c niekt\u00f3re wiadomo\u015bci, kt\u00f3re zosta\u0142y wcze\u015bniej przetworzone, zostan\u0105 odczytane i przetworzone ponownie. Aby tego unikn\u0105\u0107, mo\u017cemy zastosowa\u0107 idempotentne odczyty, jak opisano w Rozdziale 4, aby \u015bledzi\u0107 wcze\u015bniej wy\u015bwietlane wiadomo\u015bci i wyklucza\u0107 duplikaty.<\/p>\n<p>Alternatywnie, kod twojego konsumenta mo\u017ce by\u0107 prosty, je\u015bli dopuszczalna jest utrata lub duplikacja wiadomo\u015bci. Kiedy rozwa\u017camy przypadki u\u017cycia, dla kt\u00f3rych zazwyczaj wykorzystywana jest Kafka, takie jak przetwarzanie zdarze\u0144 log\u00f3w, metryk, \u015bledzenie klikni\u0119\u0107 itd., rozumiemy, \u017ce utrata pojedynczych wiadomo\u015bci raczej nie wp\u0142ynie znacz\u0105co na otaczaj\u0105ce aplikacje. W takich przypadkach warto\u015bci domy\u015blne s\u0105 jak najbardziej akceptowalne. Z drugiej strony, je\u015bli twoja aplikacja musi przesy\u0142a\u0107 p\u0142atno\u015bci, powiniene\u015b starannie dba\u0107 o ka\u017cd\u0105 pojedyncz\u0105 wiadomo\u015b\u0107. Wszystko sprowadza si\u0119 do kontekstu.<\/p>\n<p>Osobiste obserwacje pokazuj\u0105, \u017ce wraz ze wzrostem intensywno\u015bci wiadomo\u015bci, warto\u015b\u0107 ka\u017cdej pojedynczej wiadomo\u015bci maleje. Wiadomo\u015bci du\u017cych obj\u0119to\u015bci staj\u0105 si\u0119 zazwyczaj cenne, je\u015bli s\u0105 rozpatrywane w formie skonsolidowanej.<\/p>\n<h2>Wysoka dost\u0119pno\u015b\u0107 (High Availability)<\/h2>\n<p>\nPodej\u015bcie Kafka do zapewnienia wysokiej dost\u0119pno\u015bci znacznie r\u00f3\u017cni si\u0119 od podej\u015bcia ActiveMQ. Kafka zosta\u0142a zaprojektowana na bazie poziomo skalowalnych klastr\u00f3w, w kt\u00f3rych wszystkie instancje brokera jednocze\u015bnie przyjmuj\u0105 i przekazuj\u0105 wiadomo\u015bci.<\/p>\n<p>Klastor Kafka sk\u0142ada si\u0119 z kilku instancji brokera dzia\u0142aj\u0105cych na r\u00f3\u017cnych serwerach. Kafka zosta\u0142a zaprojektowana do dzia\u0142ania na standardowym sprz\u0119cie autonomicznym, gdzie ka\u017cdy w\u0119ze\u0142 ma w\u0142asne, dedykowane miejsce do przechowywania. U\u017cycie sieciowych magazyn\u00f3w (SAN) nie jest zalecane, poniewa\u017c wiele w\u0119z\u0142\u00f3w obliczeniowych mo\u017ce konkurowa\u0107 o czasowe interwa\u0142y przechowywania i powodowa\u0107 konflikty.<i>Y<\/i>e interwa\u0142y przechowywania i tworzy\u0107 konflikty.<\/p>\n<p>Kafka to <i>system ci\u0105gle w\u0142\u0105czony.<\/i> Wielu du\u017cych u\u017cytkownik\u00f3w Kafka nigdy nie wy\u0142\u0105cza swoich klastr\u00f3w, a oprogramowanie zapewnia aktualizacj\u0119 poprzez sekwencyjne ponowne uruchamianie. Osi\u0105ga si\u0119 to przez zapewnienie zgodno\u015bci z poprzedni\u0105 wersj\u0105 dla wiadomo\u015bci i interakcji mi\u0119dzy brokerami.<\/p>\n<p>Brokerzy s\u0105 pod\u0142\u0105czeni do klastra serwer\u00f3w <noindex><a rel=\"nofollow\" href=\"http:\/\/zookeeper.apache.org\">ZooKeeper<\/a><\/noindex>, kt\u00f3ry dzia\u0142a jak rejestr danych konfiguracyjnych i jest u\u017cywany do koordynowania r\u00f3l ka\u017cdego brokera. ZooKeeper sam w sobie jest rozproszonym systemem, kt\u00f3ry zapewnia wysok\u0105 dost\u0119pno\u015b\u0107 poprzez replikacj\u0119 informacji poprzez ustanowienie <i>kwarum<\/i>.<\/p>\n<p>W podstawowym przypadku temat jest tworzony w klastrze Kafka z nast\u0119puj\u0105cymi w\u0142a\u015bciwo\u015bciami:<\/p>\n<ul>\n<li>Liczba partycji. Jak om\u00f3wiono wcze\u015bniej, dok\u0142adna warto\u015b\u0107 u\u017cywana tutaj zale\u017cy od po\u017c\u0105danego poziomu r\u00f3wnoleg\u0142ego odczytu.<\/li>\n<li>Wsp\u00f3\u0142czynnik (czynnik) replikacji okre\u015bla, ile instancji brokera w klastrze powinno przechowywa\u0107 dzienniki dla tej partycji.<\/li>\n<\/ul>\n<p>\nKorzystaj\u0105c z ZooKeepers do koordynacji, Kafka stara si\u0119 sprawiedliwie rozdzieli\u0107 nowe partycje mi\u0119dzy brokerami w klastrze. Robi to jeden z broker\u00f3w, kt\u00f3ry pe\u0142ni rol\u0119 Kontrolera.<\/p>\n<p>W czasie wykonania <i>dla ka\u017cdej partycji tematu<\/i> <i>Kontroler <\/i>przydziela brokerowi role <i>lidera <\/i>(leader, master, wiod\u0105cy) oraz <i>na\u015bladowc\u00f3w <\/i>(followers, slaves, podrz\u0119dnych). Broker, pe\u0142ni\u0105cy rol\u0119 lidera dla danej partycji, odpowiada za przyjmowanie wszystkich wiadomo\u015bci wysy\u0142anych mu przez producent\u00f3w i dystrybucj\u0119 wiadomo\u015bci do konsument\u00f3w. Gdy wiadomo\u015bci s\u0105 wysy\u0142ane do partycji tematu, s\u0105 replikowane na wszystkich w\u0119z\u0142ach brokera, pe\u0142ni\u0105cych rol\u0119 na\u015bladowc\u00f3w dla tej partycji. Ka\u017cdy w\u0119ze\u0142, kt\u00f3ry zawiera dzienniki dla partycji, nazywany jest <i>replik\u0105<\/i>. Broker mo\u017ce pe\u0142ni\u0107 rol\u0119 lidera dla niekt\u00f3rych partycji i rol\u0119 na\u015bladowcy dla innych.<\/p>\n<p>Na\u015bladowca, kt\u00f3ry zawiera wszystkie wiadomo\u015bci przechowywane u lidera, nazywany jest <i>synchronizowan\u0105 replik\u0105<\/i> (replica, kt\u00f3ra jest w zsynchronizowanym stanie, in-sync replica). Je\u015bli broker, pe\u0142ni\u0105cy rol\u0119 lidera dla partycji, zostanie wy\u0142\u0105czony, ka\u017cdy broker, kt\u00f3ry jest w aktualizowanym lub zsynchronizowanym stanie dla tej partycji, mo\u017ce przej\u0105\u0107 rol\u0119 lidera. To niezwykle odporna konstrukcja.<\/p>\n<p>Cz\u0119\u015bci\u0105 konfiguracji producenta jest parametr <i>acks<\/i>, kt\u00f3ry okre\u015bla, ile replik musi potwierdzi\u0107 (acknowledge) otrzymanie wiadomo\u015bci, zanim strumie\u0144 aplikacji b\u0119dzie kontynuowa\u0142 wysy\u0142anie: 0, 1 lub wszystkie. Je\u015bli warto\u015b\u0107 <i>wszystko<\/i>jest ustawiona, to po otrzymaniu wiadomo\u015bci lider wy\u015ble potwierdzenie (confirmation) z powrotem do producenta, jak tylko otrzyma potwierdzenia (acknowledgements) zapisu od kilku replik (w tym od samego siebie), okre\u015blonych ustawieniem tematu <i>min.insync.replicas<\/i> (domy\u015blnie 1). Je\u015bli wiadomo\u015b\u0107 nie mo\u017ce by\u0107 pomy\u015blnie replikowana, producent zg\u0142osi wyj\u0105tek dla aplikacji (<i>NotEnoughReplicas<\/i> lub <i>NotEnoughReplicasAfterAppend<\/i>).<\/p>\n<p>W typowej konfiguracji tworzony jest temat z wsp\u00f3\u0142czynnikiem replikacji 3 (1 lider, 2 na\u015bladowc\u00f3w dla ka\u017cdej partycji) i parametr <i>min.insync.replicas<\/i> jest ustawiony na warto\u015b\u0107 2. W takim przypadku klaster dopuszcza, aby jeden z broker\u00f3w zarz\u0105dzaj\u0105cych partycj\u0105 tematu m\u00f3g\u0142 zosta\u0107 wy\u0142\u0105czony bez wp\u0142ywu na aplikacje klienckie.<\/p>\n<p>To prowadzi nas z powrotem do znanego ju\u017c kompromisu mi\u0119dzy wydajno\u015bci\u0105 a niezawodno\u015bci\u0105. Replikacja odbywa si\u0119 z dodatkowym czasem oczekiwania na potwierdzenia (acknowledgments) od na\u015bladowc\u00f3w. Mimo to, poniewa\u017c odbywa si\u0119 r\u00f3wnolegle, replikacja, co najmniej na trzech w\u0119z\u0142ach, ma t\u0119 sam\u0105 wydajno\u015b\u0107 jak na dw\u00f3ch (ignoruj\u0105c wzrost wykorzystania przepustowo\u015bci sieci).<\/p>\n<p>Korzystaj\u0105c z tego schematu replikacji, Kafka zr\u0119cznie unika konieczno\u015bci zapewnienia fizycznego zapisu ka\u017cdej wiadomo\u015bci na dysku za pomoc\u0105 operacji <i>sync ()<\/i>. Ka\u017cda wiadomo\u015b\u0107 wys\u0142ana przez producenta b\u0119dzie zapisywana w dzienniku partycji, ale, jak om\u00f3wiono w Rozdziale 2, zapis do pliku pocz\u0105tkowo odbywa si\u0119 w buforze systemu operacyjnego. Je\u015bli ta wiadomo\u015b\u0107 zostanie zreplikowana na inn\u0105 instancj\u0119 Kafki i znajduje si\u0119 w jej pami\u0119ci, utrata lidera nie oznacza, \u017ce sama wiadomo\u015b\u0107 zosta\u0142a utracona \u2013 mo\u017ce j\u0105 przej\u0105\u0107 zsynchronizowana replika.<br \/>\nRezygnacja z konieczno\u015bci wykonania operacji <i>sync ()<\/i> oznacza, \u017ce Kafka mo\u017ce przyjmowa\u0107 wiadomo\u015bci z pr\u0119dko\u015bci\u0105, z jak\u0105 mo\u017ce je zapisywa\u0107 w pami\u0119ci. I odwrotnie, im d\u0142u\u017cej mo\u017cna unika\u0107 zrzucania (flushing) pami\u0119ci na dysk, tym lepiej. Z tego powodu nie jest rzadko\u015bci\u0105, \u017ce brokerom Kafki przydziela si\u0119 64 GB pami\u0119ci lub wi\u0119cej. Takie wykorzystanie pami\u0119ci oznacza, \u017ce jedna instancja Kafki mo\u017ce \u0142atwo dzia\u0142a\u0107 z pr\u0119dko\u015bciami wielokrotnie przekraczaj\u0105cymi tradycyjnego brokera wiadomo\u015bci.<\/p>\n<p>Kafka mo\u017ce by\u0107 r\u00f3wnie\u017c skonfigurowana do stosowania operacji <i>sync ()<\/i> na pakietach wiadomo\u015bci. Poniewa\u017c wszystko w Kafce jest zorientowane na prac\u0119 z pakietami, w rzeczywisto\u015bci dzia\u0142a to do\u015b\u0107 dobrze w wielu scenariuszach u\u017cycia i jest u\u017cytecznym narz\u0119dziem dla u\u017cytkownik\u00f3w, kt\u00f3rzy wymagaj\u0105 bardzo silnych gwarancji. Wi\u0119kszo\u015b\u0107 czystej wydajno\u015bci Kafki zwi\u0105zana jest z wiadomo\u015bciami, kt\u00f3re s\u0105 wysy\u0142ane do brokera w postaci pakiet\u00f3w, oraz z tym, \u017ce te wiadomo\u015bci s\u0105 odczytywane z brokera sekwencyjnie w blokach za pomoc\u0105 <noindex><a rel=\"nofollow\" href=\"http:\/\/www.linuxjournal.com\/article\/6345\">zero-copy<\/a><\/noindex> operacji (operacjami, w trakcie kt\u00f3rych nie wykonywana jest operacja kopiowania danych z jednej przestrzeni pami\u0119ci do drugiej). Ostatnie jest du\u017c\u0105 zalet\u0105 z punktu widzenia wydajno\u015bci i zasob\u00f3w i jest mo\u017cliwe tylko dzi\u0119ki zastosowaniu le\u017c\u0105cej u podstaw struktury danych dziennika, okre\u015blaj\u0105cej schemat partycji.<\/p>\n<p>W klastrze Kafka mo\u017cliwa jest znacznie wy\u017csza wydajno\u015b\u0107 ni\u017c przy u\u017cyciu jednego brokera Kafka, poniewa\u017c partycje tematu mog\u0105 by\u0107 poziomo skalowane na wielu oddzielnych maszynach.<\/p>\n<h2>Podsumowanie<\/h2>\n<p>\nW tej cz\u0119\u015bci rozdzia\u0142u om\u00f3wili\u015bmy, jak architektura Kafka reinterpretacja relacji mi\u0119dzy klientami a brokerami, aby zapewni\u0107 niezwykle niezawodny kana\u0142 wymiany wiadomo\u015bci, o przepustowo\u015bci wielokrotnie wy\u017cszej ni\u017c standardowy broker wiadomo\u015bci. Dyskutowali\u015bmy o funkcjonalno\u015bci, kt\u00f3r\u0105 wykorzystuje do osi\u0105gni\u0119cia tego celu oraz kr\u00f3tko przedstawili\u015bmy architektur\u0119 aplikacji zapewniaj\u0105cych t\u0119 funkcjonalno\u015b\u0107. W nast\u0119pnej cz\u0119\u015bci rozdzia\u0142u om\u00f3wimy powszechne problemy, kt\u00f3re musz\u0105 rozwi\u0105zywa\u0107 aplikacje oparte na wymianie wiadomo\u015bci, oraz przedyskutujemy strategie ich rozwi\u0105zywania. Zako\u0144czymy rozdzia\u0142, wskazuj\u0105c, jak rozumie\u0107 technologie wymiany wiadomo\u015bci jako ca\u0142o\u015b\u0107, aby m\u00f3c oceni\u0107 ich przydatno\u015b\u0107 do twoich scenariuszy u\u017cycia.<\/p>\n<p>Poprzednia przet\u0142umaczona cz\u0119\u015b\u0107: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci przy u\u017cyciu ActiveMQ i Kafka. Rozdzia\u0142 1<\/a><\/noindex><\/p>\n<p><b> T\u0142umaczenie wykonano: <noindex><a rel=\"nofollow\" href=\"http:\/\/tele.gg\/middle_java\">tele.gg\/middle_java<\/a><\/noindex><\/b><\/p>\n<p><i>Ci\u0105g dalszy nast\u0105pi\u2026<\/i><\/p>\n<p class=\"for_users_only_msg\">Tylko zarejestrowani u\u017cytkownicy mog\u0105 bra\u0107 udzia\u0142 w ankiecie. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Zaloguj si\u0119<\/a><\/noindex>, prosz\u0119.<\/p>\n<h2 class=\"default-block__polling-title\">Czy u\u017cywasz Kafka w swojej organizacji?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Tak<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Nie<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Kiedy\u015b u\u017cywane, teraz nie<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Planujemy u\u017cywa\u0107<\/p>\n<\/li>\n<\/ul>\n<p>    38 u\u017cytkownik\u00f3w zag\u0142osowa\u0142o. 8 u\u017cytkownik\u00f3w wstrzyma\u0142o si\u0119 od g\u0142osu.<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <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.1.1 - 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\/pl\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\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\/pl\/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\udd47Zrozumienie broker\u00f3w wiadomo\u015bci. Badanie mechaniki wymiany wiadomo\u015bci przy u\u017cyciu ActiveMQ i Kafka. Rozdzia\u0142 3. Kafka | ProHoster","description":"Kontynuacja t\u0142umaczenia ma\u0142ej ksi\u0105\u017cki: \u201eZrozumienie broker\u00f3w wiadomo\u015bci\u201d, autor: Jakub Korab, wydawnictwo: O'Reilly Media, Inc., data wydania: czerwiec 2017, ISBN: 9781492049296. Poprzednia przet\u0142umaczona.","canonical_url":"https:\/\/prohoster.info\/pl\/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":"pl_PL","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\/pl\/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\/pl\/wp-json\/wp\/v2\/posts\/38172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=38172"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/38172\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=38172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=38172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=38172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}