java docker apache-kafka confluent

java - Conéctate a Kafka ejecutando en Docker desde una máquina local



apache-kafka confluent (2)

Configuré el Despliegue de Kafka Básico de Nodo Único utilizando la ventana acoplable en mi máquina local, como se describe en la documentación de Confluente Kafka (pasos 2-3).

Además, también expuse el puerto 2181 del zookeeper y el puerto 9092 de kafka para poder conectarme desde el cliente Java que se ejecuta en la máquina local:

$ 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

Problema: cuando intento conectarme a kafka desde la máquina host, la conexión falla porque no puede resolver la dirección: kafka: 9092.

Aquí está mi código de 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();

La excepción:

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

Pregunta: ¿Cómo conectarse a kafka que se ejecuta en Docker desde la máquina host?

Nota: Sé que en teoría podría jugar con la configuración de DNS y /etc/hosts pero es una solución, no debería ser así.

También hay una pregunta similar here , sin embargo, se basa en la imagen ches/kafka . Uso una imagen basada en confluent que no es lo mismo.


Descargo de responsabilidad : lo siguiente utiliza imágenes de wurstmeister/kafka confluentinc , no wurstmeister/kafka , aunque hay una configuración similar , no la he probado. Si usas esa imagen, lee su wiki de Conectividad .

debezium/kafka documentos de debezium/kafka en él se mencionan aquí .

He intentado las imágenes de bitnami , y tengo que trabajar con esta configuración

Al final del día, todo es lo mismo que Apache Kafka se ejecuta en un contenedor. Sólo dependes de cómo está configurado .

Para leer los diagramas de red y de lectura suplementarios, vea este blog por @rmoff

Ese documento de inicio rápido de Confluent asume que todas las solicitudes de producción y consumo estarán dentro de la red Docker.

Puede solucionar el problema ejecutando su código de cliente Kafka dentro de su propio contenedor, pero de lo contrario deberá agregar algunas más variables de entorno para exponer el contenedor de manera externa, mientras aún funciona en la red Docker.

Primero agregue un mapeo de protocolo de PLAINTEXT_HOST:PLAINTEXT que PLAINTEXT_HOST:PLAINTEXT el protocolo de escucha a un protocolo Kafka

-e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT

Luego, configure dos escuchas anunciados en diferentes puertos. ( kafka:9092 aquí se refiere al nombre del contenedor de la kafka:9092 acoplable). Observe que los protocolos coinciden con los valores del lado derecho de las asignaciones anteriores

-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092

Al ejecutar el contenedor, agregue -p 29092:29092 para la asignación de puertos del host

tl; dr (con los ajustes anteriores)

Cuando ejecute cualquier Cliente Kafka fuera de la red de Docker (incluidas las herramientas de CLI que pueda haber instalado localmente), use localhost:29092 para servidores bootstrap y localhost:2181 para Zookeeper

Cuando ejecute una aplicación en la red Docker , use kafka:9092 para servidores bootstrap y zookeeper:2181 para Zookeeper

Vea el ejemplo del archivo Compose para la pila completa de Confluent


Cuando te conectas por primera vez a un nodo kafka, te devolverá todo el nodo kafka y la url donde conectarte. Entonces su aplicación intentará conectarse a cada kafka directamente.

El problema es siempre ¿qué es el kafka que te dará como url? Es por eso que hay KAFKA_ADVERTISED_LISTENERS que serán utilizados por kafka para decirle al mundo cómo se puede acceder.

Ahora para su caso de uso, hay varias cosas pequeñas en las que pensar:

Digamos que configuras plaintext://kafka:9092

  • Esto está bien si tiene una aplicación en su ventana acoplable que utiliza kafka. Esta aplicación obtendrá de kafka la URL con kafka que se puede resolver a través de la red docker.
  • Si intenta conectarse desde su sistema principal o desde otro contenedor que no está en la misma red de conexión, esto fallará, ya que el nombre kafka no se puede resolver.

==> Para solucionar esto, necesita tener un servidor DNS específico como un descubrimiento de servicio, pero es un gran problema para cosas pequeñas. O establece manualmente el nombre kafka a la ip del contenedor en cada /etc/hosts

Si establece plaintext://localhost:9092

  • Esto estará bien en tu sistema si tienes un mapeo de puertos (-p 9092: 9092 al iniciar kafka)
  • Esto fallará si realiza la prueba desde una aplicación en un contenedor (la misma red docker o no) (localhost es el contenedor en sí, no el kafka)

==> Si tiene esto y desea utilizar un cliente kafka en otro contenedor, una forma de solucionarlo es compartir la red para ambos contenedores (la misma ip)

Última opción: establezca una IP en el nombre: plaintext://xyza:9092

Esto estará bien para todos ... PERO, ¿cómo puede obtener el nombre xyza?

La única forma es codificar esta ip cuando docker run .... --net confluent --ip 10.xyz ... el contenedor: la docker run .... --net confluent --ip 10.xyz ... Tenga en cuenta que necesita adaptar la ip a una ip válida en la subred confluent .