{"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\/de\/blog\/administrirovanie\/ponimanie-brokerov-soobshhenij-izuchenie-mehaniki-obmena-soobshheniyami-posredstvom-activemq-i-kafka-glava-3-kafka","title":{"rendered":"Verst\u00e4ndnis von Nachrichtenbrokern. Untersuchung der Mechanik des Nachrichtenaustauschs \u00fcber ActiveMQ und Kafka. Kapitel 3. Kafka","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Fortsetzung der \u00dcbersetzung eines kleinen Buches:<br \/>\n\u201eUnderstanding Message Brokers\u201c<br \/>\nAutor: Jakub Korab, Verlag: O'Reilly Media, Inc., Ver\u00f6ffentlichungsdatum: Juni 2017, ISBN: 9781492049296.<\/p>\n<p>Der vorherige \u00fcbersetzte Abschnitt: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">Verst\u00e4ndnis von Nachrichtenbrokern. Untersuchung der Mechanismen des Nachrichtenaustauschs \u00fcber ActiveMQ und Kafka. Kapitel 1. Einf\u00fchrung<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>KAPITEL 3<\/h2>\n<p><\/p>\n<h2>Kafka<\/h2>\n<p>\nKafka wurde bei LinkedIn entwickelt, um einige Einschr\u00e4nkungen traditioneller Nachrichtenbroker zu umgehen und die Notwendigkeit zu vermeiden, mehrere Nachrichtenbroker f\u00fcr verschiedene \u201ePoint-to-Point\u201c-Interaktionen einzurichten, was in diesem Buch im Abschnitt \u201eVertikale und horizontale Skalierung\u201c auf Seite 28 beschrieben wird. Die Anwendungsf\u00e4lle bei LinkedIn basierten haupts\u00e4chlich auf der unidirektionalen Verarbeitung sehr gro\u00dfer Datenmengen, wie z.B. Seitenaufrufen und Zugriffsprotokollen, w\u00e4hrend gleichzeitig mehreren Systemen der Zugriff auf diese Daten erm\u00f6glicht wurde, ohne die Leistung der Produzenten oder anderer Verbraucher zu beeintr\u00e4chtigen. Tats\u00e4chlich besteht der Grund f\u00fcr die Existenz von Kafka darin, eine solche Architektur des Nachrichtenaustauschs zu schaffen, wie sie die Universal Data Pipeline beschreibt.<\/p>\n<p>In Anbetracht dieses Endziels sind nat\u00fcrlich auch weitere Anforderungen entstanden. Kafka muss:<\/p>\n<ul>\n<li>\u00e4u\u00dferst schnell sein<\/li>\n<li>Eine hohe Durchsatzrate beim Verarbeiten von Nachrichten bieten<\/li>\n<li>Die Modelle \u201ePublisher-Subscriber\u201c und \u201ePoint-to-Point\u201c unterst\u00fctzen<\/li>\n<li>Bei der Hinzuf\u00fcgung von Verbrauchern nicht langsamer werden. Beispielsweise verschlechtert sich die Leistung von Warteschlangen und Themen in ActiveMQ bei steigender Anzahl von Verbrauchern am Endpunkt.<\/li>\n<li>Horizontale Skalierbarkeit erm\u00f6glichen; wenn ein Broker, der Nachrichten speichert, dies nur mit der maximalen Geschwindigkeit der Festplatte tun kann, macht es Sinn, \u00fcber ein einzelnes Broker-Exemplar hinauszugehen, um die Leistung zu steigern.<\/li>\n<li>Den Zugang zum Speichern und Abrufen von Nachrichten zu differenzieren.<\/li>\n<\/ul>\n<p>\nUm all dies zu erreichen, hat Kafka eine Architektur angenommen, die die Rollen und Aufgaben von Clients und Message-Brokern neu definiert hat. Das JMS-Modell ist stark brokerzentriert, wo der Broker f\u00fcr die Verbreitung von Nachrichten verantwortlich ist, w\u00e4hrend die Clients sich nur um das Senden und Empfangen von Nachrichten k\u00fcmmern m\u00fcssen. Kafka hingegen ist clientzentriert, wobei der Client viele Funktionen des traditionellen Brokers \u00fcbernimmt, wie die faire Verteilung relevanter Nachrichten unter den Verbrauchern, im Austausch f\u00fcr einen extrem schnellen und skalierbaren Broker. F\u00fcr Menschen, die mit traditionellen Nachrichtenaustauschsystemen gearbeitet haben, erfordert die Arbeit mit Kafka grundlegende \u00c4nderungen in der Sichtweise.<br \/>\nDieser Ingenieursansatz hat zur Schaffung einer Messaging-Infrastruktur gef\u00fchrt, die die Durchsatzkapazit\u00e4t um viele Gr\u00f6\u00dfenordnungen im Vergleich zu einem herk\u00f6mmlichen Broker steigern kann. Wie wir sehen werden, ist dieser Ansatz mit Kompromissen verbunden, die darauf hindeuten, dass Kafka nicht f\u00fcr bestimmte Arten von Lasten und etablerter Software geeignet ist.<\/p>\n<h3>Einheitliches Adressatmodell<\/h3>\n<p>\nUm die oben beschriebenen Anforderungen zu erf\u00fcllen, hat Kafka den Nachrichtenaustausch im \"Publisher-Subscriber\"- und \"Point-to-Point\"-Modell in einem einzigen Adressatstyp zusammengef\u00fchrt \u2014 <i>dem Topic<\/i>. Dies verwirrt Menschen, die mit Messaging-Systemen gearbeitet haben, bei denen das Wort \"Topic\" sich auf einen Broadcast-Mechanismus bezieht, bei dem das Lesen (aus dem Topic) nicht zuverl\u00e4ssig (is nondurable) ist. Die Topics in Kafka sollten als hybride Art von Adressat betrachtet werden, gem\u00e4\u00df der Definition, die in der Einleitung zu diesem Buch gegeben wurde.<\/p>\n<blockquote><p>Im verbleibenden Teil dieses Kapitels wird, sofern nicht ausdr\u00fccklich anders angegeben, der Begriff \"Topic\" sich auf das Kafka-Topic beziehen.<\/p><\/blockquote>\n<p>\nUm vollst\u00e4ndig zu verstehen, wie sich die Topics verhalten und welche Garantien sie bieten, m\u00fcssen wir zun\u00e4chst untersuchen, wie sie in Kafka implementiert sind.<br \/>\n<i>Jedes Topic in Kafka hat sein eigenes Protokoll.<\/i><br \/>\nProduzenten, die Nachrichten an Kafka senden, f\u00fcgen diesem Protokoll Eintr\u00e4ge hinzu, w\u00e4hrend Konsumenten aus dem Protokoll mit Hilfe von Zeigern lesen, die st\u00e4ndig vorw\u00e4rts bewegt werden. Periodisch entfernt Kafka die \u00e4ltesten Teile des Protokolls, unabh\u00e4ngig davon, ob diese Teile gelesen wurden oder nicht. Ein zentrales Merkmal von Kafkas Design ist, dass der Broker sich nicht darum k\u00fcmmert, ob die Nachrichten gelesen wurden oder nicht \u2014 das ist die Verantwortung des Clients.<\/p>\n<blockquote><p>Die Begriffe \u201eProtokoll\u201c und \u201eZeiger\u201c kommen in <noindex><a rel=\"nofollow\" href=\"https:\/\/kafka.apache.org\/documentation.html\">der Kafka-Dokumentation<\/a><\/noindex>. Diese gut bekannten Begriffe werden hier verwendet, um das Verst\u00e4ndnis zu erleichtern.<\/p><\/blockquote>\n<p>\nDieses Modell unterscheidet sich vollst\u00e4ndig von ActiveMQ, wo Nachrichten aus allen Warteschlangen in einem einzigen Protokoll gespeichert werden und der Broker die Nachrichten als gel\u00f6scht markiert, nachdem sie gelesen wurden.<br \/>\nLassen Sie uns nun etwas tiefer eintauchen und das Protokoll eines Themas genauer betrachten.<br \/>\nDas Kafka-Protokoll besteht aus mehreren Partitionen (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/tm\/w2\/yf\/tmw2yf3lanppqtrumxoidotplhi.png\">Abbildung 3-1<\/a><\/noindex>). Kafka garantiert eine strenge Reihenfolge in jeder Partition. Das bedeutet, dass Nachrichten, die in einer bestimmten Reihenfolge in eine Partition geschrieben werden, in derselben Reihenfolge gelesen werden. Jede Partition wird als zirkul\u00e4re Protokolldatei (rolling log file) implementiert, die ein <i>Teilmenge <\/i>(subset) aller Nachrichten enth\u00e4lt, die von seinen Produzenten an das Thema gesendet wurden. Standardm\u00e4\u00dfig enth\u00e4lt das erstellte Thema eine Partition. Die Idee der Partitionen ist das zentrale Konzept von Kafka f\u00fcr horizontale Skalierung.<\/p>\n<p><img decoding=\"async\" alt=\"Verst\u00e4ndnis von Nachrichtenbrokern. Untersuchung der Mechanik des Nachrichtenaustauschs \u00fcber ActiveMQ und Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/39f41ebcb73ec247656c0dea438158a9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Abbildung 3-1. Kafka-Partitionen<\/i><\/p>\n<p>Wenn ein Produzent eine Nachricht an das Kafka-Thema sendet, entscheidet er, in welche Partition er die Nachricht senden m\u00f6chte. Darauf werden wir sp\u00e4ter genauer eingehen.<\/p>\n<h2>Nachrichten lesen<\/h2>\n<p>\nEin Client, der Nachrichten lesen m\u00f6chte, verwaltet einen benannten Zeiger, der als <i>Verbrauchergruppe (consumer group)<\/i>bezeichnet wird, der auf das <i>Offset<\/i> einer Nachricht in der Partition zeigt. Das Offset ist eine Position mit fortlaufender Nummer, die bei 0 am Anfang der Partition beginnt. Diese Verbrauchergruppe, die in der API \u00fcber eine benutzerdefinierte Kennung group_id referenziert wird, entspricht <i>einem logischen Verbrauchenden oder System.<\/i>.<\/p>\n<p>Die meisten Systeme, die Messaging verwenden, lesen Daten vom Empf\u00e4nger durch mehrere Instanzen und Streams zur parallelen Verarbeitung von Nachrichten. Daher gibt es normalerweise viele Instanzen von Konsumenten, die sich eine Gruppe von Konsumenten teilen.<\/p>\n<p>Das Leseproblem kann wie folgt dargestellt werden:<\/p>\n<ul>\n<li>Ein Thema hat mehrere Partitionen<\/li>\n<li>Mehrere Gruppen von Konsumenten k\u00f6nnen gleichzeitig ein Thema nutzen<\/li>\n<li>Eine Gruppe von Konsumenten kann mehrere separate Instanzen haben<\/li>\n<\/ul>\n<p>\nDies ist ein nicht triviales \u00abviele zu viele\u00bb-Problem. Um zu verstehen, wie Kafka mit den Beziehungen zwischen Gruppen von Konsumenten, Instanzen von Konsumenten und Partitionen umgeht, betrachten wir eine Reihe von zunehmend komplexeren Lese-Szenarien.<\/p>\n<h3>Konsumenten und Gruppen von Konsumenten<\/h3>\n<p>\nLassen Sie uns als Ausgangspunkt ein Thema mit einer Partition nehmen (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/6z\/tz\/dh\/6ztzdhqmjweck-z15htxb2xbe28.png\">Abbildung 3-2<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Verst\u00e4ndnis von Nachrichtenbrokern. Untersuchung der Mechanik des Nachrichtenaustauschs \u00fcber ActiveMQ und Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/46c92e6bd38774dfef3be4bd198bf35d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Abbildung 3-2. Konsument liest aus der Partition<\/i><\/p>\n<p>Wenn sich eine Konsumenteninstanz mit ihrer eigenen group_id mit diesem Thema verbindet, wird ihr eine Partition zum Lesen und ein Offset in dieser Partition zugewiesen. Die Position dieses Offsets wird im Client konfiguriert, entweder als Zeiger auf die letzte Position (die neueste Nachricht) oder auf die fr\u00fcheste Position (die \u00e4lteste Nachricht). Der Konsument fordert (polls) Nachrichten aus dem Thema an, was zu deren sequenzieller Lesung aus dem Log f\u00fchrt.<br \/>\nDie Position des Offsets wird regelm\u00e4\u00dfig in Kafka zur\u00fcckcommitted und als Nachrichten im internen Thema gespeichert <i>_consumer_offsets<\/i>. Gelesene Nachrichten werden jedoch nicht gel\u00f6scht, im Gegensatz zu einem herk\u00f6mmlichen Broker, und der Client kann das Offset zur\u00fcckspulen, um bereits gesehene Nachrichten erneut zu verarbeiten.<\/p>\n<p>Wenn ein zweiter logischer Konsument mit einer anderen group_id verbunden wird, verwaltet er einen zweiten Zeiger, der unabh\u00e4ngig von dem ersten ist (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/qe\/v1\/yk\/qev1yktga3s-g1gqlynylbe3n9w.png\">Abbildung 3-3<\/a><\/noindex>). Somit fungiert das Kafka-Thema wie eine Warteschlange, in der es einen Konsumenten gibt, und wie ein \u00fcbliches Publisher-Subscriber-Thema (pub-sub), auf das mehrere Konsumenten abonniert sind, mit dem zus\u00e4tzlichen Vorteil, dass alle Nachrichten gespeichert werden und mehrmals verarbeitet werden k\u00f6nnen.<\/p>\n<p><img decoding=\"async\" alt=\"Verst\u00e4ndnis von Nachrichtenbrokern. Untersuchung der Mechanik des Nachrichtenaustauschs \u00fcber ActiveMQ und Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/e9e8b9063ef7367005254d36abb47f4f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Abbildung 3-3. Zwei Konsumenten in verschiedenen Gruppen von Konsumenten lesen aus einer Partition<\/i><\/p>\n<h3>Konsumenten in der Gruppe von Konsumenten<\/h3>\n<p>\nWenn ein Verbraucher-Exemplar Daten aus einer Partition liest, kontrolliert es den Zeiger vollst\u00e4ndig und verarbeitet die Nachrichten, wie im vorherigen Abschnitt beschrieben.<br \/>\nWenn mehrere Verbraucher-Exemplare mit derselben group_id an ein Thema mit einer Partition angeschlossen sind, wird das zuletzt angeschlossene Exemplar die Kontrolle \u00fcber den Zeiger \u00fcbernehmen und von diesem Zeitpunkt an alle Nachrichten erhalten (<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/0j\/ao\/f2\/0jaof2mdwg3cqvmwemhtxkrltuq.png\">Abbildung 3-4<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Verst\u00e4ndnis von Nachrichtenbrokern. Untersuchung der Mechanik des Nachrichtenaustauschs \u00fcber ActiveMQ und Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/ec6af819445dad4028f65449a735ae22.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Abbildung 3-4. Zwei Verbraucher in derselben Verbrauchergruppe lesen aus einer Partition<\/i><\/p>\n<p>Dieser Verarbeitungsmodus, in dem die Anzahl der Verbraucher-Exemplare die Anzahl der Partitionen \u00fcbersteigt, kann als eine Art monopolartiger Verbraucher betrachtet werden. Dies kann n\u00fctzlich sein, wenn Sie eine \"aktiv-passive\" (oder \"hei\u00dfe-warme\") Clusterung Ihrer Verbraucher-Exemplare ben\u00f6tigen, obwohl der parallele Betrieb mehrerer Verbraucher (\"aktiv-aktiv\" oder \"hei\u00dfe-hei\u00dfe\") viel typischer ist als Verbraucher im Wartemodus.<\/p>\n<blockquote><p>Dieses oben beschriebene Verhalten bei der Nachrichtenverteilung kann im Vergleich zu einer normalen JMS-Warteschlange \u00fcberraschend sein. In diesem Modell werden die in die Warteschlange gesendeten Nachrichten gleichm\u00e4\u00dfig auf zwei Verbraucher verteilt.<\/p><\/blockquote>\n<p>\nH\u00e4ufig schaffen wir mehrere Verbraucher-Exemplare, entweder zur parallelen Verarbeitung von Nachrichten, zur Erh\u00f6hung der Lesegeschwindigkeit oder zur Verbesserung der Robustheit des Leseprozesses. Da immer nur ein Verbraucher-Exemplar gleichzeitig Daten aus einer Partition lesen kann, wie wird dies in Kafka erreicht?<\/p>\n<p>Eine M\u00f6glichkeit, dies zu tun, besteht darin, ein Verbraucher-Exemplar zu verwenden, um alle Nachrichten zu lesen und sie an einen Thread-Pool weiterzugeben. Obwohl dieser Ansatz die Verarbeitungsbandbreite erh\u00f6ht, steigert er die Komplexit\u00e4t der Verbraucherlogik und tut nichts zur Verbesserung der Robustheit des Lesevorgangs. Wenn ein Verbraucher-Exemplar aufgrund eines Stromausfalls oder eines \u00e4hnlichen Ereignisses ausf\u00e4llt, wird die Lesung gestoppt.<\/p>\n<p>Der kanonische Weg, dieses Problem in Kafka zu l\u00f6sen, besteht darin, mehr Partitionen zu verwenden.<i>O<\/i>Partitionierung<\/p>\n<h3>Partitionierung<\/h3>\n<p>\nPartitionen sind das Hauptmechanismus zur Parallelisierung des Lesens und zur Skalierung eines Themas \u00fcber die Kapazit\u00e4t einer einzelnen Brokerinstanz hinaus. Um das besser zu verstehen, betrachten wir ein Szenario, in dem es ein Thema mit zwei Partitionen gibt und ein Consumer dieses Thema abonniert.<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/en\/9g\/ct\/en9gct0o017cqp8buawguwlscty.png\">Abbildung 3-5<\/a><\/noindex>).<\/p>\n<p><img decoding=\"async\" alt=\"Verst\u00e4ndnis von Nachrichtenbrokern. Untersuchung der Mechanik des Nachrichtenaustauschs \u00fcber ActiveMQ und Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/cc766bf69af22698aacc3f1ac70b067f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Abbildung 3-5. Ein Consumer liest von mehreren Partitionen<\/i><\/p>\n<p>In diesem Szenario hat der Consumer die Kontrolle \u00fcber die Zeiger, die seiner group_id in beiden Partitionen entsprechen, und beginnt, Nachrichten aus beiden Partitionen zu lesen.<br \/>\nWenn ein zus\u00e4tzlicher Consumer f\u00fcr dasselbe group_id zu diesem Thema hinzugef\u00fcgt wird, weist Kafka eine der Partitionen vom ersten auf den zweiten Consumer neu zu. Danach wird jeder Consumer-Instanz aus einer Partition des Themas lesen.<noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/8b\/a0\/um\/8ba0umn2yzr9yy3vztonhdfiub0.png\">Abbildung 3-6<\/a><\/noindex>).<\/p>\n<p>Um die Verarbeitung von Nachrichten parallel in 20 Threads zu gew\u00e4hrleisten, ben\u00f6tigen Sie mindestens 20 Partitionen. Wenn es weniger Partitionen gibt, bleiben Consumers \u00fcbrig, die nichts zu tun haben, wie bereits zuvor in der Diskussion \u00fcber monopolartige Consumers beschrieben.<\/p>\n<p><img decoding=\"async\" alt=\"Verst\u00e4ndnis von Nachrichtenbrokern. Untersuchung der Mechanik des Nachrichtenaustauschs \u00fcber ActiveMQ und Kafka. Kapitel 3. Kafka\" src=\"\/wp-content\/uploads\/2019\/09\/a3c4001e4a5b92d53b6f529b2633254a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Abbildung 3-6. Zwei Consumers in derselben Consumer-Gruppe lesen aus verschiedenen Partitionen<\/i><\/p>\n<p>Dieses Schema verringert erheblich die Komplexit\u00e4t der Arbeit des Kafka-Brokers im Vergleich zur Verteilung von Nachrichten, die zur Unterst\u00fctzung einer JMS-Warteschlange erforderlich ist. Hier m\u00fcssen Sie sich nicht um folgende Punkte k\u00fcmmern:<\/p>\n<ul>\n<li>Welcher Consumer die n\u00e4chste Nachricht basierend auf einer zirkul\u00e4ren (Round-Robin) Verteilung, dem aktuellen Pufferplatz oder vorherigen Nachrichten (wie bei JMS-Nachrichtengruppen) erhalten soll.<\/li>\n<li>Welche Nachrichten an welche Consumers gesendet wurden und ob sie im Falle eines Fehlers erneut zugestellt werden m\u00fcssen.<\/li>\n<\/ul>\n<p>\nAlles, was der Kafka-Broker tun muss, ist, die Nachrichten dem Consumer nacheinander zu \u00fcbergeben, wenn dieser sie anfordert.<\/p>\n<p>Die Anforderungen an die Parallelisierung des Lesens und das erneute Senden fehlerhafter Nachrichten entfallen jedoch nicht - die Verantwortung daf\u00fcr geht einfach vom Broker auf den Client \u00fcber. Das bedeutet, dass diese Aspekte in Ihrem Code ber\u00fccksichtigt werden m\u00fcssen.<\/p>\n<h2>Nachrichten senden<\/h2>\n<p>\nDie Verantwortung f\u00fcr die Entscheidung, in welche Partition eine Nachricht gesendet werden soll, liegt beim Producer dieser Nachricht. Um den Mechanismus zu verstehen, mit dem dies geschieht, m\u00fcssen wir zun\u00e4chst betrachten, was genau wir tats\u00e4chlich senden.<\/p>\n<p>W\u00e4hrend wir in JMS eine Nachrichtenstruktur mit Metadaten (Kopfzeilen und Eigenschaften) und einem K\u00f6rper, der die Nutzlast (payload) enth\u00e4lt, verwenden, ist eine Nachricht in Kafka <i>ein Paar \"Schl\u00fcssel-Wert\"<\/i>. Der Nachrichten-Nutzlast wird als Wert (value) gesendet. Der Schl\u00fcssel hingegen wird haupts\u00e4chlich f\u00fcr die Partitionierung verwendet und sollte <i>einen gesch\u00e4ftsspezifischen Schl\u00fcssel<\/i>, enthalten, um verwandte Nachrichten in derselben Partition unterzubringen.<\/p>\n<p>In Kapitel 2 haben wir das Szenario von Online-Wetten besprochen, in dem verwandte Ereignisse in der Reihenfolge von einem Konsumenten verarbeitet werden m\u00fcssen:<\/p>\n<ol>\n<li>Das Benutzerkonto ist eingerichtet.<\/li>\n<li>Geld wird auf das Konto \u00fcberwiesen.<\/li>\n<li>Eine Wette wird platziert, die Geld vom Konto abzieht.<\/li>\n<\/ol>\n<p>\nWenn jedes Ereignis eine Nachricht darstellt, die an ein Thema gesendet wird, dann w\u00e4re in diesem Fall die nat\u00fcrliche Wahl des Schl\u00fcssels die Kontowendung.<br \/>\nWenn eine Nachricht mit der Kafka Producer API gesendet wird, wird sie an die Partitionierungsfunktion weitergeleitet, die unter Ber\u00fccksichtigung der Nachricht und des aktuellen Zustands des Kafka-Clusters die Partitions-ID zur\u00fcckgibt, an die die Nachricht gesendet werden soll. Diese Funktion wird in Java \u00fcber das Partitioner-Interface implementiert.<\/p>\n<p>Dieses Interface sieht folgenderma\u00dfen aus:<\/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>\nDie Implementierung des Partitioner zur Bestimmung der Partition verwendet standardm\u00e4\u00dfig einen Hash-Algorithmus f\u00fcr den Schl\u00fcssel (allgemeiner Hashing-Algorithmus \u00fcber den Schl\u00fcssel) oder Round-Robin, wenn kein Schl\u00fcssel angegeben ist. Dieser Standardwert funktioniert in den meisten F\u00e4llen gut. Sie werden jedoch in Zukunft vielleicht Ihre eigene Strategie schreiben wollen.<\/p>\n<h3>Schreiben einer eigenen Partitionierungsstrategie<\/h3>\n<p>\nLassen Sie uns ein Beispiel betrachten, wenn Sie Metadaten zusammen mit der Nutzlast der Nachricht senden m\u00f6chten. In unserem Beispiel besteht die Nutzlast aus einer Anweisung zur Einzahlung auf das Spielkonto. Die Anweisung ist das, was wir garantieren m\u00f6chten, dass es bei der \u00dcbertragung nicht modifiziert wird, und wir m\u00f6chten sicherstellen, dass nur ein vertrauensw\u00fcrdiges \u00fcbergeordnetes System diese Anweisung initiieren kann. In diesem Fall einigen sich die sendenden und empfangenden Systeme auf die Verwendung einer Signatur zur Authentifizierung der Nachricht.<br \/>\nIn einem normalen JMS definieren wir einfach die Eigenschaft \u201eNachrichtensignatur\u201c und f\u00fcgen sie der Nachricht hinzu. Kafka bietet uns jedoch keinen Mechanismus zur \u00dcbertragung von Metadaten \u2014 nur Schl\u00fcssel und Wert.<\/p>\n<p>Da der Wert die Nutzlast der Bank\u00fcberweisung (bank transfer payload) ist, deren Integrit\u00e4t wir wahren m\u00f6chten, bleibt uns keine andere Wahl, als eine Datenstruktur zu definieren, die im Schl\u00fcssel verwendet wird. Angenommen, wir ben\u00f6tigen eine Kontoinformation zur Partitionierung, da alle Nachrichten, die sich auf das Konto beziehen, in der richtigen Reihenfolge verarbeitet werden m\u00fcssen, dann werden wir die folgende JSON-Struktur entwerfen:<\/p>\n<pre><code class=\"json\">{\n  \"signature\": \"541661622185851c248b41bf0cea7ad0\",\n  \"accountId\": \"10007865234\"\n}<\/code><\/pre>\n<p>\nDa der Wert der Signatur je nach Nutzlast variieren wird, wird die Standard-Hash-Strategie des Partitioner-Interfaces nicht zuverl\u00e4ssig verwandte Nachrichten gruppieren. Daher m\u00fcssen wir unsere eigene Strategie schreiben, die diesen Schl\u00fcssel analysiert und den value accountId partitioniert.<\/p>\n<blockquote><p>Kafka enth\u00e4lt Pr\u00fcfziffern zur Erkennung von besch\u00e4digten Nachrichten im Speicher und verf\u00fcgt \u00fcber eine vollst\u00e4ndige Palette von Sicherheitsfunktionen. In diesem Fall k\u00f6nnen jedoch manchmal branchenspezifische Anforderungen auftreten, wie das oben angegebene Beispiel.<\/p><\/blockquote>\n<p>\nDie benutzerdefinierte Partitionierungsstrategie muss sicherstellen, dass alle verwandten Nachrichten in einer Partition landen. Obwohl dies einfach erscheint, kann das Erfordernis durch die Wichtigkeit der Reihenfolge verwandter Nachrichten und die Festigkeit der Anzahl der Partitionen im Thema kompliziert werden.<\/p>\n<p>Die Anzahl der Partitionen in einem Thema kann sich im Laufe der Zeit \u00e4ndern, da sie hinzugef\u00fcgt werden k\u00f6nnen, wenn der Datenverkehr die urspr\u00fcnglichen Erwartungen \u00fcbersteigt. Somit k\u00f6nnen die Nachrichtenschl\u00fcssel mit der Partition verbunden sein, in die sie urspr\u00fcnglich gesendet wurden, was einen Teil des Zustands impliziert, der zwischen den Instanzen des Produzenten verteilt werden muss.<\/p>\n<p>Ein weiterer Faktor, den es zu ber\u00fccksichtigen gilt, ist die Gleichm\u00e4\u00dfigkeit der Verteilung von Nachrichten zwischen den Partitionen. In der Regel werden Schl\u00fcssel nicht gleichm\u00e4\u00dfig auf die Nachrichten verteilt, und Hashfunktionen garantieren keine faire Verteilung von Nachrichten bei einer kleinen Anzahl von Schl\u00fcsseln.<br \/>\nEs ist wichtig zu beachten, dass, egal wie Sie die Nachrichten aufteilen, der Separator m\u00f6glicherweise wiederverwendet werden muss.<\/p>\n<p>Betrachten wir die Anforderung zur Replikation von Daten zwischen Kafka-Clustern an unterschiedlichen geografischen Standorten. Zu diesem Zweck wird Kafka mit einem Kommandozeilenwerkzeug namens MirrorMaker geliefert, das verwendet wird, um Nachrichten aus einem Cluster zu lesen und sie in ein anderes zu \u00fcbertragen.<\/p>\n<p>MirrorMaker muss die Schl\u00fcssel des replizierten Themas verstehen, um die relative Reihenfolge der Nachrichten bei der Replikation zwischen Clustern aufrechtzuerhalten, da die Anzahl der Partitionen f\u00fcr dieses Thema in den beiden Clustern unterschiedlich sein kann.<\/p>\n<p>Benutzerdefinierte Partitionierungsstrategien kommen relativ selten vor, da das Standard-Hashing oder die zyklische Verteilung in den meisten Szenarien erfolgreich funktioniert. Wenn Sie jedoch strenge Garantien f\u00fcr die Sortierung ben\u00f6tigen oder Metadaten aus den Payloads extrahieren m\u00fcssen, sollten Sie sich etwas genauer mit der Partitionierung befassen.<\/p>\n<p>Die Vorteile der Skalierbarkeit und Performance von Kafka ergeben sich daraus, dass einige der Aufgaben eines traditionellen Brokers auf den Client \u00fcbertragen werden. In diesem Fall wird entschieden, dass potenziell verwandte Nachrichten auf mehrere parallel arbeitende Consumer verteilt werden.<\/p>\n<blockquote><p>Auch JMS-Broker m\u00fcssen mit solchen Anforderungen umgehen. Interessanterweise erfordert der Mechanismus zur Sendung verwandter Nachrichten an denselben Consumer, der \u00fcber JMS Message Groups (eine Art Sticky Load Balancing-Strategie) realisiert wird, dass der Sender die Nachrichten als verkn\u00fcpft kennzeichnet. Im Fall von JMS ist der Broker daf\u00fcr verantwortlich, diese Gruppe verbundener Nachrichten an einen von vielen Consumern zu senden und die Eigentumsrechte an der Gruppe zu \u00fcbertragen, falls der Consumer ausf\u00e4llt.<\/p><\/blockquote>\n<p><\/p>\n<h2>Vereinbarungen mit dem Producer<\/h2>\n<p>\nDie Partitionierung ist nicht das einzige, was beim Senden von Nachrichten zu ber\u00fccksichtigen ist. Lassen Sie uns die Methoden send() der Klasse Producer im Java-API betrachten:<\/p>\n<pre><code class=\"java\">Future  send(ProducerRecord  record);\nFuture  send(ProducerRecord  record, Callback callback);<\/code><\/pre>\n<p>\nEs sollte sofort darauf hingewiesen werden, dass beide Methoden ein Future zur\u00fcckgeben, was darauf hinweist, dass die Sendebetrieb nicht sofort ausgef\u00fchrt wird. Infolgedessen wird die Nachricht (ProducerRecord) in den Sendepuffer f\u00fcr jede aktive Partition geschrieben und im Hintergrund von einem Thread in der Kafka-Client-Bibliothek an den Broker \u00fcbermittelt. Obwohl dies die Arbeit unglaublich schnell macht, bedeutet es, dass eine unerfahren geschriebene Anwendung Nachrichten verlieren kann, wenn ihr Prozess angehalten wird.<\/p>\n<p>Wie immer gibt es einen Weg, die Sendebetriebs zuverl\u00e4ssiger zu gestalten, ohne die Leistung zu beeintr\u00e4chtigen. Die Gr\u00f6\u00dfe dieses Puffers kann auf 0 gesetzt werden, und der Thread der sendenden Anwendung muss warten, bis die \u00dcbertragung der Nachricht an den Broker abgeschlossen ist, wie folgt:<\/p>\n<pre><code class=\"java\">RecordMetadata metadata = producer.send(record).get();<\/code><\/pre>\n<p><\/p>\n<h2>Noch einmal zum Lesen von Nachrichten<\/h2>\n<p>\nDas Lesen von Nachrichten bringt zus\u00e4tzliche Komplikationen mit sich, \u00fcber die es nachzudenken gilt. Im Gegensatz zur JMS-API, die einen Nachrichtenh\u00f6rer (message listener) in Reaktion auf den Empfang einer Nachricht starten kann, wird das Interface <i>Consumer <\/i>Kafka nur gepollt (polling). Lassen Sie uns die Methode <i>poll ()<\/i>, die f\u00fcr diesen Zweck verwendet wird, n\u00e4her betrachten:<\/p>\n<pre><code class=\"java\">ConsumerRecords  poll(long timeout);<\/code><\/pre>\n<p>\nDer R\u00fcckgabewert der Methode ist eine Containerstruktur, die mehrere Objekte enth\u00e4lt. <i>ConsumerRecord <\/i>aus potenziell mehreren Partitionen. <i>ConsumerRecord <\/i>ist selbst ein Objekt-Holder f\u00fcr ein Schl\u00fcssel-Wert-Paar mit den entsprechenden Metadaten, wie der Partition, aus der es stammt.<\/p>\n<p>Wie in Kapitel 2 diskutiert, m\u00fcssen wir uns st\u00e4ndig bewusst sein, was mit Nachrichten passiert, nachdem sie erfolgreich oder nicht erfolgreich verarbeitet wurden, z. B. wenn der Client eine Nachricht nicht verarbeiten kann oder wenn er abst\u00fcrzt. Bei JMS wurde dies durch den Best\u00e4tigungsmodus (acknowledgement mode) behandelt. Der Broker l\u00f6scht entweder die erfolgreich verarbeiteten Nachrichten oder liefert die unbearbeiteten oder fehlgeschlagenen Nachrichten erneut aus (vorausgesetzt, es wurden Transaktionen verwendet). <br \/>\nKafka funktioniert ganz anders. Nachrichten werden nach dem Auslesen nicht im Broker gel\u00f6scht, und die Verantwortung daf\u00fcr, was bei einem Ausfall passiert, liegt im Code, der ausliest.<\/p>\n<p>Wie bereits erw\u00e4hnt, ist eine Consumer-Gruppe mit dem Offset im Log verkn\u00fcpft. Die Position im Log, die mit diesem Offset verkn\u00fcpft ist, entspricht der n\u00e4chsten Nachricht, die als Antwort ausgegeben wird. <i>poll ()<\/i>. Die entscheidende Bedeutung beim Lesen hat der Zeitpunkt, zu dem diese Verschiebung steigt.<\/p>\n<p>Zur\u00fcck zur zuvor betrachteten Lesemodel, die Verarbeitung der Nachricht besteht aus drei Phasen:<\/p>\n<ol>\n<li>Nachricht zum Lesen abrufen.<\/li>\n<li>Nachricht verarbeiten.<\/li>\n<li>Nachricht best\u00e4tigen.<\/li>\n<\/ol>\n<p>\nDer Kafka-Consumer wird mit einer Konfigurationsoption geliefert <i>enable.auto.commit<\/i>. Dies ist eine h\u00e4ufig verwendete Standardeinstellung, wie es bei Einstellungen mit dem Wort \u201eauto\u201c \u00fcblich ist.<\/p>\n<p>Bis Kafka 0.10 setzte der Client, der diesen Parameter verwendete, den Offset der zuletzt gelesenen Nachricht beim n\u00e4chsten Aufruf <i>poll ()<\/i> nach der Verarbeitung. Das bedeutete, dass alle bereits abgerufenen Nachrichten erneut verarbeitet werden konnten, wenn der Client sie bereits verarbeitet hatte, aber unerwartet beendet wurde, bevor er den Aufruf t\u00e4tigte <i>poll ()<\/i>. Da der Broker keinen Zustand dar\u00fcber speichert, wie oft eine Nachricht gelesen wurde, wird der n\u00e4chste Consumer, der diese Nachricht abruft, nicht wissen, dass etwas Schlechtgelaufen ist. Dieses Verhalten war pseudo-transaktional. Der Offset wurde nur im Falle einer erfolgreichen Verarbeitung der Nachricht best\u00e4tigt, aber wenn der Client abbrach, sendete der Broker dieselbe Nachricht an einen anderen Client zur\u00fcck. Ein solches Verhalten entsprach der Garantie f\u00fcr die Nachrichtenlieferung &#171;<i>mindestens einmal<\/i>&#171;.<\/p>\n<p>In Kafka 0.10 wurde der Client-Code so ge\u00e4ndert, dass das Commit regelm\u00e4\u00dfig von der Client-Bibliothek ausgef\u00fchrt wurde, gem\u00e4\u00df der Einstellung <i>auto.commit.interval.ms<\/i>. Dieses Verhalten liegt irgendwo zwischen den Modi JMS AUTO_ACKNOWLEDGE und DUPS_OK_ACKNOWLEDGE. Bei Verwendung des Auto-Commits konnten Nachrichten unabh\u00e4ngig davon best\u00e4tigt werden, ob sie tats\u00e4chlich verarbeitet wurden \u2013 dies konnte im Falle eines langsamen Consumers geschehen. Wenn der Consumer abbrach, wurden die Nachrichten vom n\u00e4chsten Consumer abgerufen, beginnend mit der best\u00e4tigten Position, was zu einem \u00dcbersehen von Nachrichten f\u00fchren konnte. In diesem Fall verlor Kafka keine Nachrichten, der lesende Code verarbeitete sie einfach nicht.<\/p>\n<p>Dieser Modus hat die gleichen Perspektiven wie in Version 0.9: Nachrichten k\u00f6nnen verarbeitet werden, aber im Falle eines Fehlers k\u00f6nnte der Offset nicht best\u00e4tigt werden, was potenziell zu einer doppelten Lieferung f\u00fchren kann. Je mehr Nachrichten Sie beim Abrufen ziehen <i>poll ()<\/i>, desto gr\u00f6\u00dfer ist dieses Problem.<\/p>\n<p>Wie im Abschnitt \u201eNachrichten aus der Warteschlange lesen\u201c auf Seite 21 diskutiert, gibt es im Nachrichtenaustauschsystem kein Konzept der einmaligen Nachrichtenzustellung, wenn man die Ausfallmodi ber\u00fccksichtigt.<\/p>\n<p>In Kafka gibt es zwei M\u00f6glichkeiten, den Offset zu fixieren (zu committen): automatisch und manuell. In beiden F\u00e4llen k\u00f6nnen Nachrichten mehrmals verarbeitet werden, wenn eine Nachricht verarbeitet wurde, aber ein Fehler vor dem Commit aufgetreten ist. Sie k\u00f6nnen eine Nachricht auch vollst\u00e4ndig ignorieren, wenn das Commit im Hintergrund erfolgt und Ihr Code abgeschlossen ist, bevor er mit der Verarbeitung begonnen hat (m\u00f6glicherweise in Kafka 0.9 und fr\u00fcheren Versionen).<\/p>\n<p>Um den Commit-Prozess des Offsets manuell zu steuern, k\u00f6nnen Sie im Kafka-Consumer-API die Einstellung <i>enable.auto.commit<\/i> auf false setzen und explizit eine der folgenden Methoden aufrufen:<\/p>\n<pre><code class=\"java\">void commitSync();\nvoid commitAsync();<\/code><\/pre>\n<p>\nWenn Sie eine Nachricht \u201emindestens einmal\u201c verarbeiten m\u00f6chten, m\u00fcssen Sie den Offset manuell mit <i>commitSync ()<\/i>, ausf\u00fchren, indem Sie diesen Befehl direkt nach der Verarbeitung der Nachrichten ausf\u00fchren.<\/p>\n<p>Diese Methoden erlauben es nicht, Nachrichten zu best\u00e4tigen (acknowledged), bevor sie verarbeitet werden, jedoch bieten sie nichts zur Behebung einer m\u00f6glichen doppelten Verarbeitung, w\u00e4hrend sie gleichzeitig den Anschein von Transaktionsf\u00e4higkeit erwecken. In Kafka gibt es keine Transaktionen. Der Client hat nicht die M\u00f6glichkeit, Folgendes zu tun:<\/p>\n<ul>\n<li>Eine fehlgeschlagene Nachricht automatisch zur\u00fcckzurollen (roll back). Die Consumer m\u00fcssen selbst mit Ausnahmen umgehen, die durch problematische Payloads und Backend-Ausf\u00e4lle entstehen, da sie nicht auf die erneute Zustellung von Nachrichten durch den Broker vertrauen k\u00f6nnen.<\/li>\n<li>Nachrichten in mehrere Topics im Rahmen einer atomaren Operation zu senden. Wie wir bald sehen werden, kann die Kontrolle \u00fcber verschiedene Topics und Partitionen auf unterschiedlichen Maschinen im Kafka-Cluster liegen, die keine Transaktionen bei der Sendung koordinieren. Zum Zeitpunkt der Erstellung dieses Artikels wurde bereits etwas Arbeit geleistet, um dies mit KIP-98 m\u00f6glich zu machen.<\/li>\n<li>Das Lesen einer Nachricht aus einem Topic mit dem Senden einer anderen Nachricht in ein anderes Topic zu verkn\u00fcpfen. Erneut h\u00e4ngt die Architektur von Kafka von vielen unabh\u00e4ngigen Maschinen ab, die als ein Bus arbeiten, und es werden keine Versuche unternommen, dies zu verbergen. Zum Beispiel gibt es keine API-Komponenten, die es erm\u00f6glichen w\u00fcrden, <i>Consumer <\/i>und <i>Producer <\/i>in der Transaktion. In JMS wird dies durch ein Objekt gew\u00e4hrleistet <i>Sitzung<\/i>, aus dem erstellt wird <i>MessageProducers <\/i>und <i>MessageConsumers<\/i>.<\/li>\n<\/ul>\n<p>\nWenn wir uns nicht auf Transaktionen verlassen k\u00f6nnen, wie k\u00f6nnen wir dann eine Semantik gew\u00e4hrleisten, die n\u00e4her an der liegt, die traditionelle Nachrichten\u00fcbermittlungssysteme bieten?<\/p>\n<p>Wenn die M\u00f6glichkeit besteht, dass sich der Offset des Consumers erh\u00f6ht, bevor die Nachricht verarbeitet wurde, zum Beispiel w\u00e4hrend eines Ausfalls des Consumers, hat der Consumer keine M\u00f6glichkeit zu wissen, ob seine Consumer-Gruppe beim Zuweisen einer Partition Nachrichten verpasst hat. Eine der Strategien besteht daher darin, den Offset auf die vorherige Position zur\u00fcckzusetzen. Die Kafka-Consumer-API bietet die folgenden Methoden daf\u00fcr an:<\/p>\n<pre><code class=\"java\">void seek(TopicPartition partition, long offset);\nvoid seekToBeginning(Collection  partitions);<\/code><\/pre>\n<p>\nMethode <i>seek ()<\/i> kann zusammen mit der Methode verwendet werden <br \/>\n<i>offsetsForTimes (Map timestampsToSearch)<\/i> um auf einen Zustand zu einem bestimmten Zeitpunkt in der Vergangenheit zur\u00fcckzusetzen.<\/p>\n<p>Implizit bedeutet die Verwendung dieses Ansatzes, dass es sehr wahrscheinlich ist, dass einige Nachrichten, die zuvor bearbeitet wurden, erneut gelesen und bearbeitet werden. Um dies zu vermeiden, k\u00f6nnen wir idempotente Lesevorg\u00e4nge verwenden, wie in Kapitel 4 beschrieben, um zuvor gesehene Nachrichten nachzuverfolgen und Duplikate auszuschlie\u00dfen.<\/p>\n<p>Alternativ kann der Code Ihres Consumers einfach sein, wenn der Verlust oder die Duplizierung von Nachrichten akzeptabel ist. Wenn wir die Anwendungsf\u00e4lle betrachten, f\u00fcr die Kafka typischerweise verwendet wird, wie die Verarbeitung von Protokollen, Metriken, Klickverfolgung usw., verstehen wir, dass der Verlust einzelner Nachrichten wahrscheinlich keinen signifikanten Einfluss auf die umgebenden Anwendungen haben wird. In solchen F\u00e4llen sind Standardwerte durchaus akzeptabel. Andererseits, wenn Ihre Anwendung Zahlungen \u00fcbermitteln muss, m\u00fcssen Sie sorgf\u00e4ltig auf jede einzelne Nachricht achten. Alles h\u00e4ngt vom Kontext ab.<\/p>\n<p>Pers\u00f6nliche Beobachtungen zeigen, dass mit der Zunahme der Nachrichtenintensit\u00e4t der Wert jeder einzelnen Nachricht abnimmt. Gro\u00dfe Nachrichtenmengen werden in der Regel als wertvoll betrachtet, wenn sie in aggregierter Form betrachtet werden.<\/p>\n<h2>Hohe Verf\u00fcgbarkeit (High Availability)<\/h2>\n<p>\nDer Ansatz von Kafka in Bezug auf hohe Verf\u00fcgbarkeit unterscheidet sich wesentlich von dem Ansatz von ActiveMQ. Kafka wurde auf der Grundlage horizontal skalierbarer Cluster entwickelt, in denen alle Brokerinstanzen Nachrichten gleichzeitig empfangen und verteilen.<\/p>\n<p>Ein Kafka-Cluster besteht aus mehreren Brokerinstanzen, die auf verschiedenen Servern arbeiten. Kafka wurde f\u00fcr den Betrieb auf normaler, eigenst\u00e4ndiger Hardware entwickelt, bei der jeder Knoten seinen eigenen dedizierten Speicher hat. Die Verwendung von Netzwerkspeichern (SAN) wird nicht empfohlen, da mehrere Rechenknoten um die Zeitintervalle des Speichers konkurrieren und Konflikte erzeugen k\u00f6nnen.<i>\u201e<\/i>Die Zeitintervalle des Speichers und Konflikte erzeugen k\u00f6nnen.<\/p>\n<p>Kafka ist ein <i>st\u00e4ndig aktives<\/i> System. Viele gro\u00dfe Nutzer von Kafka schalten ihre Cluster nie aus, und die Software sorgt st\u00e4ndig f\u00fcr Aktualisierungen durch sequenzielle Neustarts. Dies wird erreicht, indem die Kompatibilit\u00e4t mit der vorherigen Version f\u00fcr Nachrichten und Interaktionen zwischen den Brokern garantiert wird.<\/p>\n<p>Die Broker sind mit dem Servercluster <noindex><a rel=\"nofollow\" href=\"http:\/\/zookeeper.apache.org\">ZooKeeper<\/a><\/noindex>, verbunden, der als Konfigurationsdatenregister fungiert und zur Koordination der Rollen jedes Brokers verwendet wird. ZooKeeper ist selbst ein verteiltes System, das hohe Verf\u00fcgbarkeit durch die Replikation von Informationen gew\u00e4hrleistet, indem es <i>ein Quorum<\/i>.<\/p>\n<p>bildet. Im Basisfall wird ein Topic im Kafka-Cluster mit den folgenden Eigenschaften erstellt:<\/p>\n<ul>\n<li>Anzahl der Partitionen. Wie bereits erw\u00e4hnt, h\u00e4ngt der genaue Wert, der hier verwendet wird, vom gew\u00fcnschten Grad des parallelen Lesens ab.<\/li>\n<li>Der Replikationsfaktor gibt an, wie viele Brokerinstanzen im Cluster die Protokolle f\u00fcr diese Partition enthalten m\u00fcssen.<\/li>\n<\/ul>\n<p>\nDurch die Verwendung von ZooKeepers zur Koordination versucht Kafka, neue Partitionen gerecht zwischen den Brokern im Cluster zu verteilen. Dies geschieht durch eine Instanz, die die Rolle des Controllers \u00fcbernimmt.<\/p>\n<p>Zur Laufzeit <i>wird f\u00fcr jede Topic-Partition<\/i> <i>Controller <\/i>eine Brokerrolle <i>als Leader <\/i>zugewiesen (leader, master, f\u00fchrend) und <i>Follower <\/i>(Follower, Sklaven, Untergebene). Der Broker, der als F\u00fchrer f\u00fcr diese Partition fungiert, ist verantwortlich f\u00fcr den Empfang aller Nachrichten, die von Produzenten an ihn gesendet werden, und f\u00fcr die Verbreitung der Nachrichten an die Konsumenten. Beim Senden von Nachrichten an die Partition des Themas werden sie auf alle Broker-Knoten repliziert, die als Nachfolger f\u00fcr diese Partition fungieren. Jeder Knoten, der Protokolle f\u00fcr die Partition enth\u00e4lt, wird genannt <i>Replik<\/i>. Der Broker kann f\u00fcr einige Partitionen als F\u00fchrer und f\u00fcr andere als Nachfolger fungieren.<\/p>\n<p>Der Nachfolger, der alle Nachrichten enth\u00e4lt, die beim F\u00fchrer gespeichert sind, wird genannt <i>synchronisierte Replik<\/i> (Replik, die sich im synchronisierten Zustand befindet, in-sync replica). Wenn der Broker, der als F\u00fchrer f\u00fcr die Partition fungiert, ausf\u00e4llt, kann jeder Broker, der sich im aktualisierten oder synchronisierten Zustand f\u00fcr diese Partition befindet, die Rolle des F\u00fchrers \u00fcbernehmen. Dies ist ein unglaublich robuster Entwurf.<\/p>\n<p>Ein Teil der Konfiguration des Produzenten ist der Parameter <i>acks<\/i>, der bestimmt, wie viele Replikate den Erhalt der Nachricht best\u00e4tigen (acknowledge) m\u00fcssen, bevor der Anwendungsstrom mit dem Senden fortf\u00e4hrt: 0, 1 oder alle. Wenn ein Wert von <i>all<\/i>festgelegt ist, sendet der F\u00fchrer beim Empfang der Nachricht eine Best\u00e4tigung (confirmation) zur\u00fcck an den Produzenten, sobald er mehrere Best\u00e4tigungen (acknowledgements) von Replikaten (einschlie\u00dflich sich selbst) erhalten hat, die in der Themenkonfiguration festgelegt sind. <i>min.insync.replicas<\/i> (standardm\u00e4\u00dfig 1). Wenn die Nachricht nicht erfolgreich repliziert werden kann, l\u00f6st der Produzent eine Ausnahme f\u00fcr die Anwendung aus (<i>NotEnoughReplicas<\/i> oder <i>NotEnoughReplicasAfterAppend<\/i>).<\/p>\n<p>In einer typischen Konfiguration wird ein Thema mit einem Replikationsfaktor von 3 (1 F\u00fchrer, 2 Nachfolger f\u00fcr jede Partition) erstellt und der Parameter <i>min.insync.replicas<\/i> auf 2 gesetzt. In diesem Fall wird der Cluster es erlauben, dass einer der Broker, die die Partition des Themas verwalten, ausfallen kann, ohne dass dies Auswirkungen auf die Client-Anwendungen hat.<\/p>\n<p>Das bringt uns zu dem uns bereits bekannten Kompromiss zwischen Leistung und Zuverl\u00e4ssigkeit. Die Replikation erfolgt durch zus\u00e4tzliche Wartezeit auf Best\u00e4tigungen (acknowledgments) von den Folgesystemen. Da sie jedoch parallel durchgef\u00fchrt wird, hat die Replikation, zumindest auf drei Knoten, dieselbe Leistung wie auf zwei (unter Ignorierung der erh\u00f6hten Netzwerkbandbreitennutzung).<\/p>\n<p>Durch die Verwendung dieses Replikationsschemas meidet Kafka geschickt die Notwendigkeit, jede Nachricht physisch auf der Festplatte durch eine Operation <i>sync()<\/i>aufzuzeichnen. Jede vom Producer gesendete Nachricht wird im Journal der Partition aufgezeichnet, aber wie in Kapitel 2 besprochen, erfolgt die Aufzeichnung in die Datei zun\u00e4chst im Puffer des Betriebssystems. Wenn diese Nachricht auf eine andere Kafka-Instanz repliziert wird und sich im Speicher befindet, bedeutet der Verlust des Leaders nicht, dass die Nachricht selbst verloren gegangen ist \u2013 diese kann von einer synchronen Replik \u00fcbernommen werden.<br \/>\nDer Verzicht auf die Notwendigkeit, die Operation <i>sync()<\/i> auszuf\u00fchren, bedeutet, dass Kafka Nachrichten mit der Geschwindigkeit empfangen kann, mit der sie im Speicher aufgezeichnet werden k\u00f6nnen. Umgekehrt gilt: Je l\u00e4nger das Speichern (Flushing) im Speicher auf die Festplatte vermieden werden kann, desto besser. Aus diesem Grund ist es nicht ungew\u00f6hnlich, Kafka-Brokern 64 GB oder mehr Speicher zuzuweisen. Diese Speichernutzung bedeutet, dass eine Kafka-Instanz Geschwindigkeiten erreichen kann, die viele tausend Mal schneller sind als die eines traditionellen Nachrichtenbrokers.<\/p>\n<p>Kafka kann auch so konfiguriert werden, dass die Operation <i>sync()<\/i> auf Nachrichtengruppen angewendet wird. Da in Kafka alles auf die Arbeit mit Gruppen ausgerichtet ist, funktioniert dies tats\u00e4chlich ziemlich gut f\u00fcr viele Nutzungsszenarien und ist ein n\u00fctzliches Werkzeug f\u00fcr Benutzer, die sehr starke Garantien verlangen. Der Gro\u00dfteil der reinen Leistung von Kafka h\u00e4ngt von Nachrichten ab, die in Gruppen an den Broker gesendet werden und die aus dem Broker in aufeinanderfolgende Bl\u00f6cke gelesen werden. <noindex><a rel=\"nofollow\" href=\"http:\/\/www.linuxjournal.com\/article\/6345\">zero-copy<\/a><\/noindex> Operationen (bei denen keine Aufgabe zum Kopieren von Daten aus einem Speicherbereich in einen anderen ausgef\u00fchrt wird). Dies stellt einen gro\u00dfen Vorteil in Bezug auf Leistung und Ressourcen dar und ist nur durch die Verwendung der zugrunde liegenden Protokolldatenstruktur m\u00f6glich, die das Partitionsschema definiert.<\/p>\n<p>In einem Kafka-Cluster ist eine deutlich h\u00f6here Leistung m\u00f6glich als bei der Verwendung eines einzelnen Kafka-Brokers, da die Topic-Partitionen horizontal auf vielen separaten Maschinen skaliert werden k\u00f6nnen.<\/p>\n<h2>Ergebnisse<\/h2>\n<p>\nIn diesem Kapitel haben wir untersucht, wie die Kafka-Architektur die Beziehungen zwischen Clients und Brokern neu definiert, um einen unglaublich robusten Messaging-Pipeline zu bieten, mit einer viel h\u00f6heren Durchsatzrate als bei einem herk\u00f6mmlichen Nachrichtenbroker. Wir haben die Funktionen besprochen, die sie nutzt, um dieses Ziel zu erreichen, und einen kurzen \u00dcberblick \u00fcber die Anwendungsarchitektur gegeben, die diese Funktionalit\u00e4t gew\u00e4hrleistet. Im n\u00e4chsten Kapitel werden wir die h\u00e4ufigen Probleme betrachten, mit denen Messaging-basierte Anwendungen konfrontiert sind, und Strategien zu ihrer L\u00f6sung er\u00f6rtern. Wir schlie\u00dfen das Kapitel ab, indem wir skizzieren, wie man \u00fcber Messaging-Technologien insgesamt nachdenken kann, damit Sie ihre Eignung f\u00fcr Ihre Anwendungsf\u00e4lle bewerten k\u00f6nnen.<\/p>\n<p>Der vorherige \u00fcbersetzte Abschnitt: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/466385\/\">Verstehen von Nachrichtenbrokern. Mechanismen der Nachrichten\u00fcbertragung durch ActiveMQ und Kafka. Kapitel 1<\/a><\/noindex><\/p>\n<p><b> \u00dcbersetzung von: <noindex><a rel=\"nofollow\" href=\"http:\/\/tele.gg\/middle_java\">tele.gg\/middle_java<\/a><\/noindex><\/b><\/p>\n<p><i>Fortsetzung folgt\u2026<\/i><\/p>\n<p class=\"for_users_only_msg\">Nur registrierte Benutzer k\u00f6nnen an der Umfrage teilnehmen. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Bitte einloggen<\/a><\/noindex>.<\/p>\n<h2 class=\"default-block__polling-title\">Wird Kafka in Ihrer Organisation verwendet?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Ja<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Nein<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Wurde fr\u00fcher verwendet, jetzt nicht mehr<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Geplant zu verwenden<\/p>\n<\/li>\n<\/ul>\n<p>    38 Nutzer haben abgestimmt. 8 Nutzer haben sich enthalten.<br \/>\n<br \/>Quelle: <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\/de\/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=\"de_DE\" \/>\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\/de\/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\udd47Verstehen von Nachrichtendienstleistern. Untersuchung der Mechanik des Nachrichtenaustauschs mit ActiveMQ und Kafka. Kapitel 3. Kafka | ProHoster","description":"Fortsetzung der \u00dcbersetzung eines kleinen Buches: \u201eUnderstanding Message Brokers\u201c, Autor: Jakub Korab, Verlag: O'Reilly Media, Inc., Erscheinungsdatum: Juni 2017, ISBN: 9781492049296. Die vorherige \u00dcbersetzung.","canonical_url":"https:\/\/prohoster.info\/de\/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":"de_DE","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\/de\/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\/de\/wp-json\/wp\/v2\/posts\/38172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=38172"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/38172\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=38172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=38172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=38172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}