Heim >Backend-Entwicklung >Golang >Stellen Sie eine Verbindung zu Kafka her, das in Docker ausgeführt wird

Stellen Sie eine Verbindung zu Kafka her, das in Docker ausgeführt wird

PHPz
PHPznach vorne
2024-02-14 23:42:081039Durchsuche

连接到在 Docker 中运行的 Kafka

Im heutigen Bereich der Softwareentwicklung ist die Containerisierungstechnologie zu einer immer beliebter werdenden Bereitstellungsmethode geworden. Als eine der beliebtesten Containerisierungslösungen bietet Docker Entwicklern praktische Methoden zur Isolierung und Bereitstellung von Umgebungen. Für Entwickler, die Kafka als Nachrichtenwarteschlangensystem verwenden, kann die Kombination von Kafka mit Docker die Entwicklung und Bereitstellung flexibler und effizienter machen. In diesem Artikel stellt der PHP-Editor Xigua vor, wie man Kafka in Docker ausführt, damit Sie den Komfort der Containerisierung problemlos nutzen können.

Frageninhalt

Ich habe auf meinem lokalen Computer einen Kafka-Docker-Container mit einem Knoten eingerichtet, wie in der Confluence-Dokumentation beschrieben (Schritte 2-3).

Außerdem habe ich den Port 2181 von zookeeper und den Port 9092 von kafka offengelegt, sodass ich von einem Client, der auf meinem lokalen Computer ausgeführt wird, eine Verbindung zu ihnen herstellen kann:

$ docker run -d \
    -p 2181:2181 \
    --net=confluent \
    --name=zookeeper \
    -e zookeeper_client_port=2181 \
    confluentinc/cp-zookeeper:4.1.0

$ docker run -d \
    --net=confluent \
    --name=kafka \
    -p 9092:9092 \
    -e kafka_zookeeper_connect=zookeeper:2181 \
    -e kafka_advertised_listeners=plaintext://kafka:9092 \
    -e kafka_offsets_topic_replication_factor=1 \
    confluentinc/cp-kafka:4.1.0

Problem: Wenn ich versuche, vom Host aus eine Verbindung zu Kafka herzustellen, schlägt die Verbindung fehl, weil 无法解析地址:kafka:9092.

Das ist mein Java-Code:

properties props = new properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("client.id", "kafkaexampleproducer");
props.put("key.serializer", longserializer.class.getname());
props.put("value.serializer", stringserializer.class.getname());
kafkaproducer<long, string> producer = new kafkaproducer<>(props);
producerrecord<long, string> record = new producerrecord<>("foo", 1l, "test 1");
producer.send(record).get();
producer.flush();

Ausnahmen:

java.io.IOException: Can't resolve address: kafka:9092
    at org.apache.kafka.common.network.Selector.doConnect(Selector.java:235) ~[kafka-clients-2.0.0.jar:na]
    at org.apache.kafka.common.network.Selector.connect(Selector.java:214) ~[kafka-clients-2.0.0.jar:na]
    at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:864) [kafka-clients-2.0.0.jar:na]
    at org.apache.kafka.clients.NetworkClient.ready(NetworkClient.java:265) [kafka-clients-2.0.0.jar:na]
    at org.apache.kafka.clients.producer.internals.Sender.sendProducerData(Sender.java:266) [kafka-clients-2.0.0.jar:na]
    at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:238) [kafka-clients-2.0.0.jar:na]
    at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:176) [kafka-clients-2.0.0.jar:na]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]
Caused by: java.nio.channels.UnresolvedAddressException: null
    at sun.nio.ch.Net.checkAddress(Net.java:101) ~[na:1.8.0_144]
    at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:622) ~[na:1.8.0_144]
    at org.apache.kafka.common.network.Selector.doConnect(Selector.java:233) ~[kafka-clients-2.0.0.jar:na]
    ... 7 common frames omitted

Frage: Wie verbinde ich mich mit Kafka, das im Docker läuft? Mein Code wird vom Host ausgeführt, nicht vom Docker.

Hinweis: Ich weiß, theoretisch könnte ich DNS-Einstellungen ausprobieren und /etc/hosts, aber das ist eine Problemumgehung – so sollte es nicht sein.

Hier gibt es eine ähnliche Frage, aber sie basiert auf dem ches/kafka-Bild. Ich verwende Bilder basierend auf confluenceinc und das ist anders. ches/kafka 图像。我使用基于 confluenceinc 的图像,这是不一样的。

解决方法

tl;dr - 从容器到主机的简单端口转发将不起作用...主机文件(例如 *NIX 系统上的 /etc/hosts

Problemumgehung

advertished.listeners (不是 advertished.host.nameadvertished.port,因为这些已被弃用)。如果您看到诸如 Connection to node -1 (localhost/127.0.0.1:9092)

tl;dr

– Eine einfache Portweiterleitung vom Container zum Host wird bootstrap.servers 一部分列出的服务器实际上是可解析的。例如 ping IP/主机名,使用 netcat 检查端口...如果您的客户端位于容器中,则需要从容器执行此操作,而不是(仅)从主机执行此操作。如果容器没有立即崩溃以访问其 shell,请使用 docker execnicht funktionieren

... Hostdateien (z. B.

auf *NIX-Systemen) sollten nicht geändert werden, um Kafka-Netzwerkprobleme zu beheben, da dies bei dieser Lösung nicht der Fall ist tragbar. docker ps 显示 kafka 容器是从 0.0.0.0 映射的:50c5a3c9bd6141bda139d1e2f6e9d778 -> cd3356af2f6e059e7bd54cd1ababa980 /tcp

1) Mit welcher genauen IP/Hostname + Port möchten Sie eine Verbindung herstellen? Stellen Sie sicher, dass der Wert auf dem Proxy auf

eingestellt ist. Ein Fehler wie confluenceinc docker 镜像来解决所提出的问题,不是 wurstmeister/kafka。如果您设置了 KAFKA_ADVERTISED_HOST_NAME bedeutet, dass Ihr Anwendungscontainer versucht, eine Verbindung zu sich selbst herzustellen. Führen Ihre Anwendungscontainer auch Kafka-Brokerprozesse aus? vielleicht nicht.

2) Stellen Sie sicher, dass . 3) Um zu überprüfen, ob die Ports korrekt auf dem Host zugeordnet sind, wenn Sie den Prozess vom Host statt von einem anderen Container ausführen, stellen Sie sicher, dass beim Versuch, den Client von außerhalb des Docker-Netzwerks auszuführen, übereinstimmen müssen. Keine Portweiterleitung zwischen zwei Containern erforderlich; Link-/Docker-Netzwerk verwenden
Die Antwort unten verwendet das Docker-Image confluenceinc, um das gestellte Problem zu lösen, nicht . Wenn Sie die Variable KAFKA_ADVERTISED_HOST_NAME festlegen, entfernen Sie sie bitte (es handelt sich um eine veraltete Eigenschaft)

Der folgende Abschnitt versucht, alle Details zusammenzufassen, die für die Verwendung anderer Bilder erforderlich sind. Andere häufig verwendete Kafka-Bilder wurstmeister/kafkalaufen alle in Containern

Apache

Kafka

.

Sie verlassen sich nur darauf, wie es konfiguriert ist a>. Und welche Variablen dies verursachen.

bitnami/kafka

Ab Oktober 2023 ist dieser Inhalt nicht mehr in DockerHub vorhanden. Auf jeden Fall wird es nach 2022 nicht mehr aufrechterhalten. wurstmeister Lesen Sie den Readme-Abschnitt zur

Listener-Konfiguration und

lesen Sie auch das Konnektivitäts-Wikidebezium/kafka.

Wenn Sie einen kleinen Behälter wünschen, probieren Sie diese aus. Die Bilder sind viel kleiner als Confluence und besser gepflegt als 🎜. 🎜Informationen zur Listener-Konfiguration finden Sie in der Readme-Datei.🎜 🎜 🎜🎜🎜 Relevante Dokumentation wird 🎜hier🎜hier🎜 erwähnt. 🎜

HINWEIS: Veröffentlichte Host- und Porteinstellungen sind veraltet. Werbung Listeners deckt beides ab. Ähnlich wie der Confluence-Container kann Debezium seine Eigenschaften mithilfe der vorangestellten Proxy-Einstellungen aktualisieren. KAFKA_

Andere

  • ...Ich finde es weniger portierbar als Umgebungsvariablen und empfehle es nichtubuntu/kafka 要求您通过 Docker 映像参数添加 --overrideadvertising.listeners=kafka:9092
  • Veraltet und veraltet. spotify/kafka
  • Großartig für eine All-in-One-Lösung mit Schema-Registrierung, Kafka Connect usw., aber aufgebläht, wenn Sie fast-data-devlensesio/box nur Kafka wollen. Außerdem handelt es sich hierbei um ein Docker-Anti-Pattern zum Ausführen mehrerer Dienste in einem Container
  • Dein eigenes
  • – Warum? Sind diese anderen Dinge unvollständig? Beginnen Sie mit einer Pull-Anfrage, anstatt bei Null anzufangen. Dockerfile
Weitere Informationen,

voll funktionsfähig und Netzwerkdiagramme finden Sie unter docker-composeDieser Blog wurde geschrieben von: @rmoff

Antwort

Die

Confluence Quick Start (Docker)-Dokumentation geht davon aus, dass alle Produktions- und Verbrauchsanforderungen innerhalb des Docker-Netzwerks erfolgen.

Sie können das Problem der Verbindung mit

umgehen, indem Sie den Kafka-Clientcode in einem eigenen Container ausführen (mithilfe einer Docker-Bridge). Andernfalls müssen Sie jedoch weitere Umgebungsvariablen hinzufügen, um den Container nach außen hin verfügbar zu machen, während er noch vorhanden ist innerhalb von Docker Arbeiten im Netzwerk. kafka:9092

Fügen Sie zunächst die Protokollzuordnung von

hinzu, die das Listener-Protokoll dem Kafka-Protokoll zuordnetPLAINTEXT_HOST:PLAINTEXT

Schlüssel:

KAFKA_LISTENER_SECURITY_PROTOCOL_MAP Wert:
PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT

Dann richten Sie zwei angekündigte Listener auf verschiedenen Ports ein. (

hier, also überprüfen Sie noch einmal Ihren Dienst + Hostnamen). kafka 指的是 docker 容器名称;它也可能被命名为 broker

Schlüssel:

KAFKA_ADVERTISED_LISTENERS Wert:
PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092

Bitte beachten Sie, dass das Protokoll hier mit dem Wert links in der Protokollzuordnungseinstellung oben übereinstimmt

Fügen Sie beim Ausführen des Containers einen

-Listener hinzu. -p 29092:29092 进行主机端口映射,并通告 PLAINTEXT_HOST

Also...(

mit den oben genannten Einstellungen)

Wenn

immer noch nicht funktioniert, können Sie ändern wobei beide Optionen mit den Anzeigeneinstellungen und den von Docker weitergeleiteten Ports übereinstimmen KAFKA_LISTENERS 设置为包含 9625b882931466931ca10eb1a60367b3://0.0.0.0:a3b0c87895079be75e30be94102cc20b

Der Client befindet sich auf demselben Computer, nicht in einem Container

Durch die Bekanntgabe des Localhosts und des zugehörigen Ports können Sie wie erwartet eine Verbindung außerhalb des Containers herstellen.

Mit anderen Worten: Wenn Sie einen Kafka-Client (einschließlich CLI-Tools, die Sie möglicherweise lokal installiert haben) außerhalb eines Docker-Netzwerks ausführen, verwenden Sie

als Zookeeper (erfordert Docker-Portweiterleitung) localhost:29092 作为引导服务器,使用 localhost:2181

Client auf einem anderen Computer

Wenn Sie versuchen, eine Verbindung von einem externen Server herzustellen, müssen Sie den externen Hostnamen/die externe IP des Hosts (z. B.

) 192.168.x.y sowie/anstelle von localhost angeben. Das einfache Ankündigen von localhost über die Portweiterleitung funktioniert nicht, da das Kafka-Protokoll weiterhin Ihre konfigurierten Listener ankündigt.

Dieses Setup erfordert Docker-Portweiterleitung

und Router-Portweiterleitung (und Firewall-/Sicherheitsgruppenänderungen), wenn sich Ihr Container nicht im selben lokalen Netzwerk befindet, z. B. wenn Ihr Container in der Cloud ausgeführt wird und Sie von Ihrem lokalen Computer aus mit ihm interagieren möchten.

Client (oder ein anderer Proxy) in einem Container auf demselben Host

Dies ist die am wenigsten fehleranfällige Konfiguration; Sie können den DNS-Dienstnamen direkt verwenden.

Wenn Sie die Anwendung

in einem Docker-Netzwerk ausführen, verwenden Sie (siehe die oben angegebene Listener-Konfiguration PLAINTEXT) als Bootstrap-Server und zookeeper:2181 als Zookeeper wie jede andere Docker-Dienstkommunikation (ohne erforderliche Portweiterleitung) kafka:9092 (请参阅上面广告的 PLAINTEXT 侦听器配置)作为引导服务器,使用 zookeeper:2181

Wenn Sie separate

docker run 命令或 Compose 文件,则需要使用 compose networks 部分或 docker network --create 手动定义共享 network verwenden

Sehen Sie sich die Compose-Beispieldatei für den vollständigen Confluence-Stack an oder für eine einfachere Version für einen einzelnen Broker.

Wenn Sie mehrere Proxys verwenden, müssen diese einen eindeutigen Hostnamen und einen Anzeigen-Listener verwenden. Beispiel ansehen一个>

Verwandte Fragen

Verbinden Sie sich über Docker (ksqlDB) mit Kafka auf dem Host

Anhang

Für alle, die sich für die Bereitstellung von Kubernetes interessieren:

Das obige ist der detaillierte Inhalt vonStellen Sie eine Verbindung zu Kafka her, das in Docker ausgeführt wird. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen