{"id":18714,"date":"2025-03-24T15:59:33","date_gmt":"2025-03-24T13:59:33","guid":{"rendered":"https:\/\/inteca.com\/?p=18714"},"modified":"2025-10-26T15:58:55","modified_gmt":"2025-10-26T13:58:55","slug":"apache-kafka-w-praktyce","status":"publish","type":"technical-blog","link":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/","title":{"rendered":"Apache Kafka w praktyce"},"content":{"rendered":"<p>Systemy komunikacji zdarzeniowej (Message Brokers) umo\u017cliwiaj\u0105 lu\u017ane powi\u0105zanie mi\u0119dzy us\u0142ugami i komponentami w organizacji lub projekcie, zapewniaj\u0105c jednocze\u015bnie asynchroniczn\u0105 komunikacj\u0119, skalowalno\u015b\u0107, wysok\u0105 przepustowo\u015b\u0107, niezawodno\u015b\u0107 oraz bezpiecze\u0144stwo przesy\u0142anych danych.<\/p>\n<p>Apache Kafka to jeden z najpopularniejszych broker\u00f3w wiadomo\u015bci, znany ze swojej wydajno\u015bci i szeroko stosowany przez firmy takie jak Netflix, Uber czy LinkedIn. Ale czy rzeczywi\u015bcie spe\u0142nia te oczekiwania? Czy zapewnia bezpiecze\u0144stwo danych, skalowalno\u015b\u0107 i niezawodno\u015b\u0107? Czy dzia\u0142a optymalnie od razu po instalacji, czy wymaga dodatkowej konfiguracji?<\/p>\n<h2>Architektura Apache Kafka<\/h2>\n<p>W tej sekcji przedstawi\u0119 i kr\u00f3tko om\u00f3wi\u0119 komponenty sk\u0142adaj\u0105ce si\u0119 na typow\u0105 instalacj\u0119 Apache Kafka. Zrozumienie ich dzia\u0142ania u\u0142atwi nam dalsz\u0105 analiz\u0119 funkcjonalno\u015bci i mo\u017cliwo\u015bci konfiguracji Kafki.<\/p>\n<h3>Jakie s\u0105 podstawowe komponenty Apache Kafka?<\/h3>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18718 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/1.png\" alt=\"Apache Kafka components diagram\" width=\"1248\" height=\"568\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/1.png 1248w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/1-300x137.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/1-1024x466.png 1024w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/1-768x350.png 768w\" sizes=\"(max-width: 1248px) 100vw, 1248px\" \/><\/p>\n<p>Powy\u017cszy diagram przedstawia typowe elementy sk\u0142adowe instalacji Apache Kafka. Kluczowym sk\u0142adnikiem jest klaster Kafka, kt\u00f3ry sk\u0142ada si\u0119 z broker\u00f3w \u2013 serwer\u00f3w odpowiedzialnych za przechowywanie i przetwarzanie danych.<\/p>\n<p>Klaster zarz\u0105dzany jest przez Apache Zookeeper (od wersji 2.8.0 wprowadzono alternatywne <a href=\"https:\/\/inteca.com\/pl\/blog\/blog\/sinf-reporter-rozwiazanie-na-zapytania-o-dane-finansowe\/\">rozwi\u0105zanie \u2013<\/a> Kafka Kraft, kt\u00f3re eliminuje konieczno\u015b\u0107 korzystania z Zookeepera; od wersji 3.5.0 Zookeeper zosta\u0142 oznaczony jako <em>deprecated<\/em>).<\/p>\n<p>Ka\u017cdy broker przechowuje dane w topicach, kt\u00f3re s\u0105 podzielone na partycje. Podzia\u0142 topicu na partycje odgrywa kluczow\u0105 rol\u0119 w skalowalno\u015bci i wydajno\u015bci Kafki, poniewa\u017c umo\u017cliwia r\u00f3wnoleg\u0142e przetwarzanie danych przez wielu konsument\u00f3w.<\/p>\n<h3>Czym jest partycjonowanie i kolejno\u015b\u0107 wiadomo\u015bci?<\/h3>\n<p>Podczas zapisywania wiadomo\u015bci do topicu Kafka przypisuje je do konkretnej partycji na podstawie jednej z dw\u00f3ch mo\u017cliwo\u015bci:<\/p>\n<ul>\n<li>Klucza partycjonowania \u2013 je\u015bli jest okre\u015blony, wszystkie wiadomo\u015bci z tym samym kluczem trafiaj\u0105 do tej samej partycji.<\/li>\n<li>Algorytmu <em>round-robin<\/em> \u2013 je\u015bli klucz nie jest okre\u015blony, Kafka rozdziela wiadomo\u015bci r\u00f3wnomiernie pomi\u0119dzy dost\u0119pne partycje.<\/li>\n<\/ul>\n<p>W obr\u0119bie pojedynczej partycji Kafka gwarantuje zachowanie kolejno\u015bci wiadomo\u015bci (wed\u0142ug momentu zapisu), natomiast nie zapewnia globalnej kolejno\u015bci mi\u0119dzy r\u00f3\u017cnymi partycjami tego samego topicu. Ka\u017cda wiadomo\u015b\u0107 w partycji posiada unikalny identyfikator zwany offsetem, kt\u00f3ry pozwala na \u015bledzenie przetwarzania danych przez konsument\u00f3w.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18720 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/2.png\" alt=\"\" width=\"780\" height=\"328\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/2.png 780w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/2-300x126.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/2-768x323.png 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/p>\n<h3>Czym jest grupa konsument\u00f3w i r\u00f3wnoleg\u0142e przetwarzanie?<\/h3>\n<p>Konsumenci Kafka s\u0105 przypisani do grup konsument\u00f3w. Ka\u017cdy konsument w grupie odczytuje wiadomo\u015bci z jednej lub wielu partycji, jednak \u017cadna partycja nie mo\u017ce by\u0107 obs\u0142ugiwana przez wi\u0119cej ni\u017c jednego konsumenta w danej grupie.<\/p>\n<p>Przyk\u0142ady:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18723 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/3.png\" alt=\"\" width=\"780\" height=\"263\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/3.png 780w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/3-300x101.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/3-768x259.png 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/p>\n<ul>\n<li>Topic ma 3 partycje, a grupa konsument\u00f3w sk\u0142ada si\u0119 z jednego konsumenta \u2192 konsument odbiera wiadomo\u015bci ze wszystkich partycji. (diagram powy\u017cej)<\/li>\n<\/ul>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18726 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/4.png\" alt=\"\" width=\"780\" height=\"291\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/4.png 780w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/4-300x112.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/4-768x287.png 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/p>\n<ul>\n<li>Topic ma 3 partycje, a grupa sk\u0142ada si\u0119 z 3 konsument\u00f3w \u2192 ka\u017cdy konsument odbiera wiadomo\u015bci z jednej partycji (diagram powy\u017cej).<\/li>\n<\/ul>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18728 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/5.png\" alt=\"\" width=\"780\" height=\"364\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/5.png 780w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/5-300x140.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/5-768x358.png 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/p>\n<ul>\n<li>Topic ma 3 partycje, a grupa sk\u0142ada si\u0119 z 4 konsument\u00f3w \u2192 jeden z konsument\u00f3w pozostaje nieaktywny (diagram powy\u017cej).<\/li>\n<\/ul>\n<p>Grup\u0119 konsument\u00f3w mo\u017cna traktowa\u0107 jako aplikacj\u0119 Spring Boot lub Quarkus, a pojedynczego konsumenta jako w\u0105tek tej aplikacji. Dlatego podczas planowania przepustowo\u015bci wdra\u017canego systemu nale\u017cy odpowiednio dobra\u0107 liczb\u0119 partycji w topicach \u2013 to w\u0142a\u015bnie liczba partycji okre\u015bla maksymaln\u0105 liczb\u0119 w\u0105tk\u00f3w, kt\u00f3re mog\u0105 r\u00f3wnolegle przetwarza\u0107 wiadomo\u015bci.<\/p>\n<h3>Rola brokera w klastrze Kafka<\/h3>\n<p>Ka\u017cdy broker pe\u0142ni kilka istotnych funkcji:<\/p>\n<ul>\n<li>Liderowanie partycjom \u2013 broker mo\u017ce by\u0107 liderem dla wybranych partycji i obs\u0142ugiwa\u0107 ich operacje zapisu\/odczytu.<\/li>\n<li>Replikacja danych \u2013 broker przesy\u0142a dane z partycji do innych serwer\u00f3w klastra, zapewniaj\u0105c redundancj\u0119.<\/li>\n<li>Zarz\u0105dzanie offsetami konsument\u00f3w (offset konsumenta = miejsce, gdzie dany konsument sko\u0144czy\u0142 czyta\u0107 wiadomo\u015b\u0107)\u2013 broker przechowuje informacj\u0119 o tym, kt\u00f3re wiadomo\u015bci zosta\u0142y ju\u017c odczytane.<\/li>\n<li>Obs\u0142uga retencji danych z topicu\u2013 broker kontroluje usuwanie starszych danych zgodnie z polityk\u0105 retencji ustawion\u0105 dla danego topicu w partycji.<\/li>\n<\/ul>\n<h3>Czym jest Kafka Connect? Jak kafka integruje si\u0119 z innymi systemami?<\/h3>\n<p>Kolejnym elementem architektury jest Kafka Connect. To mechanizm umo\u017cliwiaj\u0105cy integracj\u0119 Kafki z innymi systemami, a tym samym komunikacje ze \u015bwiatem zewn\u0119trznym. Sk\u0142ada si\u0119 z dw\u00f3ch typ\u00f3w konektor\u00f3w:<\/p>\n<ul>\n<li>Source \u2013 konektory pozwalaj\u0105ce na odczyt danych z system\u00f3w \u017ar\u00f3d\u0142owych (np. baz danych, system\u00f3w plik\u00f3w, S3) i przesy\u0142anie ich do Kafki.<\/li>\n<li>Sink \u2013 konektory, kt\u00f3re pobieraja\/odczytuj\u0105 dane z wskazanych topic\u00f3w Kafki i zapisuj\u0105 je w systemach docelowych (np. bazach danych, systemach plik\u00f3w, S3).<\/li>\n<\/ul>\n<p>Na rynku dost\u0119pnych jest wiele gotowych konektor\u00f3w. Do najpopularniejszych dostawc\u00f3w nale\u017c\u0105:<\/p>\n<ul>\n<li>Confluent \u2192 <a href=\"https:\/\/docs.confluent.io\/platform\/current\/connect\/kafka_connectors.html\" target=\"_blank\" rel=\"nofollow noopener\">konektory Confluent<\/a> (niekt\u00f3re wymagaj\u0105 licencji).<\/li>\n<li>Camel \u2192 <a href=\"https:\/\/camel.apache.org\/camel-kafka-connector\/4.8.x\/index.html\" target=\"_blank\" rel=\"nofollow noopener\">konektory Apache Camel<\/a> (licencja Apache 2.0).<\/li>\n<li>io \u2192 <a href=\"https:\/\/lenses.io\/kafka-connectors\/\" target=\"_blank\" rel=\"nofollow noopener\">konektory Lenses.io<\/a> (licencja Open Source).<\/li>\n<\/ul>\n<p>Warto zwr\u00f3ci\u0107 uwag\u0119, \u017ce w przypadku Confluent licencja mo\u017ce si\u0119 r\u00f3\u017cni\u0107 w zale\u017cno\u015bci od konektora \u2013 niekt\u00f3re wymagaj\u0105 op\u0142at, inne s\u0105 <a href=\"https:\/\/inteca.com\/blog\/application-modernization\/the-power-of-open-source-technologies-in-modern-application-development\/\">open source<\/a>. Czasami r\u00f3wnie\u017c konektor source i sink dla tego samego systemu mog\u0105 mie\u0107 r\u00f3\u017cne licencje.<\/p>\n<p>Ciekaw\u0105 opcj\u0105 s\u0105 konektory Lenses.io, kt\u00f3re oferuj\u0105 m.in. konektor JMS \u2013 wykorzystywali\u015bmy go w jednym z naszych projekt\u00f3w.<\/p>\n<h3>Znaczenie Stream Application \u2013 przetwarzanie danych w Kafce<\/h3>\n<p>Ostatnim elementem, przedstawionym na diagramie architektury jest Stream Application. To komponent, kt\u00f3ry pobiera dane z topicu, przetwarza je i zapisuje w topicu docelowym. Pe\u0142ni jednocze\u015bnie rol\u0119 producenta i konsumenta wiadomo\u015bci.<\/p>\n<p>Aplikacje typu Stream Application mog\u0105 by\u0107 tworzone w r\u00f3\u017cnych frameworkach, takich jak:<\/p>\n<ul>\n<li>Spring Boot<\/li>\n<li>Quarkus<\/li>\n<\/ul>\n<p>Typowe operacje realizowane przez Stream Applications obejmuj\u0105:<\/p>\n<ul>\n<li>Transformaty wiadomo\u015bci<\/li>\n<li>Przeliczanie<\/li>\n<li>Agregacj\u0119, \u0142\u0105czenie komunikat\u00f3w z wielu topic\u00f3w<\/li>\n<\/ul>\n<p>Ostatnim elementem, przedstawionym na diagramie architektury, jest Stream Application. Jest to komponent, kt\u00f3ry pobiera dane z topicu, przetwarza i wysy\u0142a na topic docelowy. Innymi s\u0142owy grupuje w sobie funkcjonalno\u015b\u0107 konsumenta i producenta Kafka. Aplikacje takie mo\u017cna wytwarza\u0107 w r\u00f3\u017cnych frameworkach np. Spring Boot, Quarkus i mog\u0105 one realizowa\u0107 transformaty wiadomo\u015bci, przeliczenia, agregaty, mog\u0105 \u0142\u0105czy\u0107 komunikaty z kilku topic\u00f3w.<\/p>\n<p>Om\u00f3wione powy\u017cej komponenty stanowi\u0105 podstaw\u0119 architektury Apache Kafka. W kolejnych sekcjach przyjrzymy si\u0119 ich konfiguracji i optymalizacji.<\/p>\n<p>Kafka posiada bogat\u0105 dokumentacj\u0119, a w Internecie mo\u017cna znale\u017a\u0107 wiele dodatkowych materia\u0142\u00f3w na jej temat. Warto na przyk\u0142ad zapozna\u0107 si\u0119 z takimi elementami jak Schema Registry, kt\u00f3re umo\u017cliwia zarz\u0105dzanie schematami wiadomo\u015bci przesy\u0142anych w Kafce, a nie zosta\u0142 om\u00f3wiony powy\u017cej.<\/p>\n<h2>Obszary funkcjonalne Apache Kafka<\/h2>\n<p>Zanim przejdziemy do szczeg\u00f3\u0142owej analizy, warto om\u00f3wi\u0107 kluczowe obszary funkcjonalne, kt\u00f3re powinien zapewnia\u0107 broker wiadomo\u015bci:<\/p>\n<ul>\n<li>Wdra\u017canie i konfiguracja \u2013 Broker (lub ekosystem narz\u0119dzi wok\u00f3\u0142 niego) powinien umo\u017cliwia\u0107 \u0142atwe wdra\u017canie komponent\u00f3w, zarz\u0105dzanie kolejkami i kontrol\u0119 dost\u0119pu do nich, a tak\u017ce elastyczne konfigurowanie systemu.<\/li>\n<li>Monitoring \u2013 Istotnym elementem dzia\u0142ania brokera (lub ekosystemu narzedzi wok\u00f3\u0142 brokera) jest mo\u017cliwo\u015b\u0107 monitorowania dzia\u0142ania kompoenent\u00f3w oraz zbierania kluczowych metryk, takich jak przepustowo\u015b\u0107, wykorzystanie zasob\u00f3w (CPU\/RAM), rozmiar kolejek i inne parametry operacyjne.<\/li>\n<li>Bezpiecze\u0144stwo \u2013 w tym zakresie broker powinien zapewnia\u0107 komunikacj\u0119 z wykorzystaniem bezpiecznych protoko\u0142\u00f3w transmisji danych, a tak\u017ce mechanizmy uwierzytelniania i autoryzacji, umo\u017cliwiaj\u0105ce kontrol\u0119 dost\u0119pu do kolejek i operacji.<\/li>\n<li>Wysoka dost\u0119pno\u015b\u0107 oraz odtwarzanie po awarii \u2013 broker powinien wspiera\u0107 mechanizmy zapewniaj\u0105ce nieprzerwane dzia\u0142anie, takie jak replikacja danych, strategie przywracania po awarii oraz mo\u017cliwo\u015b\u0107 tworzenia kopii zapasowych.<\/li>\n<li>Wysoka wydajno\u015b\u0107 przetwarzania komunikat\u00f3w \u2013 broker powinien oferowa\u0107 mechanizmy wysokiej przepustowo\u015bci przetwarzania wiadomo\u015bci, przy jednoczesnym optymalnym wykorzystaniu zasob\u00f3w systemowych (CPU\/RAM).<\/li>\n<\/ul>\n<p>W kolejnych sekcjach przeanalizujemy te obszary w kontek\u015bcie Apache Kafka, omawiaj\u0105c jej mo\u017cliwo\u015bci oraz elementy, na kt\u00f3re warto zwr\u00f3ci\u0107 szczeg\u00f3ln\u0105 uwag\u0119, aby unikn\u0105\u0107 problem\u00f3w.<\/p>\n<h2>Wdra\u017canie i konfiguracja Kafka<\/h2>\n<p>Apache Kafka oferuje r\u00f3\u017cne opcje instalacji. W naszych projektach najcz\u0119\u015bciej wykorzystujemy wdro\u017cenia na klastrach Kubernetes lub RedHat OpenShift, poniewa\u017c zapewniaj\u0105 one wysoki poziom dost\u0119pno\u015bci i bezpiecze\u0144stwa (szczeg\u00f3\u0142owe om\u00f3wienie tych aspekt\u00f3w wykracza poza zakres tego artyku\u0142u).<\/p>\n<p>Jednym z popularnych sposob\u00f3w instalacji Apache Kafka na OpenShift jest Strimzi (<a href=\"https:\/\/strimzi.io\/\" target=\"_blank\" rel=\"nofollow noopener\">strimzi.io<\/a>), dzia\u0142aj\u0105ce zgodnie ze wzorcem Operator (<a href=\"https:\/\/kubernetes.io\/docs\/concepts\/extend-kubernetes\/operator\/\" target=\"_blank\" rel=\"nofollow noopener\">Operator Pattern<\/a>). Strimzi wprowadza zestaw dedykowanych zasob\u00f3w (<em>Custom Resource Definitions \u2013 CRD<\/em>), umo\u017cliwiaj\u0105cych opisanie instalacji klastra Kafka, Kafka Connect, konektor\u00f3w, definiowanie topic\u00f3w oraz zarz\u0105dzanie dost\u0119pami.<\/p>\n<p>Jedn\u0105 z g\u0142\u00f3wnych zalet Strimzi jest znacz\u0105ce uproszczenie instalacji ca\u0142ego ekosystemu Apache Kafka, kt\u00f3ry \u2013 jak om\u00f3wili\u015bmy w sekcji dotycz\u0105cej architektury \u2013 sk\u0142ada si\u0119 z wielu komponent\u00f3w.<\/p>\n<p>W poni\u017cszych przyk\u0142adach do definiowania zasob\u00f3w klastra OpenShift wykorzystujemy szablony Helm (<a href=\"https:\/\/helm.sh\/\" target=\"_blank\" rel=\"nofollow noopener\">helm.sh<\/a>).<\/p>\n<h3>Instalacja klastra Apache Kafka<\/h3>\n<p>Podstawowym CRD jest CRD typu Kafka, kt\u00f3ry pozwala na instalacj\u0119 klastra Kafka:<\/p>\n<pre>apiVersion: kafka.strimzi.io\/v1beta2\nkind: Kafka\nmetadata:\n\u00a0 name: {{ include \"broker.fullname\" . }}\n\u00a0 labels:\n\u00a0 \u00a0 {{- include \"broker.labels\" . | nindent 4 }}\nspec:\n\u00a0 kafka:\n\u00a0 \u00a0 resources: (1)\n\u00a0 \u00a0 \u00a0 requests:\n\u00a0 \u00a0 \u00a0 \u00a0 cpu: {{ .Values.kafka.resources.requests.cpu }}\n\u00a0 \u00a0 \u00a0 \u00a0 memory: {{ .Values.kafka.resources.requests.memory }}\n\u00a0 \u00a0 \u00a0 limits:\n\u00a0 \u00a0 \u00a0 \u00a0 cpu: {{ .Values.kafka.resources.limits.cpu }}\n\u00a0 \u00a0 \u00a0 \u00a0 memory: {{ .Values.kafka.resources.limits.memory }}\n\u00a0 \u00a0 version: 3.4.0\n\u00a0 \u00a0 replicas: {{ .Values.kafka.replicas}} (2)\n\n\u2026<\/pre>\n<p>W (1) okre\u015blamy zasoby obliczeniowe dla broker\u00f3w Kafka, takie jak \u017c\u0105dane CPU\/RAM oraz limity CPU i RAM.<br \/>\nW (2) definiujemy liczb\u0119 broker\u00f3w, kt\u00f3re b\u0119d\u0105 tworzy\u0107 klaster Apache Kafka.<\/p>\n<p>W tym samym CRD mo\u017cemy r\u00f3wnie\u017c okre\u015bli\u0107 parametry instalacji Zookeepera.<\/p>\n<pre>\u00a0 zookeeper:\n\u00a0 \u00a0 resources: (1)\n\u00a0 \u00a0 \u00a0 requests:\n\u00a0 \u00a0 \u00a0 \u00a0 cpu: {{ .Values.zookeeper.resources.requests.cpu }}\n\u00a0 \u00a0 \u00a0 \u00a0 memory: {{ .Values.zookeeper.resources.requests.memory }}\n\u00a0 \u00a0 \u00a0 limits:\n\u00a0 \u00a0 \u00a0 \u00a0 cpu: {{ .Values.zookeeper.resources.limits.cpu }}\n\u00a0 \u00a0 \u00a0 \u00a0 memory: {{ .Values.zookeeper.resources.limits.memory }}\n\u00a0 \u00a0 replicas: {{ .Values.zookeeper.replicas }} (2)<\/pre>\n<p>W (1) okre\u015blamy zasoby CPU\/RAM przeznaczone dla Zookeepera, a w (2) liczb\u0119 jego instancji.<\/p>\n<p>Dodatkowo, w tym samym CRD mo\u017cemy skonfigurowa\u0107 parametry dyskowe dla Apache Kafka oraz szczeg\u00f3\u0142owe ustawienia konfiguracyjne:<\/p>\n<pre>\u00a0 \u00a0 storage: (1)\n\u00a0 \u00a0 \u00a0 type: jbod\n\u00a0 \u00a0 \u00a0 volumes:\n\u00a0 \u00a0 \u00a0 - id: 0\n\u00a0 \u00a0 \u00a0 \u00a0 type: persistent-claim\n\u00a0 \u00a0 \u00a0 \u00a0 size: {{ .Values.kafka.storage.size }}\n\u00a0 \u00a0 \u00a0 \u00a0 deleteClaim: true\n\u00a0 \u00a0 \u00a0 \u00a0 class: {{ .Values.kafka.storage.class }}\n\u00a0 \u00a0 \u00a0 - id: 1\n\u00a0 \u00a0 \u00a0 \u00a0 type: persistent-claim\n\u00a0 \u00a0 \u00a0 \u00a0 size: {{ .Values.kafka.storage.size }}\n\u00a0 \u00a0 \u00a0 \u00a0 deleteClaim: true\n\u00a0 \u00a0 \u00a0 \u00a0 class: {{ .Values.kafka.storage.class }}\n\u00a0 \u00a0 config: (2)\n\u00a0 \u00a0 \u00a0message.max.bytes:{{ .Values.kafka.config.messageMaxBytes }} (3)\n\u00a0 \u00a0 \u00a0num.partitions:{{.Values.kafka.config.defaultNumPartitions }}(4)\n\u00a0 \u00a0 \u00a0log.retention.hours:{{.Values.kafka.config.logRetentionHours}}(5)\n\u00a0 \u00a0 \u00a0num.network.threads: {{.Values.kafka.config.networkThreads }} (6)\n\u00a0 \u00a0 \u00a0num.io.threads: {{.Values.kafka.config.ioThreads }} (7)<\/pre>\n<p>W (1) znajduje si\u0119 definicja storage dla tworzonego klastra Apache Kafka.<\/p>\n<p>W (2) okre\u015blamy szczeg\u00f3\u0142owe parametry konfiguracyjne brokera. W powy\u017cszym przyk\u0142adzie zdefiniowano kilka podstawowych parametr\u00f3w, takich jak:<br \/>\n\u2022 (3) maksymalny rozmiar wiadomo\u015bci,<br \/>\n\u2022 (4) domy\u015blna liczba partycji,<br \/>\n\u2022 (5) domy\u015blna retencja dla topic\u00f3w,<br \/>\n\u2022 (6) liczba w\u0105tk\u00f3w sieciowych,<br \/>\n\u2022 (7) liczba w\u0105tk\u00f3w I\/O.<\/p>\n<p>Po za\u0142adowaniu powy\u017cszej konfiguracji do klastra Kubernetes lub OpenShift i jej przetworzeniu przez operatora Strimzi, uzyskamy w pe\u0142ni funkcjonalny klaster Apache Kafka obs\u0142ugiwany przez Zookeepera. Jego dzia\u0142anie mo\u017cna zweryfikowa\u0107 za pomoc\u0105 odpowiednich narz\u0119dzi:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18732 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/6.png\" alt=\"\" width=\"881\" height=\"100\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/6.png 881w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/6-300x34.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/6-768x87.png 768w\" sizes=\"(max-width: 881px) 100vw, 881px\" \/><\/p>\n<p>Po wylistowaniu POD\u2019\u00f3w zobaczymy zar\u00f3wno broker\u2019y jak i Zookeeper:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18734 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/7.png\" alt=\"\" width=\"998\" height=\"98\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/7.png 998w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/7-300x29.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/7-768x75.png 768w\" sizes=\"(max-width: 998px) 100vw, 998px\" \/><\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18774 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/8.png\" alt=\"\" width=\"978\" height=\"94\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/8.png 978w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/8-300x29.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/8-768x74.png 768w\" sizes=\"(max-width: 978px) 100vw, 978px\" \/><\/p>\n<p>Kolejnym elementem koniecznym do instalacji jest Kafka Connect co mo\u017cemy osi\u0105gn\u0105\u0107 przy pomocy innego CRD dostarczanego przez Strimzi jakim jest KafkaConnect:<\/p>\n<pre>apiVersion: kafka.strimzi.io\/v1beta2\nkind: KafkaConnect\nmetadata:\n\u00a0 name: connect-cluster-{{ include \"broker.fullname\" . }}\n\u00a0 annotations:\n\u00a0 \u00a0 strimzi.io\/use-connector-resources: \"true\"\nspec:\n\u00a0 image:{{ .Values.kafkaConnect.image.repository}}:{{ .Values.kafkaConnect.image.tag}}\n\u00a0 replicas: {{ .Values.kafkaConnect.replicas}} (1)\n\u00a0 bootstrapServers: {{ include \"broker.fullname\" . }}-kafka-bootstrap:9093 (2)<\/pre>\n<p>W punkcie (1) definiujemy liczb\u0119 instancji wchodz\u0105cych w sk\u0142ad klastra Kafka Connect, (2) okre\u015bla namiar na klaster Apache Kafka. CRD KafkaConnect pozwala tez okre\u015bli\u0107 inne elementy takie jak bezpiecze\u0144stwo, storage, zasoby, parametry konfiguracyjne Zookeeper.<\/p>\n<p>Po wgraniu tego CRD na klaster OpenShift dostaniemy funkcjonalny klaster KafkaConnect co mo\u017cna sprawdzi\u0107 nast\u0119puj\u0105cym poleceniem:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18738 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/9.png\" alt=\"\" width=\"707\" height=\"93\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/9.png 707w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/9-300x39.png 300w\" sizes=\"(max-width: 707px) 100vw, 707px\" \/><\/p>\n<p>W ten spos\u00f3b sprawnie i szybko zainstalowali\u015bmy klaster Apache Kafka oraz Kafka Connect. Ostatnim krokiem jest wdro\u017cenie przyk\u0142adowego topicu oraz przyk\u0142adowego konektora.<\/p>\n<p>Zacznijmy od definicji topicu, do kt\u00f3rej Strimzi dostarcza dedykowane CRD \u2013 KafkaTopic:<\/p>\n<pre>apiVersion: kafka.strimzi.io\/v1beta2\nkind: KafkaTopic\nmetadata:\n\u00a0 name: {{ .Values.kafkaTopics.file.data.name }} (1)\n\u00a0 labels:\n\u00a0 \u00a0 strimzi.io\/cluster: {{ .Values.kafkaTopics.cluster }}\nspec:\n\u00a0 partitions: {{.Values.kafkaTopics.file.data.partitions }} (2)\n\u00a0 replicas: {{.Values.kafkaTopics.file.data.replicas }} (3)\n\u00a0 config:\n\u00a0 \u00a0retention.ms:{{.Values.kafkaTopics.file.data.config.retention}} (4)<\/pre>\n<p>Ten prosty plik pozwala okre\u015bli\u0107:<br \/>\n\u2022 (1) Nazw\u0119 topicu.<br \/>\n\u2022 (2) Liczb\u0119 partycji topicu \u2013 je\u015bli nie zostanie podana, Kafka u\u017cyje domy\u015blnej warto\u015bci skonfigurowanej na poziomie brokera (zgodnie z opisem CRD dla klastra Kafka).<br \/>\n\u2022 (3) Liczb\u0119 replik topicu \u2013 okre\u015bla, ile kopii danych powinno by\u0107 przechowywanych w klastrze.<br \/>\n\u2022 (4) Retencj\u0119 topicu \u2013 czas przechowywania danych przed ich usuni\u0119ciem. Wiadomo\u015bci starsze ni\u017c okre\u015blona warto\u015b\u0107 b\u0119d\u0105 usuwane.<\/p>\n<p>Parametr retencji jest kluczowy w kontek\u015bcie zarz\u0105dzania przestrzeni\u0105 dyskow\u0105 klastra Kafka. R\u00f3\u017cne topici mog\u0105 mie\u0107 ustawione r\u00f3\u017cne warto\u015bci w zale\u017cno\u015bci od potrzeb \u2013 topicom o wi\u0119kszym znaczeniu biznesowym mo\u017cna przypisa\u0107 d\u0142u\u017csz\u0105 retencj\u0119.<\/p>\n<p>Teraz przygotujmy przyk\u0142adow\u0105 definicj\u0119 konektora, korzystaj\u0105c z CRD KafkaConnector.<\/p>\n<pre>apiVersion: kafka.strimzi.io\/v1beta2\nkind: KafkaConnector\nmetadata:\n\u00a0 \u00a0 name: jmssourceconnector-{{ $connector.name }}\n\u00a0 \u00a0 labels:\n\u00a0 \u00a0 \u00a0 \u00a0 strimzi.io\/cluster: {{ $.Values.kafkaConnectors.kccluster }}\nspec:\n\u00a0 \u00a0 class: com.datamountaineer.streamreactor.connect.jms.source.JMSSourceConnector (1)\n\u00a0 \u00a0 tasksMax: {{ .Values.connector.tasksMax }} (2)\n\u00a0 \u00a0 autoRestart:\n\u00a0 \u00a0 \u00a0 \u00a0 enabled: {{ $.Values.connector.autoRestart }} (3)\n\u00a0 \u00a0 config: (4)\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.connection.factory: {{ .Values.connector.connectionFactory \u00a0}}\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.destination.selector: {{ .Values.connector.selector }}\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.initial.context.factory:{{.Values.connector.contextFactoryClass }}\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.kcql: INSERT INTO test_topic SELECT * FROM {{ .Values .connector.queue }} WITHTYPE QUEUE\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.queues: {{ .Values.connector.queue }}\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.url: {{ .Values.connector.urls }}\n\u00a0 \u00a0 \u00a0 \u00a0 connect.progess.enabled: {{ .Values.connector.progessEnabled }}\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.scale.type: {{ .Values.scaleType }}\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.username: {{ .Values.username }}\n\u00a0 \u00a0 \u00a0 \u00a0 connect.jms.password: {{ .Values.password }}<\/pre>\n<p>Ten plik definiuje konektor JMS typu source, kt\u00f3ry odpowiada za odczyt danych z kolejki JMS i przekazanie ich do topicu Kafka:<\/p>\n<ul>\n<li>(1) Klasa implementuj\u0105ca konektor \u2013 okre\u015bla komponent, kt\u00f3ry zostanie uruchomiony do odbierania wiadomo\u015bci z serwera JMS. Ka\u017cdy konektor ma swoj\u0105 implementacj\u0119 w postaci plik\u00f3w JAR dostarczanych przez producenta konektora. Pliki te musz\u0105 znajdowa\u0107 si\u0119 na klastrze Kafka Connect, aby mog\u0142y by\u0107 u\u017cywane w czasie dzia\u0142ania (<em>runtime<\/em>).<\/li>\n<li>(2) Liczba zada\u0144 konektora \u2013 okre\u015bla liczb\u0119 instancji zada\u0144 uruchomionych w klastrze Kafka Connect. Dzi\u0119ki temu parametrowi mo\u017cna kontrolowa\u0107 liczb\u0119 r\u00f3wnolegle dzia\u0142aj\u0105cych instancji, co wp\u0142ywa na przepustowo\u015b\u0107 przetwarzania danych.<\/li>\n<li>(3) Parametry konfiguracyjne konektora \u2013 specyficzne dla danej implementacji. Powinny by\u0107 ustawiane zgodnie z dokumentacj\u0105 dostarczon\u0105 przez producenta konektora. W przedstawionym przyk\u0142adzie s\u0105 to parametry wymagane do pod\u0142\u0105czenia si\u0119 do zewn\u0119trznego serwera JMS.<\/li>\n<\/ul>\n<p>W ten <a href=\"https:\/\/inteca.com\/pl\/blog\/blog\/w-jaki-sposob-wartosci-firmy-wspieraja-proces-oceny-pracowniczej-w-inteca\/\">spos\u00f3b zako\u0144czyli\u015bmy proces<\/a> instalacji klastra Apache Kafka i Kafka Connect, a tak\u017ce wdro\u017cenie przyk\u0142adowego topicu oraz konektora.<\/p>\n<p>Jak wida\u0107, Kafka oferuje wiele mo\u017cliwo\u015bci konfiguracyjnych, a Strimzi umo\u017cliwia ich definiowanie za pomoc\u0105 dedykowanych CRD. Wykorzystanie Helm pozwala na parametryzacj\u0119 tych CRD (poprzez dedykowane pliki <em>Values<\/em>), co umo\u017cliwia utrzymywanie wielu konfiguracji, np. dla \u015brodowisk deweloperskich, testowych i produkcyjnych.<\/p>\n<p>Jedn\u0105 z kluczowych zalet takiego podej\u015bcia do zarz\u0105dzania instalacj\u0105 i konfiguracj\u0105 klastra Kafka jest mo\u017cliwo\u015b\u0107 przechowywania plik\u00f3w konfiguracyjnych (szablon\u00f3w) \u2013 s\u0105 to pliki YAML \u2013 w systemie kontroli wersji w dedykowanym repozytorium. Dzi\u0119ki temu mo\u017cna \u0142atwo audytowa\u0107 zmiany i \u015bledzi\u0107 histori\u0119 modyfikacji.<\/p>\n<p>Taka konfiguracja mo\u017ce by\u0107 nast\u0119pnie wdra\u017cana na \u015brodowiska przy u\u017cyciu pipeline\u2019\u00f3w w narz\u0119dziach takich jak GitLab czy Jenkins. Dodatkowo mo\u017cliwe jest wykorzystanie system\u00f3w automatycznej synchronizacji, np. ArgoCD (<a href=\"https:\/\/argo-cd.readthedocs.io\/en\/stable\/\" target=\"_blank\" rel=\"nofollow noopener\">https:\/\/argo-cd.readthedocs.io\/en\/stable\/<\/a>), kt\u00f3re monitoruj\u0105 repozytorium pod k\u0105tem zmian i automatycznie propaguj\u0105 je na \u015brodowiska docelowe.<\/p>\n<p>Po om\u00f3wieniu procesu wdra\u017cania i konfiguracji Kafki przejd\u017amy teraz do kwestii bezpiecze\u0144stwa.<\/p>\n<h2>Bezpiecze\u0144stwo systemu komunikacji zdarzeniowej<\/h2>\n<p>Ka\u017cdy system przeznaczony do komunikacji zdarzeniowej powinien zapewnia\u0107 bezpiecze\u0144stwo przesy\u0142anych danych, obejmuj\u0105ce szyfrowanie, uwierzytelnianie i autoryzacj\u0119. W tym zakresie Apache Kafka, zgodnie z <a href=\"https:\/\/kafka.apache.org\/documentation\/#security\" target=\"_blank\" rel=\"nofollow noopener\">oficjaln\u0105 dokumentacj\u0105<\/a>, oferuje nast\u0119puj\u0105ce mechanizmy zabezpiecze\u0144:<\/p>\n<ul>\n<li>Uwierzytelnianie po\u0142\u0105cze\u0144 klienckich do brokera z u\u017cyciem protoko\u0142\u00f3w takich jak SSL lub SASL,<\/li>\n<li>Uwierzytelnianie komunikacji mi\u0119dzy brokerem a Zookeeperem,<\/li>\n<li>Szyfrowanie przesy\u0142anych danych \u2013 zar\u00f3wno mi\u0119dzy klientami a brokerem, jak i pomi\u0119dzy brokerami w ramach replikacji,<\/li>\n<li>Autoryzacj\u0119 operacji wykonywanych przez klient\u00f3w w celu kontroli dost\u0119pu do temat\u00f3w i zasob\u00f3w.<\/li>\n<\/ul>\n<p>Dostosowanie Apache Kafka do spe\u0142nienia wymog\u00f3w bezpiecze\u0144stwa wymaga konfiguracji wielu parametr\u00f3w. Przyk\u0142adowo, konieczne jest skonfigurowanie zabezpieczonego listenera:<\/p>\n<pre>listeners=BROKER:\/\/localhost:9092\nlistener.security.protocol.map=BROKER:SASL_SSL,CONTROLLER:SASL_SSL<\/pre>\n<p>oraz wygenerowanie kluczy SSL przy pomocy narz\u0119dzi takich jak keytool. Proces ten wymaga szczeg\u00f3lnej uwagi i koncentracji, ale zdecydowanie jest to konfiguracja kt\u00f3r\u0105 warto wykona\u0107 w celu zapewnienia pe\u0142nego bezpiecze\u0144stwa przesy\u0142anych danych.<\/p>\n<p>Je\u015bli Kafka jest wdra\u017cana na klastrze Kubernetes lub OpenShift i korzysta z Strimzi, konfiguracja uwierzytelniania staje si\u0119 prostsza. Strimzi automatyzuje wiele proces\u00f3w, udost\u0119pniaj\u0105c odpowiednie wpisy w plikach CR (Custom Resource), a tak\u017ce dodatkowe definicje CRD (Custom Resource Definitions), kt\u00f3re upraszczaj\u0105 zarz\u0105dzanie bezpiecze\u0144stwem.<\/p>\n<p>Rozpocznijmy od konfiguracji uwierzytelniania dla brokera \u2013 w pliku definiuj\u0105cym klaster Kafka dost\u0119pne s\u0105 nast\u0119puj\u0105ce opcje:<\/p>\n<pre>apiVersion: kafka.strimzi.io\/v1beta2\nkind: Kafka\nmetadata:\n\u00a0 name: {{ include \"broker.fullname\" . }}\n\u00a0 labels:\n\u00a0 \u00a0 {{- include \"broker.labels\" . | nindent 4 }}\nspec:\n\u00a0 kafka:\n\u00a0 \u00a0 \u2026\n\u00a0 \u00a0 listeners: (1)\n\u00a0 \u00a0 \u00a0 - name: tls (2)\n\u00a0 \u00a0 \u00a0 \u00a0 port: 9093\n\u00a0 \u00a0 \u00a0 \u00a0 type: internal\n\u00a0 \u00a0 \u00a0 \u00a0 tls: true\n\u00a0 \u00a0 \u00a0 \u00a0 authentication:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 type: tls \u00a0 \u00a0 \u00a0 \u00a0\n\u00a0 \u00a0 \u00a0 - name: external (3)\n\u00a0 \u00a0 \u00a0 \u00a0 port: 9094\n\u00a0 \u00a0 \u00a0 \u00a0 type: route\n\u00a0 \u00a0 \u00a0 \u00a0 tls: true \u00a0 \u00a0 \u00a0 \n\u00a0 \u00a0 \u00a0 \u00a0 authentication:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 type: tls\n\n\u00a0\u00a0\u00a0\u00a0 \u2026<\/pre>\n<ul>\n<li>(1) Definicja listener\u00f3w.<\/li>\n<li>(2) Listener wewn\u0119trzny (dla klastra OpenShift) dzia\u0142aj\u0105cy na porcie 9093, z w\u0142\u0105czonym TLS oraz uwierzytelnianiem opartym na certyfikacie.<\/li>\n<li>(3) Zewn\u0119trzny port 9094 (udost\u0119pniony za pomoc\u0105 route OpenShift) z w\u0142\u0105czonym TLS, ale bez uwierzytelniania certyfikatowego.<\/li>\n<\/ul>\n<p>Po za\u0142adowaniu tej konfiguracji operator Strimzi automatycznie wygeneruje odpowiednie secrety OpenShift, kt\u00f3re b\u0119d\u0105 wykorzystywane do zarz\u0105dzania uwierzytelnianiem i szyfrowaniem komunikacji:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18742 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/10.png\" alt=\"\" width=\"1248\" height=\"577\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/10.png 1248w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/10-300x139.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/10-1024x473.png 1024w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/10-768x355.png 768w\" sizes=\"(max-width: 1248px) 100vw, 1248px\" \/><\/p>\n<p>Je\u015bli teraz spojrzymy na wcze\u015bniej przygotowany i wdro\u017cony klaster Kafka Connect, zauwa\u017cymy, \u017ce nie b\u0119dzie on m\u00f3g\u0142 po\u0142\u0105czy\u0107 si\u0119 z brokerem Kafka. Aby przywr\u00f3ci\u0107 komunikacj\u0119 mi\u0119dzy tymi komponentami, konieczne jest dostosowanie konfiguracji Kafka Connect, uwzgl\u0119dniaj\u0105c aspekty zwi\u0105zane z bezpiecze\u0144stwem.<\/p>\n<p>W tym celu nale\u017cy wprowadzi\u0107 odpowiednie zmiany w pliku CR (Custom Resource) dla KafkaConnect:<\/p>\n<pre>apiVersion: kafka.strimzi.io\/v1beta2\nkind: KafkaConnect\nmetadata:\n\u00a0 name: connect-cluster-{{ include \"broker.fullname\" . }}\nspec:\n\u00a0 rack:\n\u00a0 \u2026\n\u00a0 bootstrapServers:{{include \"broker.fullname\" .}}-kafka-bootstrap:9093\n\u00a0 authentication: (1)\n\u00a0 \u00a0 type: tls\n\u00a0 \u00a0 certificateAndKey:\n\u00a0 \u00a0 \u00a0 secretName: kafka-connect-tls-user\n\u00a0 \u00a0 \u00a0 certificate: user.crt\n\u00a0 \u00a0 \u00a0 key: user.key\n\u00a0 tls: (2)\n\u00a0 \u00a0 trustedCertificates:\n\u00a0 \u00a0 \u00a0 - secretName: {{ include \"broker.fullname\" . }}-cluster-ca-cert\n\u00a0 \u00a0 \u00a0 \u00a0 certificate: ca.crt<\/pre>\n<ul>\n<li>(1) W tym miejscu definiujemy spos\u00f3b, w jaki Kafka Connect b\u0119dzie si\u0119 \u0142\u0105czy\u0107 i uwierzytelnia\u0107 w brokerze Kafka. Wskazujemy u\u017cycie protoko\u0142u TLS oraz informujemy, \u017ce Kafka Connect ma si\u0119 \u201eprzedstawi\u0107\u201d za pomoc\u0105 certyfikatu.<\/li>\n<li>(2) Tutaj konfigurujemy, jak Kafka Connect b\u0119dzie \u201cufa\u0107\u201d certyfikatowi, kt\u00f3rym broker Kafka uwierzytelnia si\u0119 podczas nawi\u0105zywania po\u0142\u0105czenia. Wida\u0107, \u017ce odnosi si\u0119 on do secretu OpenShift, kt\u00f3ry operator Strimzi wygenerowa\u0142 w poprzednim kroku.<\/li>\n<\/ul>\n<p>Pozostaje jednak kluczowe pytanie: sk\u0105d Kafka Connect w miejscu oznaczonym (1) we\u017amie certyfikat? Przecie\u017c nigdzie nie definiowali\u015bmy secretu kafka-connect-tls-user.<\/p>\n<p>Odpowied\u017a jest prosta \u2013 ten certyfikat reprezentuje u\u017cytkownika lub aplikacj\u0119, kt\u00f3ra \u0142\u0105czy si\u0119 z brokerem Kafka. Strimzi dostarcza w tym celu dedykowany CRD o nazwie KafkaUser, kt\u00f3ry pozwala na zdefiniowanie takiego u\u017cytkownika:<\/p>\n<pre>apiVersion: kafka.strimzi.io\/v1beta2\nkind: KafkaUser\nmetadata:\n\u00a0 name: kafka-connect-tls-user\n\u00a0 labels:\n\u00a0 \u00a0 strimzi.io\/cluster: {{ include \"broker.fullname\" . }}\nspec:\n\u00a0 authentication: (1)\n\u00a0 \u00a0 type: tls\n\u00a0 authorization:(2)\n\u00a0 \u00a0 type: simple\n\u00a0 \u00a0 acls:\n\u00a0 \u00a0 \u00a0 - resource: (3)\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 type: topic (3.1)\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 name: event-data (3.2)\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 patternType: literal (3.3)\n\u00a0 \u00a0 \u00a0 \u00a0 operations: (3.4)\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Create\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Describe\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - DescribeConfigs\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Read\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Write\n\u00a0 \u00a0 \u00a0 \u00a0 host: \"*\" (3.5)\n\u00a0 \u00a0 \u00a0 # consumer group aws s3 sink connector\n\u00a0 \u00a0 \u00a0 - resource: \n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 type: group (4)\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 name: connect-sinkconnector\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 patternType: literal\n\u00a0 \u00a0 \u00a0 \u00a0 operations:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Create\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Describe\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Read\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Write\n\u00a0 \u00a0 \u00a0 \u00a0 host: \"*\"<\/pre>\n<p>Przyjrzyjmy si\u0119 zawarto\u015bci tego pliku:<\/p>\n<ul>\n<li>(1) Definiujemy uwierzytelnianie TLS dla tworzonego u\u017cytkownika.<\/li>\n<li>(2) Okre\u015blamy uprawnienia u\u017cytkownika \u2013 jest to lista element\u00f3w definiuj\u0105cych dost\u0119p do zasob\u00f3w.<\/li>\n<li>(3) Definiujemy pierwszy zas\u00f3b typu topic:\n<ul>\n<li>(3.1) Okre\u015blamy typ zasobu jako topic.<\/li>\n<li>(3.2) Ustawiamy jego nazw\u0119.<\/li>\n<li>(3.3) Wskazujemy, \u017ce nazwa ma by\u0107 traktowana literalnie \u2013 mo\u017cna r\u00f3wnie\u017c u\u017cy\u0107 warto\u015bci prefix, co pozwala na nadanie uprawnie\u0144 do wszystkich zasob\u00f3w, kt\u00f3rych nazwa zaczyna si\u0119 od okre\u015blonego ci\u0105gu znak\u00f3w.<\/li>\n<li>(3.4) Wymieniamy operacje, do kt\u00f3rych u\u017cytkownik ma prawo dost\u0119pu.<\/li>\n<li>(3.5) Okre\u015blamy adres\/host, z kt\u00f3rego u\u017cytkownik mo\u017ce si\u0119 \u0142\u0105czy\u0107.<\/li>\n<\/ul>\n<\/li>\n<li>(4) Definiujemy zas\u00f3b innego typu \u2013 grup\u0119 konsument\u00f3w o okre\u015blonej nazwie oraz list\u0119 dozwolonych operacji dla tej grupy.<\/li>\n<\/ul>\n<p>Po za\u0142adowaniu tej definicji operator Strimzi automatycznie wygeneruje odpowiedni secret, kt\u00f3ry Kafka Connect wykorzysta do uwierzytelnienia w brokerze i kt\u00f3ry b\u0119dzie zrozumia\u0142y dla brokera:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18744 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/11.png\" alt=\"\" width=\"1248\" height=\"1023\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/11.png 1248w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/11-300x246.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/11-1024x839.png 1024w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/11-768x630.png 768w\" sizes=\"(max-width: 1248px) 100vw, 1248px\" \/><\/p>\n<p>Je\u015bli aplikacja (KafkaUser) korzystaj\u0105ca z takiego certyfikatu spr\u00f3buje wykona\u0107 na brokerze operacj\u0119 niedozwolon\u0105 (czyli tak\u0105, kt\u00f3rej nie uwzgl\u0119dnili\u015bmy w definicji KafkaUser), broker automatycznie j\u0105 zablokuje. W logach zobaczymy wtedy komunikat o b\u0142\u0119dzie:<\/p>\n<pre>2024-10-02 13:42:21,932 INFO Principal = User:CN=kafka-connect-tls-user is Denied Operation = Describe from host = 10.253.23.147 on resource = Cluster:LITERAL:kafka-cluster for request = ListPartitionReassignments with resourceRefCount = 1<\/pre>\n<p>Powy\u017cszy b\u0142\u0105d wskazuje, \u017ce u\u017cytkownik kafka-connect-tls-user nie posiada uprawnie\u0144 do pobierania informacji o klastrze. Jest to oczekiwane zachowanie, poniewa\u017c nie nadali\u015bmy mu takiego dost\u0119pu w konfiguracji.<\/p>\n<p>Aby usun\u0105\u0107 ten b\u0142\u0105d, musimy doda\u0107 odpowiednie uprawnienie do pliku konfiguracyjnego:<\/p>\n<pre>- resource:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 type: cluster\n\u00a0 \u00a0 \u00a0 \u00a0 operations:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 - Describe\n\u00a0 \u00a0 \u00a0 \u00a0 host: \"*\"<\/pre>\n<p>W przedstawionym przyk\u0142adzie pojawia si\u0119 nowy typ zasobu reprezentuj\u0105cy klaster Kafka.<\/p>\n<p>Jak wida\u0107, Apache Kafka oferuje szerokie mo\u017cliwo\u015bci konfiguracyjne w zakresie bezpiecze\u0144stwa \u2013 od uwierzytelniania, przez szyfrowanie, a\u017c po autoryzacj\u0119. Je\u015bli korzystamy z Strimzi, konfiguracja tych mechanizm\u00f3w staje si\u0119 znacznie prostsza, poniewa\u017c wiele element\u00f3w jest generowanych automatycznie przez operatora Strimzi.<\/p>\n<p>Potwierdzili\u015bmy zatem, \u017ce pod wzgl\u0119dem bezpiecze\u0144stwa Apache Kafka to rozwi\u0105zanie klasy enterprise, kt\u00f3re spe\u0142ni wymagania nawet najbardziej rygorystycznych departament\u00f3w bezpiecze\u0144stwa.<\/p>\n<p>Przejd\u017amy teraz do analizy wysokiej dost\u0119pno\u015bci Kafki i metod zapewnienia jej niezawodno\u015bci.<\/p>\n<h2>Wysoka dost\u0119pno\u015b\u0107 oraz odtwarzanie po awarii<\/h2>\n<p>Systemy komunikacji zdarzeniowej odpowiadaj\u0105 za przesy\u0142anie komunikat\u00f3w mi\u0119dzy wieloma systemami i us\u0142ugami. Im wi\u0119cej komponent\u00f3w polega na takiej komunikacji, tym wi\u0119ksze znaczenie ma rola brokera w ca\u0142ym przep\u0142ywie informacji.<\/p>\n<p>Co jednak stanie si\u0119 w przypadku awarii brokera? Czy mo\u017ce on sta\u0107 si\u0119 pojedynczym punktem awarii (Single Point of Failure, SPOF)? Odpowied\u017a brzmi: <a href=\"https:\/\/inteca.com\/pl\/blog\/blog\/umiejetnosc-pracy-w-zespole-dlaczego-jest-tak-wazna-w-branzy-it\/\">tak \u2013 je\u015bli system jest<\/a> \u017ale rozmieszczony i skonfigurowany, mo\u017ce sta\u0107 si\u0119 SPOF.<\/p>\n<p>Jak zatem Apache Kafka radzi sobie z tym wyzwaniem?<\/p>\n<p>Podstawowym mechanizmem zapewniaj\u0105cym wysok\u0105 dost\u0119pno\u015b\u0107 w Kafce jest replikacja. Replikacja oznacza, \u017ce dane z partycji topicu s\u0105 przechowywane na r\u00f3\u017cnych w\u0119z\u0142ach klastra. W przypadku awarii jednego z w\u0119z\u0142\u00f3w jego rol\u0119 mog\u0105 przej\u0105\u0107 inne w\u0119z\u0142y, poniewa\u017c dane s\u0105 replikowane.<\/p>\n<p>Poni\u017cszy diagram ilustruje ten proces:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18746 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/12.png\" alt=\"\" width=\"780\" height=\"374\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/12.png 780w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/12-300x144.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/12-768x368.png 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/p>\n<p>Klaster Kafka sk\u0142ada si\u0119 z trzech broker\u00f3w. Na poni\u017cszym diagramie kolorem niebieskim zaznaczono lider\u00f3w partycji. Przyk\u0142adowo, Broker 1 pe\u0142ni rol\u0119 lidera partycji 0 w topicu 1 i odpowiada za replikacj\u0119 danych tej partycji na inne w\u0119z\u0142y klastra:<\/p>\n<ul>\n<li>Broker 2 jest pierwsz\u0105 replik\u0105 partycji 0 w topicu 1 (kolor pomara\u0144czowy),<\/li>\n<li>Broker 3 jest drug\u0105 replik\u0105 partycji 0 w topicu 1 (kolor zielony).<\/li>\n<\/ul>\n<p>W\u0119z\u0142y Broker 2 i Broker 3 s\u0105 nazywane in-sync replicas (ISR), czyli synchronizowanymi replikami. W przypadku awarii Brokera 1, jeden z broker\u00f3w in-sync zostanie automatycznie wybrany nowym liderem partycji 0 dla topicu 1, co pozwoli klientom na nieprzerwane korzystanie z topicu. Dzi\u0119ki temu mechanizmowi Kafka zapewnia odporno\u015b\u0107 na awarie.<\/p>\n<p>Dodatkowo, je\u015bli Kafka jest wdra\u017cana na klastrze OpenShift, kt\u00f3ry jest rozmieszczony w podziale na dwa centra danych (g\u0142\u00f3wnym \u2013 Data Center i zapasowym \u2013 Disaster Recovery Center), mo\u017cna wymusi\u0107 odpowiednie rozmieszczenie broker\u00f3w, aby zwi\u0119kszy\u0107 dost\u0119pno\u015b\u0107 systemu. W\u0119z\u0142y trafiaj\u0105 w tym wypadku r\u00f3wnie\u017c do zapasowego centrum co zwi\u0119ksza dost\u0119pno\u015b\u0107 naszej instalacji. W tym celu warto skorzysta\u0107 z konfiguracji przynale\u017cno\u015bci (affinity), kt\u00f3ra umo\u017cliwia kontrol\u0119 nad tym, gdzie uruchamiane s\u0105 poszczeg\u00f3lne w\u0119z\u0142y klastra.<\/p>\n<pre>affinity:\n\u00a0\u00a0 nodeAffinity:\n\u00a0\u00a0\u00a0\u00a0\u00a0 requiredDuringSchedulingIgnoredDuringExecution:\n\n \u00a0\u00a0\u00a0\u00a0 \u2026<\/pre>\n<p>Kolejnym kluczowym elementem zapewnienia niezawodno\u015b\u0107 jest mo\u017cliwo\u015b\u0107 odtworzenia systemu po awarii oraz tworzenie kopii zapasowych. W tym zakresie dost\u0119pnych jest kilka metod:<\/p>\n<ul>\n<li>Opcja 1:<\/li>\n<\/ul>\n<p>Cz\u0119\u015b\u0107 os\u00f3b wykorzystuje narz\u0119dzie Kafka Mirror Maker, kt\u00f3re pozwala na replikacj\u0119 danych mi\u0119dzy klastrami Kafka. W tym modelu mamy klaster podstawowy, oraz klaster zapasowy &#8211; rozmieszczony w innym miejscu. MirrorMaker jest u\u017cywany do synchronizacji danych mi\u0119dzy tymi klastrami. W przypadku awarii klastra podstawowego, ruch zostanie przekierowywany\u00a0 do klastra zapasowego.<\/p>\n<ul>\n<li>Opcja 2:<\/li>\n<\/ul>\n<p>W przypadku instalacji na klastrze OpenShift, gdy dyski klastra Kafka s\u0105 dostarczane przez OpenShift, pojawia si\u0119 mo\u017cliwo\u015b\u0107 tworzenia ich kopii zapasowych (ang. <em>Persistent Volume Claim<\/em>) za pomoc\u0105 tzw. snapshot\u00f3w. Jednym z narz\u0119dzi umo\u017cliwiaj\u0105cych to dzia\u0142anie jest <a href=\"https:\/\/www.commvault.com\/platform\/backup-and-recovery\" target=\"_blank\" rel=\"nofollow noopener\">Commvault<\/a>. W jednym z projekt\u00f3w Inteca sprawdzali\u015bmy, czy mo\u017cliwe jest wykonanie kopii zapasowej PVC klastra Kafka bez konieczno\u015bci wy\u0142\u0105czania jego w\u0119z\u0142\u00f3w. Sama kopia zapasowa przebieg\u0142a bez problem\u00f3w, jednak odtworzenie danych okaza\u0142o si\u0119 problematyczne i nie zawsze ko\u0144czy\u0142o si\u0119 powodzeniem. G\u0142\u00f3wnym wyzwaniem by\u0142a sp\u00f3jno\u015b\u0107 danych po przywr\u00f3ceniu.<\/p>\n<p>Aby skutecznie korzysta\u0107 z takich narz\u0119dzi do tworzenia kopii zapasowych, warto rozwa\u017cy\u0107 wy\u0142\u0105czenie klastra Kafka na czas wykonywania snapshotu. Cho\u0107 wi\u0105\u017ce si\u0119 to z kr\u00f3tkotrwa\u0142\u0105 niedost\u0119pno\u015bci\u0105 systemu, mo\u017ce znacz\u0105co zwi\u0119kszy\u0107 niezawodno\u015b\u0107 procesu przywracania danych.<\/p>\n<ul>\n<li>Opcja 3:<\/li>\n<\/ul>\n<p>Opcj\u0105 kt\u00f3ra jest cz\u0119sto wykorzystywana w przypadku tworzenia kopii zapasowej Apache Kafka jest tworzenie kopii zapasowej poprzez wys\u0142anie danych do S3. W tym podej\u015bciu w ramach Kafka Connect u\u017cywany jest konektor S3 typu sink, kt\u00f3ry pobiera dane z topic\u00f3w i wysy\u0142a do S3 (konektor S3 source jest wy\u0142\u0105czony):<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18748 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/13.png\" alt=\"\" width=\"780\" height=\"354\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/13.png 780w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/13-300x136.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/13-768x349.png 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/p>\n<p>W momencie przywr\u00f3cenia dzia\u0142ania systemu po awarii, konektory zmieniaj\u0105 sw\u00f3j stan i nast\u0119puje odczytanie danych z kopii zapasowej (konektor sink jest wy\u0142\u0105czony a source w\u0142\u0105czony):<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18750 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/14.png\" alt=\"\" width=\"780\" height=\"403\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/14.png 780w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/14-300x155.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/14-768x397.png 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/p>\n<p>Po przywr\u00f3ceniu danych z kopii zapasowej konektory wracaj\u0105 do ustawienia pierwotnego. Nale\u017cy tutaj zaznaczy\u0107 \u017ce zmiany stan\u00f3w konektor\u00f3w w momencie odtwarzania z backupu oraz po odtworzeniu s\u0105 operacjami manualnymi, czynno\u015bciami administracyjnymi.<\/p>\n<p>Opisane wy\u017cej podej\u015bcie to cz\u0119sto wykorzystywane rozwi\u0105zanie do tworzenia kopii zapasowych dla Apache Kafka. Nale\u017cy jednak zwr\u00f3ci\u0107 uwag\u0119 na jeden istotny fakt a mianowicie odpowiednie odtworzenie danych i przywr\u00f3cenie offset\u00f3w dla grup konsument\u00f3w:<\/p>\n<ul>\n<li>W zakresie odtworzenia danych konieczne jest zapewnienie aby dane trafi\u0142y na odpowiednie partycje w odpowiedniej kolejno\u015bci, je\u015bli si\u0119 to nie uda to grupy konsument\u00f3w mog\u0105 zacz\u0105\u0107 przetwarza\u0107 dane ju\u017c raz przeprocesowane albo (w szczeg\u00f3lnym przypadku) cz\u0119\u015bci danych w og\u00f3le nie przeprocesowa\u0107,<\/li>\n<li>Drugim wa\u017cnym aspektem jest zachowanie informacji o tym gdzie dana konsumer grupa sko\u0144czy\u0142a przetwarzanie tzn. zachowanie informacji o offsetach przetwarzania poszczeg\u00f3lnych partycji topicu.<\/li>\n<\/ul>\n<p>Przedstawimy to na przyk\u0142adzie:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18754 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/15.png\" alt=\"\" width=\"780\" height=\"325\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/15.png 780w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/15-300x125.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/15-768x320.png 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/p>\n<p>Konsument odczytuje dane z topicu 1. Z partycji 0 pobra\u0142 i przetworzy\u0142 wiadomo\u015b\u0107 0, podobnie jak dla partycji 1. Po przetworzeniu konsument informuje broker \u017ce te wiadomo\u015bci s\u0105 ju\u017c przetworzone i ta informacja jest zapisywana w specjalnym, wewn\u0119trznym topicu Kafka o nazwie __consumer_offsets. Wiadomo\u015b\u0107 1 z partycji 0 nie zosta\u0142a potwierdzona tzn. offset grupy dla tej partycji jest mniejszy ni\u017c offset tej wiadomo\u015bci.<\/p>\n<p>Je\u015bli po awarii odczytamy dane z kopii zapasowej, a podczas ich odtwarzania wiadomo\u015bci zamieni\u0105 swoje partycje lub kolejno\u015b\u0107, zapisane informacje o tym, gdzie dany konsument zako\u0144czy\u0142 przetwarzanie, stan\u0105 si\u0119 bezu\u017cyteczne. Co wi\u0119cej, ich u\u017cycie mo\u017ce prowadzi\u0107 do b\u0142\u0119d\u00f3w.<\/p>\n<p>Na przyk\u0142ad, je\u015bli po przywr\u00f3ceniu partycja 1 zawiera zar\u00f3wno wiadomo\u015b\u0107 fioletow\u0105, jak i pomara\u0144czow\u0105, a partycja 0 jedynie wiadomo\u015b\u0107 zielon\u0105, mog\u0105 wyst\u0105pi\u0107 nast\u0119puj\u0105ce problemy:<\/p>\n<ul>\n<li>Wiadomo\u015b\u0107 zielona nigdy nie zostanie przetworzona, poniewa\u017c offset dla tej partycji wskazuje, \u017ce wiadomo\u015b\u0107 z offsetem 0 zosta\u0142a ju\u017c przeprocesowana \u2013 cho\u0107 w rzeczywisto\u015bci jeszcze nie by\u0142a.<\/li>\n<li>Wiadomo\u015b\u0107 pomara\u0144czowa, kt\u00f3ra trafi\u0142a do partycji 1 zamiast do partycji 0, mo\u017ce mie\u0107 offset 1. W kontek\u015bcie zapisanego offsetu dla tej partycji oznacza to, \u017ce musi zosta\u0107 przetworzona \u2013 mimo \u017ce ju\u017c wcze\u015bniej by\u0142a przeprocesowana.<\/li>\n<\/ul>\n<p>Dlatego niezwykle istotne jest, aby podczas odtwarzania zachowa\u0107 zar\u00f3wno poprawne przypisanie wiadomo\u015bci do partycji, jak i ich kolejno\u015b\u0107. Kluczowe jest r\u00f3wnie\u017c odwzorowanie stanu przetwarzania poszczeg\u00f3lnych grup konsument\u00f3w, czyli ich offset\u00f3w.<\/p>\n<p>Jakich konektor\u00f3w mo\u017cna u\u017cy\u0107 do implementacji takiej kopii zapasowej?<\/p>\n<p>Confluent dostarcza odpowiednie konektory, np. <a href=\"https:\/\/docs.confluent.io\/kafka-connectors\/s3-source\/current\/backup-and-restore\/overview.html#limitations\" target=\"_blank\" rel=\"nofollow noopener\">Confluent S3 Source Connector<\/a>. Nale\u017cy jednak pami\u0119ta\u0107, \u017ce wymagaj\u0105 one licencji.<\/p>\n<p>Alternatyw\u0105 s\u0105 opensource\u2019owe konektory Apache Camel S3 Sink oraz Source, jednak maj\u0105 one pewne ograniczenia implementacyjne:<\/p>\n<ul>\n<li>Nie zapisuj\u0105 informacji o partycji, z kt\u00f3rej pochodzi wiadomo\u015b\u0107.<\/li>\n<li>Ka\u017cd\u0105 wiadomo\u015b\u0107 zapisuj\u0105 jako osobny obiekt w S3.<\/li>\n<\/ul>\n<p>Z tego wzgl\u0119du ich produkcyjne u\u017cycie wymaga dostosowania, np. poprzez implementacj\u0119 dedykowanego transformatora wiadomo\u015bci dla konektora sink (ang. Single Message Transformations), kt\u00f3ry b\u0119dzie propagowa\u0107 informacj\u0119 o partycji i offsecie do S3. Oraz drugiego transformatora dla konektora source, kt\u00f3ry u\u017cyje informacji o partycji i offsecie, zapisanych w S3 do poprawnego przywr\u00f3cenia wiadomo\u015bci.<\/p>\n<p>Om\u00f3wili\u015bmy elementy zwi\u0105zane z wysok\u0105 dost\u0119pno\u015bci\u0105 oraz kopi\u0105 zapasow\u0105. Przejd\u017amy do kwestii monitorowania naszej instalacji Kafki na \u015brodowisku produkcyjnym.<\/p>\n<h2>Monitorowanie dzia\u0142ania Kafka<\/h2>\n<p>Dla ka\u017cdego systemu komunikacji zdarzeniowej istotne jest monitorowanie jego dzia\u0142ania produkcyjnego aby chroni\u0107 si\u0119 przed takimi problemami jak utrata danych, przestoje w przetwarzaniu czy niewystarczaj\u0105ca wydajno\u015b\u0107 przetwarzania. Apache Kafka z racji swojej architektury i sposobu dzia\u0142ania wymaga monitorowania stanu\u00a0 klastra, utylizacji zasob\u00f3w, replikacji, konektor\u00f3w oraz wydajno\u015bci przetwarzania.<\/p>\n<p>Apache Kafka potrafi wystawi\u0107 te informacje do Prometheus (<a href=\"https:\/\/prometheus.io\/\" target=\"_blank\" rel=\"nofollow noopener\">https:\/\/prometheus.io\/<\/a>), sk\u0105d te dane mo\u017cna pobra\u0107 i wizualizowa\u0107 na przyk\u0142ad przy u\u017cyciu Grafana (<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"nofollow noopener\">https:\/\/grafana.com\/<\/a>).<\/p>\n<p>Aby zrealizowa\u0107 taki monitoring, w przypadku instalacji klastra Kafka na OpenShift, mo\u017cna zdefiniowa\u0107 odpowiedni PodMonitor czyli byt pochodz\u0105cy z Prometheus Operator, kt\u00f3ry jest wbudowany w platform\u0119 OpenShift:<\/p>\n<pre>apiVersion: monitoring.coreos.com\/v1\nkind: PodMonitor\nmetadata:\n\u00a0 name: kafka-resources-metrics\n\u00a0 labels:\n\u00a0 \u00a0 app: strimzi\nspec:\n\u00a0 selector:\n\u00a0 \u00a0 matchExpressions:\n\u00a0 \u00a0 \u00a0 - key: \"strimzi.io\/kind\"\n\u00a0 \u00a0 \u00a0 \u00a0 operator: In\n\u00a0 \u00a0 \u00a0 \u00a0 values: [\"Kafka\", \"KafkaConnect\", \"KafkaMirrorMaker\", \"KafkaMirrorMaker2\"]\n\u00a0 namespaceSelector:\n\u00a0 \u00a0 matchNames:\n\u00a0 \u00a0 \u00a0 - {{ .Release.Namespace }}\n\u00a0 podMetricsEndpoints:\n\u00a0 - path: \/metrics\n\u00a0 \u00a0 port: tcp-prometheus\n\u00a0 \u00a0 interval: 1m\n\u00a0 \u00a0 relabelings:\n\u00a0 \u00a0 - separator: ;\n\u00a0 \u00a0 \u00a0 regex: __meta_kubernetes_pod_label_(strimzi_io_.+)\n\u00a0 \u00a0 \u00a0 replacement: $1\n\u00a0 \u00a0 \u00a0 action: labelmap\n\n\u00a0\u00a0\u00a0\u00a0 \u2026<\/pre>\n<p>Po wgraniu tej definicji i skonfigurowaniu Grafana otrzymamy nast\u0119puj\u0105cy widok:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18757 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/16.png\" alt=\"\" width=\"1301\" height=\"505\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/16.png 1301w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/16-300x116.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/16-1024x397.png 1024w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/16-768x298.png 768w\" sizes=\"(max-width: 1301px) 100vw, 1301px\" \/><\/p>\n<p>Znajduj\u0105 si\u0119 tu takie informacje jak:<\/p>\n<ul>\n<li>Liczba replik,<\/li>\n<li>Liczba In Sync Replicas,<\/li>\n<li>Szczeg\u00f3\u0142owe dane na temat partycji<\/li>\n<li>Liczb\u0119 wiadomo\u015bci publikowane na sekund\u0119,<\/li>\n<li>Liczb\u0119 wiadomo\u015bci procesowanych przez konsument grupy na sekund\u0119<\/li>\n<li>Lag, czyli r\u00f3\u017cnic\u0119 mi\u0119dzy aktualnym offsetem wiadomo\u015bci na partycjach topicu a offsetem przetworzonym przez grup\u0119 konsument\u00f3w. Im wi\u0119kszy lag tym gorzej, poniewa\u017c mo\u017ce to oznacza\u0107 \u017ce konsument grupa nie nad\u0105\u017ca z procesowaniem wiadomo\u015bci.<\/li>\n<\/ul>\n<p>Dodatkowo mo\u017cna zdefiniowa\u0107 r\u00f3wnie\u017c alerty w oparciu o Prometheus Alert Manager lub Grafana Alerting, dzi\u0119ki czemu mo\u017cliwe b\u0119dzie otrzymywanie powiadomie\u0144 o problemach.<\/p>\n<p>Kolejnym narz\u0119dzie wartym polecenia w tym obszarze jest <a href=\"https:\/\/www.redpanda.com\/redpanda-console-kafka-ui\" target=\"_blank\" rel=\"nofollow noopener\">Redpanda Console<\/a>. \u00a0To narz\u0119dzie pozwala na weryfikacj\u0119 stanu klastra, konektor\u00f3w, konsumer grup oraz topic\u00f3w:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18759 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/17.png\" alt=\"\" width=\"1118\" height=\"507\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/17.png 1118w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/17-300x136.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/17-1024x464.png 1024w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/17-768x348.png 768w\" sizes=\"(max-width: 1118px) 100vw, 1118px\" \/><\/p>\n<p>Dodatkowo narz\u0119dzie to pozwala na wykonywanie operacji aktywnych jak na przyk\u0142ad restart konektora, usuni\u0119cie wiadomo\u015bci z topicu, usuni\u0119cie topicu. Wszystkie te funkcjonalno\u015bci s\u0105 przydatne przy codziennym utrzymaniu Kafki i wykonywaniu operacji administracyjnych.<\/p>\n<p>Wyposa\u017ceni w narz\u0119dzia monitoruj\u0105ce, mo\u017cemy przej\u015b\u0107 do ostatniego tematu jakim jest wysoka wydajno\u015b\u0107 przetwarzania.<\/p>\n<h2>Wysoka wydajno\u015b\u0107 przetwarzania<\/h2>\n<p>Systemy komunikacji zdarzeniowej musz\u0105 odznacza\u0107 si\u0119 wysok\u0105 wydajno\u015bci\u0105 przetwarzania danych. Integruj\u0105 one i przesy\u0142aj\u0105 wiadomo\u015bci mi\u0119dzy r\u00f3\u017cnymi systemami i zbyt wolne przetwarzanie komunikat\u00f3w mo\u017ce prowadzi\u0107 do powa\u017cnych problem\u00f3w zw\u0142aszcza w rozwi\u0105zaniach zbli\u017conych do rozwi\u0105za\u0144 czasu rzeczywistego.<\/p>\n<p>Jak ju\u017c wspomnia\u0142em w punkcie dotycz\u0105cym architektury, wa\u017cnym elementem zapewnienia wydajno\u015bci przetwarzania jest odpowiednie dobranie liczby partycji dla topic\u00f3w. Liczba partycji okre\u015bla nam maksymaln\u0105 liczb\u0119 w\u0105tk\u00f3w procesuj\u0105cych r\u00f3wnolegle dane z danego topicu. Ale to nie jedyny parametr o kt\u00f3rym nale\u017cy pami\u0119ta\u0107.<\/p>\n<p>Kafka procesuje ogromne ilo\u015bci danych kt\u00f3re s\u0105 nieustanie przesy\u0142ane mi\u0119dzy klientami a brokerami oraz pomi\u0119dzy brokerami w ramach procesu replikacji. Dlatego istotne jest aby narzuty na ruch sieciowy nie powodowa\u0142y problemu z wydajno\u015bci\u0105. Wp\u0142yw narzut\u00f3w komunikacji sieciowej ma ogromny wp\u0142yw na wydajno\u015b\u0107 ca\u0142ego przetwarzania. Apache Kafka dostarcza nam w tym zakresie kilku parametr\u00f3w:<\/p>\n<ul>\n<li>Kompresja (compression.type) \u2013 pozwala na w\u0142\u0105czenie kompresji ze strony producenta np. konektora lub aplikacji streamowej. Dzi\u0119ki kompresji mo\u017cemy znacz\u0105co zmniejszy\u0107 rozmiar przesy\u0142anych przez sie\u0107 danych. Kafka wspiera nast\u0119puj\u0105ce typy kompresji: none, gzip, snappy, lz4, zstd. Domy\u015blnie w\u0142\u0105czona jest kompresja typu \u2018none\u2019 czyli brak kompresji. Nie jest to zalecane ustawienie dla wdro\u017ce\u0144 produkcyjnych chyba, \u017ce zachodz\u0105 uzasadnione powody dla takiej konfiguracji. Kompresja jest w\u0142\u0105czana po stronie producenta Kafki. Konsumenci nie wymagaj\u0105 specjalnej konfiguracji a proces dekompresji realizowany po\u00a0 stronie konsumenta zachodzi automatycznie za spraw\u0105 bibliotek klienckich Kafki. W\u0142\u0105czenie kompresji wprowadza narzut na przeprowadzenie tego procesu po stronie producenta i konsumenta ale generalnie, mimo tego narzutu, znacz\u0105co zwi\u0119ksza przepustowo\u015b\u0107 producenta,<\/li>\n<li>Rozmiar batch (batch.size) \u2013 kolejny parametr dedykowany dla producenta Kafka. Okre\u015bla w jakich \u2018paczkach\u2019 producent wysy\u0142a wiadomo\u015bci a jego domy\u015blna warto\u015b\u0107 do 16KB. Oznacza to, \u017ce je\u015bli nasze wiadomo\u015bci maj\u0105 rozmiar wi\u0119kszy od 16KB to ka\u017cda z tych wiadomo\u015bci b\u0119dzie wysy\u0142ana oddzielnie co przek\u0142ada si\u0119 na negatywny wp\u0142yw narzut\u00f3w sieciowych na przepustowo\u015b\u0107. Lepiej wysy\u0142a\u0107 rzadziej a wi\u0119cej, dlatego warto rozwa\u017cy\u0107 dostosowanie warto\u015bci tego parametru do rozmiaru naszych wiadomo\u015bci,<\/li>\n<li>Czas op\u00f3\u017anienia\/\u2019marudzenia\u2019 (linger.ms) \u2013 r\u00f3wnie\u017c parametr dedykowany dla producent\u00f3w Kafka i \u015bci\u015ble powi\u0105zany z parametrem batch.size. Parametr ten okre\u015bla ile czasu producent czeka na wype\u0142nienie si\u0119 batch. Je\u015bli batch wype\u0142ni si\u0119 wiadomo\u015bciami przed up\u0142ywem tego czasu to taki batch jest wysy\u0142any. Je\u015bli brach nie jest wype\u0142niony wiadomo\u015bciami ale up\u0142yn\u0105\u0142 czas linger to r\u00f3wnie\u017c batch jest wysy\u0142any. Domy\u015blna warto\u015b\u0107 tego parametru to 0ms co oznacza \u017ce wiadomo\u015bci wys\u0142ane s\u0105 natychmiast czyli zn\u00f3w wysy\u0142amy bardzo cz\u0119sto a narzuty sieciowe mog\u0105 mie\u0107 negatywny wp\u0142yw na przepustowo\u015b\u0107 naszego rozwi\u0105zania.<\/li>\n<\/ul>\n<p>Poni\u017cej przyk\u0142ad dla jednego z realizowanych system\u00f3w:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18761 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/18.png\" alt=\"\" width=\"1248\" height=\"378\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/18.png 1248w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/18-300x91.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/18-1024x310.png 1024w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/18-768x233.png 768w\" sizes=\"(max-width: 1248px) 100vw, 1248px\" \/><\/p>\n<p>Jak wida\u0107 na za\u0142\u0105czonych wykresach system wykorzystuje 3 aplikacje\u00a0 streamowe. Jedna z tych aplikacji (wykres \u017c\u00f3\u0142ty) przetwarza oko\u0142o 1250 wiadomo\u015bci na sekund\u0119, aplikacja zielona przetwarza 750 wiadomo\u015bci, a aplikacja niebieska najmniej \u2013 poni\u017cej 500 wiadomo\u015bci na sekund\u0119. Skutkiem tego aplikacja niebieska ma najwi\u0119kszy lag (co wida\u0107 na wykresie po prawej), kt\u00f3ry nieustannie ro\u015bnie co mo\u017ce skutkowa\u0107 zbyt p\u00f3\u017anym dostarczeniem danych do system\u00f3w docelowych.<\/p>\n<p>Po zmianie opisanych wy\u017cej parametr\u00f3w:<\/p>\n<ul>\n<li>type=lz4 dla wszystkich producent\u00f3w,<\/li>\n<li>size=128KB dla wszystkich producent\u00f3w,<\/li>\n<li>ms=100ms dla wszystkich producent\u00f3w,<\/li>\n<\/ul>\n<p>otrzymali\u015bmy nast\u0119puj\u0105ce rezultaty:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-18763 size-full\" src=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/19.png\" alt=\"\" width=\"1248\" height=\"375\" srcset=\"https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/19.png 1248w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/19-300x90.png 300w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/19-1024x308.png 1024w, https:\/\/inteca.com\/wp-content\/uploads\/2025\/03\/19-768x231.png 768w\" sizes=\"(max-width: 1248px) 100vw, 1248px\" \/><\/p>\n<p>Na wykresie prezentuj\u0105cym liczb\u0119 wiadomo\u015bci konsumowanych na sekund\u0119 (po lewej stronie), wykresy wszystkich aplikacji nachodz\u0105 na siebie co oznacza \u017ce aplikacje te osi\u0105gaj\u0105 niemal identyczne warto\u015bci procesowanych wiadomo\u015bci na sekund\u0119. Na wykresie prezentuj\u0105cym lag poszczeg\u00f3lnych konsument\u00f3w (prawa strona) wida\u0107 \u017ce \u017caden z nich nie ro\u015bnie, utrzymuj\u0105 si\u0119 na niskim poziomie co jest po\u017c\u0105danym zachowaniem. Wynik jest o tyle niesamowity, \u017ce mi\u0119dzy pierwszym a drugim przebiegiem \u017cadne inne parametry nie zosta\u0142y zmienione, nie wprowadzono \u017cadnych zmian w aplikacji a test wykonywano na tych samych serwerach. Wp\u0142yw tylko tych trzech parametr\u00f3w na przepustowo\u015b\u0107 jest ogromny.<\/p>\n<p>Zaprezentowane wy\u017cej warto\u015bci parametr\u00f3w nie stanowi\u0105 \u017cadnej referencji albo jedynego s\u0142usznego rozwi\u0105zania. W ka\u017cdym przypadku warto\u015bci tych parametr\u00f3w mog\u0105 by\u0107 inne i nale\u017cy je dobra\u0107 z \u2018g\u0142ow\u0105\u2019 na bazie test\u00f3w wydajno\u015bciowych i specyfiki danego rozwi\u0105zania. Dodatkowo przed \u2018kr\u0119ceniem\u2019 tymi parametrami powinni\u015bmy zadba\u0107, w pierwszej kolejno\u015bci, o wydajno\u015b\u0107 naszych aplikacji \u2013 w kontek\u015bcie Kafki aplikacje te, zw\u0142aszcza streamowe, powinny procesowa\u0107 wiadomo\u015bci bardzo szybko tzn. na poziomie milisekund lub kilkunastu milisekund. D\u0142u\u017csze czasy procesowania mog\u0105 spowodowa\u0107, \u017ce nawet strojenie wskazanych wy\u017cej parametr\u00f3w nic nie zmieni.<\/p>\n<h2>Podsumowanie<\/h2>\n<p>Apache Kafka jest rozwi\u0105zaniem, kt\u00f3re z powodzeniem mo\u017ce by\u0107 u\u017cywane w celu zapewnienia wydajnej i bezpiecznej komunikacji opartej o zdarzenia. W artykule star\u0142em si\u0119 zaadresowa\u0107 r\u00f3\u017cne obszary funkcjonalne, kt\u00f3ra s\u0105 podstaw\u0105 dla dzia\u0142ania takich system\u00f3w i musz\u0105 by\u0107 uwzgl\u0119dnione w momencie ich wdra\u017cania. Mam nadziej\u0119 \u017ce zebrane tu informacje pozwol\u0105 Wam w spos\u00f3b efektywny u\u017cywa\u0107 Kafki. Celem artyku\u0142u by\u0142o podzielenie si\u0119 rzeczywistymi do\u015bwiadczeniami projektowymi, a fakt \u017ce Kafka w wielu aspektach wypada \u015bwietnie to wy\u0142\u0105cznie zas\u0142uga Kafki i nie jest to \u017cadna forma lokowania produktu \ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Systemy komunikacji zdarzeniowej (Message Brokers) umo\u017cliwiaj\u0105 lu\u017ane powi\u0105zanie mi\u0119dzy us\u0142ugami i komponentami w organizacji lub projekcie, zapewniaj\u0105c jednocze\u015bnie asynchroniczn\u0105 komunikacj\u0119, skalowalno\u015b\u0107, wysok\u0105 przepustowo\u015b\u0107, niezawodno\u015b\u0107 oraz bezpiecze\u0144stwo przesy\u0142anych danych. Apache Kafka to jeden z najpopularniejszych broker\u00f3w wiadomo\u015bci, znany ze swojej wydajno\u015bci i szeroko stosowany przez firmy takie jak Netflix, Uber czy LinkedIn. Ale czy rzeczywi\u015bcie spe\u0142nia&#8230;<\/p>\n","protected":false},"author":23,"featured_media":23045,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","format":"standard","meta":{"_acf_changed":false,"qubely_global_settings":"","qubely_interactions":"","_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","_kadence_starter_templates_imported_post":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[],"tags":[367,71,74],"class_list":["post-18714","technical-blog","type-technical-blog","status-publish","format-standard","has-post-thumbnail","hentry","tag-apache-kafka","tag-big-data","tag-kafka-stream"],"acf":[],"aioseo_notices":[],"qubely_featured_image_url":{"full":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png",1000,523,false],"landscape":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png",1000,523,false],"portraits":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka-540x320.png",540,320,true],"thumbnail":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka-150x150.png",150,150,true],"medium":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka-300x157.png",300,157,true],"medium_large":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka-768x402.png",768,402,true],"large":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png",1000,523,false],"1536x1536":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png",1000,523,false],"2048x2048":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png",1000,523,false],"qubely_landscape":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png",1000,523,false],"qubely_portrait":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka-540x320.png",540,320,true],"qubely_thumbnail":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka-140x100.png",140,100,true]},"qubely_author":{"display_name":"S\u0142awomir Pasieczny","author_link":"https:\/\/inteca.com\/pl\/blog\/author\/slawomirpasieczny\/"},"qubely_comment":0,"qubely_category":false,"qubely_excerpt":"Systemy komunikacji zdarzeniowej (Message Brokers) umo\u017cliwiaj\u0105 lu\u017ane powi\u0105zanie mi\u0119dzy us\u0142ugami i komponentami w organizacji lub projekcie, zapewniaj\u0105c jednocze\u015bnie asynchroniczn\u0105 komunikacj\u0119, skalowalno\u015b\u0107, wysok\u0105 przepustowo\u015b\u0107, niezawodno\u015b\u0107 oraz bezpiecze\u0144stwo przesy\u0142anych danych. Apache Kafka to jeden z najpopularniejszych broker\u00f3w wiadomo\u015bci, znany ze swojej wydajno\u015bci i szeroko stosowany przez firmy takie jak Netflix, Uber czy LinkedIn. Ale czy rzeczywi\u015bcie spe\u0142nia...","taxonomy_info":{"post_tag":[{"value":367,"label":"Apache Kafka"},{"value":71,"label":"big data"},{"value":74,"label":"kafka stream"}]},"featured_image_src_large":["https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png",1000,523,false],"author_info":{"display_name":"S\u0142awomir Pasieczny","author_link":"https:\/\/inteca.com\/pl\/blog\/author\/slawomirpasieczny\/"},"comment_info":0,"aioseo_head":"\n\t\t<!-- All in One SEO Pro 4.9.5.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\u0144. Dowiedz si\u0119, jak dobrze skonfigurowa\u0107, optymalizowa\u0107 i monitorowa\u0107 Kafk\u0119.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"S\u0142awomir Pasieczny\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO Pro (AIOSEO) 4.9.5.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Inteca \u00bb IT&#039;s about business\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja\" \/>\n\t\t<meta property=\"og:description\" content=\"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\u0144. Dowiedz si\u0119, jak dobrze skonfigurowa\u0107, optymalizowa\u0107 i monitorowa\u0107 Kafk\u0119.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png\" \/>\n\t\t<meta property=\"og:image:width\" content=\"1000\" \/>\n\t\t<meta property=\"og:image:height\" content=\"523\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2025-03-24T13:59:33+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2025-10-26T13:58:55+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\u0144. Dowiedz si\u0119, jak dobrze skonfigurowa\u0107, optymalizowa\u0107 i monitorowa\u0107 Kafk\u0119.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#blogposting\",\"name\":\"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja\",\"headline\":\"Apache Kafka w praktyce\",\"author\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/author\\\/slawomirpasieczny\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/inteca.com\\\/wp-content\\\/uploads\\\/2022\\\/11\\\/Apache-Kafka.png\",\"width\":1000,\"height\":523},\"datePublished\":\"2025-03-24T15:59:33+02:00\",\"dateModified\":\"2025-10-26T15:58:55+02:00\",\"inLanguage\":\"pl-PL\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#webpage\"},\"articleSection\":\"Apache Kafka, big data, kafka stream\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/inteca.com\\\/pl\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/#listItem\",\"name\":\"Technical blog\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/#listItem\",\"position\":2,\"name\":\"Technical blog\",\"item\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/tag\\\/big-data\\\/#listItem\",\"name\":\"big data\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/tag\\\/big-data\\\/#listItem\",\"position\":3,\"name\":\"big data\",\"item\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/tag\\\/big-data\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#listItem\",\"name\":\"Apache Kafka w praktyce\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/#listItem\",\"name\":\"Technical blog\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#listItem\",\"position\":4,\"name\":\"Apache Kafka w praktyce\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/tag\\\/big-data\\\/#listItem\",\"name\":\"big data\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/#organization\",\"name\":\"Inteca Sp. z o.o.\",\"description\":\"Inteca is a specialized enterprise platform provider and Red Hat Advanced Partner. We design, implement, and operate mission-critical platforms based on Keycloak, Kafka, OpenShift, and Nuxeo enhanced with AI automation. We work in banking, insurance, and government sectors across the EU and the US.\",\"url\":\"https:\\\/\\\/inteca.com\\\/pl\\\/\",\"email\":\"contact@inteca.com\",\"telephone\":\"+48717156091\",\"foundingDate\":\"2011-04-01\",\"numberOfEmployees\":{\"@type\":\"QuantitativeValue\",\"value\":50},\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/inteca.com\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/Inteca_logo_pion_tagline_JasneTlo.png\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#organizationLogo\",\"width\":288,\"height\":344},\"image\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#organizationLogo\"},\"sameAs\":[\"https:\\\/\\\/pl.linkedin.com\\\/company\\\/inteca\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/author\\\/slawomirpasieczny\\\/#author\",\"url\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/author\\\/slawomirpasieczny\\\/\",\"name\":\"S\\u0142awomir Pasieczny\",\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ca005371f46ec895c54e25b0ed4303abd0d345351a2bafe13f4d086108326408?s=96&d=blank&r=g\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#webpage\",\"url\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/\",\"name\":\"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja\",\"description\":\"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\\u0144. Dowiedz si\\u0119, jak dobrze skonfigurowa\\u0107, optymalizowa\\u0107 i monitorowa\\u0107 Kafk\\u0119.\",\"inLanguage\":\"pl-PL\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/author\\\/slawomirpasieczny\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog\\\/author\\\/slawomirpasieczny\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/inteca.com\\\/wp-content\\\/uploads\\\/2022\\\/11\\\/Apache-Kafka.png\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#mainImage\",\"width\":1000,\"height\":523},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/blog-technologiczny\\\/apache-kafka-w-praktyce\\\/#mainImage\"},\"datePublished\":\"2025-03-24T15:59:33+02:00\",\"dateModified\":\"2025-10-26T15:58:55+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/#website\",\"url\":\"https:\\\/\\\/inteca.com\\\/pl\\\/\",\"name\":\"Inteca\",\"alternateName\":\"Inteca\",\"description\":\"IT's about business\",\"inLanguage\":\"pl-PL\",\"publisher\":{\"@id\":\"https:\\\/\\\/inteca.com\\\/pl\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO Pro -->\r\n\t\t<title>Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja<\/title>\n\n","aioseo_head_json":{"title":"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja","description":"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\u0144. Dowiedz si\u0119, jak dobrze skonfigurowa\u0107, optymalizowa\u0107 i monitorowa\u0107 Kafk\u0119.","canonical_url":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#blogposting","name":"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja","headline":"Apache Kafka w praktyce","author":{"@id":"https:\/\/inteca.com\/pl\/blog\/author\/slawomirpasieczny\/#author"},"publisher":{"@id":"https:\/\/inteca.com\/pl\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png","width":1000,"height":523},"datePublished":"2025-03-24T15:59:33+02:00","dateModified":"2025-10-26T15:58:55+02:00","inLanguage":"pl-PL","mainEntityOfPage":{"@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#webpage"},"isPartOf":{"@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#webpage"},"articleSection":"Apache Kafka, big data, kafka stream"},{"@type":"BreadcrumbList","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/#listItem","position":1,"name":"Home","item":"https:\/\/inteca.com\/pl\/","nextItem":{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/#listItem","name":"Technical blog"}},{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/#listItem","position":2,"name":"Technical blog","item":"https:\/\/inteca.com\/pl\/blog-technologiczny\/","nextItem":{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/blog\/tag\/big-data\/#listItem","name":"big data"},"previousItem":{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/blog\/tag\/big-data\/#listItem","position":3,"name":"big data","item":"https:\/\/inteca.com\/pl\/blog\/tag\/big-data\/","nextItem":{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#listItem","name":"Apache Kafka w praktyce"},"previousItem":{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/#listItem","name":"Technical blog"}},{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#listItem","position":4,"name":"Apache Kafka w praktyce","previousItem":{"@type":"ListItem","@id":"https:\/\/inteca.com\/pl\/blog\/tag\/big-data\/#listItem","name":"big data"}}]},{"@type":"Organization","@id":"https:\/\/inteca.com\/pl\/#organization","name":"Inteca Sp. z o.o.","description":"Inteca is a specialized enterprise platform provider and Red Hat Advanced Partner. We design, implement, and operate mission-critical platforms based on Keycloak, Kafka, OpenShift, and Nuxeo enhanced with AI automation. We work in banking, insurance, and government sectors across the EU and the US.","url":"https:\/\/inteca.com\/pl\/","email":"contact@inteca.com","telephone":"+48717156091","foundingDate":"2011-04-01","numberOfEmployees":{"@type":"QuantitativeValue","value":50},"logo":{"@type":"ImageObject","url":"https:\/\/inteca.com\/wp-content\/uploads\/2022\/01\/Inteca_logo_pion_tagline_JasneTlo.png","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#organizationLogo","width":288,"height":344},"image":{"@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#organizationLogo"},"sameAs":["https:\/\/pl.linkedin.com\/company\/inteca"]},{"@type":"Person","@id":"https:\/\/inteca.com\/pl\/blog\/author\/slawomirpasieczny\/#author","url":"https:\/\/inteca.com\/pl\/blog\/author\/slawomirpasieczny\/","name":"S\u0142awomir Pasieczny","image":{"@type":"ImageObject","url":"https:\/\/secure.gravatar.com\/avatar\/ca005371f46ec895c54e25b0ed4303abd0d345351a2bafe13f4d086108326408?s=96&d=blank&r=g"}},{"@type":"WebPage","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#webpage","url":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/","name":"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja","description":"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\u0144. Dowiedz si\u0119, jak dobrze skonfigurowa\u0107, optymalizowa\u0107 i monitorowa\u0107 Kafk\u0119.","inLanguage":"pl-PL","isPartOf":{"@id":"https:\/\/inteca.com\/pl\/#website"},"breadcrumb":{"@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#breadcrumblist"},"author":{"@id":"https:\/\/inteca.com\/pl\/blog\/author\/slawomirpasieczny\/#author"},"creator":{"@id":"https:\/\/inteca.com\/pl\/blog\/author\/slawomirpasieczny\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png","@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#mainImage","width":1000,"height":523},"primaryImageOfPage":{"@id":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/#mainImage"},"datePublished":"2025-03-24T15:59:33+02:00","dateModified":"2025-10-26T15:58:55+02:00"},{"@type":"WebSite","@id":"https:\/\/inteca.com\/pl\/#website","url":"https:\/\/inteca.com\/pl\/","name":"Inteca","alternateName":"Inteca","description":"IT's about business","inLanguage":"pl-PL","publisher":{"@id":"https:\/\/inteca.com\/pl\/#organization"}}]},"og:locale":"pl_PL","og:site_name":"Inteca \u00bb IT's about business","og:type":"article","og:title":"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja","og:description":"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\u0144. Dowiedz si\u0119, jak dobrze skonfigurowa\u0107, optymalizowa\u0107 i monitorowa\u0107 Kafk\u0119.","og:url":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/","og:image":"https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png","og:image:secure_url":"https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png","og:image:width":1000,"og:image:height":523,"article:published_time":"2025-03-24T13:59:33+00:00","article:modified_time":"2025-10-26T13:58:55+00:00","twitter:card":"summary_large_image","twitter:title":"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja","twitter:description":"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\u0144. Dowiedz si\u0119, jak dobrze skonfigurowa\u0107, optymalizowa\u0107 i monitorowa\u0107 Kafk\u0119.","twitter:image":"https:\/\/inteca.com\/wp-content\/uploads\/2022\/11\/Apache-Kafka.png"},"aioseo_meta_data":{"post_id":"18714","title":"Apache Kafka w praktyce: architektura, konfiguracja i optymalizacja","description":"Praktyczne zastosowanie Apache Kafka w systemach komunikacji zdarze\u0144. Dowiedz si\u0119, jak dobrze skonfigurowa\u0107, optymalizowa\u0107 i monitorowa\u0107 Kafk\u0119.","keywords":null,"keyphrases":{"focus":{"keyphrase":"Apache kafka","score":82,"analysis":{"keyphraseInTitle":{"score":9,"maxScore":9,"error":0},"keyphraseInDescription":{"score":9,"maxScore":9,"error":0},"keyphraseLength":{"score":9,"maxScore":9,"error":0,"length":2},"keyphraseInURL":{"score":5,"maxScore":5,"error":0},"keyphraseInIntroduction":{"score":3,"maxScore":9,"error":1},"keyphraseInSubHeadings":{"score":3,"maxScore":9,"error":1},"keyphraseInImageAlt":{"score":9,"maxScore":9,"error":0},"keywordDensity":{"type":"best","score":9,"maxScore":9,"error":0}}},"additional":[]},"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":"","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":"WebPage","isEnabled":true},"graphs":[]},"schema_type":"default","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":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":"0","open_ai":"{\"title\":{\"suggestions\":[],\"usage\":0},\"description\":{\"suggestions\":[],\"usage\":0}}","ai":{"faqs":[],"keyPoints":[],"titles":[],"descriptions":[],"socialPosts":{"email":[],"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"created":"2025-03-24 13:14:34","updated":"2025-10-26 14:01:48"},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t<a href=\"https:\/\/inteca.com\/pl\/\" title=\"Home\">Home<\/a>\n<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t<a href=\"https:\/\/inteca.com\/pl\/blog-technologiczny\/\" title=\"Technical blog\">Technical blog<\/a>\n<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t<a href=\"https:\/\/inteca.com\/pl\/blog\/tag\/big-data\/\" title=\"big data\">big data<\/a>\n<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\tApache Kafka w praktyce\n<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/inteca.com\/pl\/"},{"label":"Technical blog","link":"https:\/\/inteca.com\/pl\/blog-technologiczny\/"},{"label":"big data","link":"https:\/\/inteca.com\/pl\/blog\/tag\/big-data\/"},{"label":"Apache Kafka w praktyce","link":"https:\/\/inteca.com\/pl\/blog-technologiczny\/apache-kafka-w-praktyce\/"}],"_links":{"self":[{"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/technical-blog\/18714","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/technical-blog"}],"about":[{"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/types\/technical-blog"}],"author":[{"embeddable":true,"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/users\/23"}],"replies":[{"embeddable":true,"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/comments?post=18714"}],"version-history":[{"count":0,"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/technical-blog\/18714\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/media\/23045"}],"wp:attachment":[{"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/media?parent=18714"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/categories?post=18714"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/inteca.com\/pl\/wp-json\/wp\/v2\/tags?post=18714"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}