Maison  >  Article  >  développement back-end  >  Connectez-vous à Kafka exécuté dans Docker

Connectez-vous à Kafka exécuté dans Docker

PHPz
PHPzavant
2024-02-14 23:42:08948parcourir

连接到在 Docker 中运行的 Kafka

Dans le domaine actuel du développement logiciel, la technologie de conteneurisation est devenue une méthode de déploiement de plus en plus populaire. En tant que l'une des solutions de conteneurisation les plus populaires, Docker offre aux développeurs des méthodes pratiques d'isolation de l'environnement et de déploiement. Pour les développeurs qui utilisent Kafka comme système de file d'attente de messages, la combinaison de Kafka avec Docker peut rendre le développement et le déploiement plus flexibles et efficaces. Dans cet article, l'éditeur PHP Xigua vous présentera comment exécuter Kafka dans Docker, afin que vous puissiez facilement profiter de la commodité apportée par la conteneurisation.

Contenu de la question

J'ai configuré un conteneur Docker Kafka à nœud unique sur ma machine locale comme décrit dans la documentation Confluence (étapes 2-3).

De plus, j'ai exposé le port 2181 de zookeeper et le port 9092 de kafka afin de pouvoir m'y connecter à partir d'un client exécuté sur ma machine locale :

$ 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

Problème : Lorsque j'essaie de me connecter à kafka depuis l'hôte, la connexion échoue parce que 无法解析地址:kafka:9092.

Voici mon code Java :

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();

Exceptions :

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

Question : Comment se connecter à Kafka exécuté dans Docker ? Mon code s'exécute depuis l'hôte, pas depuis le docker.

Remarque : je sais qu'en théorie, je pourrais essayer les paramètres DNS et /etc/hosts mais c'est une solution de contournement - cela ne devrait pas être comme ça.

Il y a une question similaire ici, mais elle est basée sur l'image ches/kafka. J'utilise des images basées sur confluenceinc et c'est différent. ches/kafka 图像。我使用基于 confluenceinc 的图像,这是不一样的。

解决方法

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

Solution de contournement

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

tl;dr

- Une simple redirection de port du conteneur vers l'hôte ne fonctionnera pasbootstrap.servers 一部分列出的服务器实际上是可解析的。例如 ping IP/主机名,使用 netcat 检查端口...如果您的客户端位于容器中,则需要从容器执行此操作,而不是(仅)从主机执行此操作。如果容器没有立即崩溃以访问其 shell,请使用 docker exec... Les fichiers hôtes (par exemple

sur les systèmes *NIX) ne doivent pas être modifiés pour résoudre les problèmes de réseau Kafka car cette solution n'est pas portable.

docker ps 显示 kafka 容器是从 0.0.0.0 映射的:50c5a3c9bd6141bda139d1e2f6e9d778 -> cd3356af2f6e059e7bd54cd1ababa980 /tcp1) À quelle adresse IP/nom d'hôte + port souhaitez-vous vous connecter ? Assurez-vous que la valeur est définie sur

sur le proxy. Une erreur comme

signifie que votre conteneur d'application essaie de se connecter à lui-même. Vos conteneurs d'applications exécutent-ils également des processus de courtier Kafka ? peut être pas. confluenceinc docker 镜像来解决所提出的问题,不是 wurstmeister/kafka。如果您设置了 KAFKA_ADVERTISED_HOST_NAME

2) Assurez-vous que

. 3) Pour vérifier que les ports sont correctement mappés sur l'hôte si vous exécutez le processus à partir de l'hôte au lieu d'un autre conteneur, assurez-vous que Si vous essayez d'exécuter le client depuis l'extérieur du réseau Docker, les ports doivent correspondre. Aucune redirection de port requise entre deux conteneurs ; utilisez le réseau Link/Docker
La réponse ci-dessous utilise l'image docker confluenceinc pour résoudre le problème posé, pas . Si vous définissez la variable KAFKA_ADVERTISED_HOST_NAME, veuillez la supprimer (c'est une propriété obsolète)

La section suivante tente de résumer tous les détails nécessaires pour utiliser d'autres images. Pour les autres images Kafka couramment utilisées,

sont toutes exécutées dans des conteneurs wurstmeister/kafkaApache

Kafka

.

Vous comptez uniquement sur

comment il est configuré. Et a>quelles variables sont à l'origine de cela.

bitnami/kafka

Depuis octobre 2023, ce contenu n'existe plus dans DockerHub. En tout cas, il ne sera pas maintenu après 2022.

wurstmeisterVoir la section Lisez-moi sur la configuration de l'auditeur, et également

lisez leur wiki Connectivité

. debezium/kafka

Si vous voulez un petit récipient, essayez-les. Les images sont beaucoup plus petites que Confluence et mieux entretenues que

. 🎜Référez-vous à leur fichier Lisez-moi pour la configuration de l'écouteur🎜. 🎜 🎜🎜🎜 La documentation pertinente est mentionnée 🎜ici🎜ici🎜. 🎜

REMARQUE : Les paramètres d'hôte et de port publiés sont obsolètes. La publicité Listeners couvre les deux. Semblable au conteneur Confluence, Debezium peut mettre à jour ses propriétés en utilisant les paramètres de proxy préfixés KAFKA_.

Autres

  • ubuntu/kafka 要求您通过 Docker 映像参数添加 --overrideadvertising.listeners=kafka:9092...Je le trouve moins portable que les variables d'environnement et je ne le recommande pas
  • spotify/kafka Obsolète et obsolète.
  • fast-data-devlensesio/box Idéal pour une solution tout-en-un, avec registre de schémas, Kafka Connect, etc., mais gonflé si vous seulement voulez Kafka. Il s'agit également d'un anti-modèle Docker permettant d'exécuter plusieurs services dans un conteneur
  • Le vôtre Dockerfile - Pourquoi ? Ces autres choses sont-elles incomplètes ? Commencez par une pull request au lieu de repartir de zéro.

Pour des lectures supplémentaires, entièrement fonctionnels docker-compose et des schémas de réseau, veuillez consulter Ce blog est écrit par : @rmoff

Réponse

La

Documentation Confluence Quick Start (Docker) suppose que toutes les demandes de production et de consommation se produiront au sein du réseau Docker.

Vous pouvez contourner le problème de connexion à kafka:9092 en exécutant le code client Kafka dans son propre conteneur (en utilisant un pont Docker), mais sinon vous devrez ajouter plus de variables d'environnement pour exposer le conteneur à l'extérieur tout en le laissant exécuté sous Docker Work dans le réseau.

Ajoutez d'abord le mappage de protocole de PLAINTEXT_HOST:PLAINTEXT qui mappe le protocole d'écoute au protocole Kafka

Clé : KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
Valeur : PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT

Puis configurez deux écouteurs annoncés sur des ports différents. (kafka 指的是 docker 容器名称;它也可能被命名为 broker ici, alors vérifiez votre service + nom d'hôte).

Clé : KAFKA_ADVERTISED_LISTENERS
Valeur : PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092

Veuillez noter que le protocole ici correspond à la valeur à gauche du paramètre de mappage de protocole ci-dessus

Lors de l'exécution du conteneur, ajoutez un -p 29092:29092 进行主机端口映射,并通告 PLAINTEXT_HOST écouteur.

Alors... (en utilisant les paramètres ci-dessus)

Si ne fonctionne toujours pas, vous pouvez modifier l'endroit où les deux options correspondent aux paramètres publicitaires et aux ports transférés Docker KAFKA_LISTENERS 设置为包含 9625b882931466931ca10eb1a60367b3://0.0.0.0:a3b0c87895079be75e30be94102cc20b

Le client est sur la même machine, pas dans un conteneur

La publicité de l'hôte local et du port associé vous permettra de vous connecter en dehors du conteneur, comme vous vous en doutez.

En d'autres termes, lorsque vous exécutez un client Kafka (y compris les outils CLI que vous avez peut-être installés localement) en dehors d'un réseau Docker, utilisez

comme Zookeeper (nécessite la redirection de port Docker) localhost:29092 作为引导服务器,使用 localhost:2181

Client sur une autre machine

Si vous essayez de vous connecter à partir d'un serveur externe, vous devez annoncer le nom d'hôte/l'adresse IP externe de l'hôte (par exemple

) 192.168.x.y ainsi que/au lieu de localhost . La simple publicité de localhost via la redirection de port ne fonctionnera pas car le protocole Kafka continuera à annoncer vos écouteurs configurés.

Cette configuration nécessite la redirection de port Docker

et la redirection de port de routeur (et les modifications du pare-feu/groupe de sécurité) si vous n'êtes pas sur le même réseau local, par exemple votre conteneur s'exécute dans le cloud et vous souhaitez interagir avec lui depuis votre machine locale.

Client (ou autre proxy) dans un conteneur sur le même hôte

Il s'agit de la configuration la moins sujette aux erreurs ; vous pouvez utiliser directement le nom du service DNS.

Lors de l'exécution de l'application

dans un réseau Docker , utilisez (voir la configuration de l'écouteur PLAINTEXT annoncée ci-dessus) comme serveur d'amorçage et zookeeper:2181 comme Zookeeper , juste comme toute autre communication du service Docker (sans aucune redirection de port requise) kafka:9092 (请参阅上面广告的 PLAINTEXT 侦听器配置)作为引导服务器,使用 zookeeper:2181

Si vous utilisez séparément

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

Voir l'exemple de fichier Compose pour la pile Confluence complète ou pour une pile plus simple pour un seul courtier.

Si vous utilisez plusieurs proxys, ils doivent utiliser un nom d'hôte unique + un écouteur publicitaire. Voir l'exemple一个>

Questions connexes

Connectez-vous à Kafka sur l'hôte depuis Docker (ksqlDB)

Annexe

Pour toute personne intéressée par le déploiement de Kubernetes :

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer