Ligar ao Kafka a correr na área de acoplagem a partir da máquina local

configurei uma implementação básica de Kafka com o acoplador na minha máquina local, tal como está descrito em a documentação Confluente do Kafka (Passos 2-3).

Além disso, também expus o porto 2181 e o porto 9092 do Kafka para poder ligar-me a eles a partir de um cliente java que funciona numa 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: quando tento ligar-me ao kafka a partir da máquina anfitriã, a ligação falha porque não consegue resolver o endereço: kafka: 9092.

Aqui está o meu código 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();

a excepção:

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

pergunta: como se ligar ao kafka a correr na Docker a partir da máquina hospedeira?

Nota: eu sei que eu poderia teoricamente brincar com a configuração do DNS e {[[3]} mas é uma solução-não deveria ser assim.

também há uma questão semelhante aqui, no entanto, é baseada em ches/kafka imagem. Eu uso uma imagem baseada em confluent que não é a mesma.

Author: Kling Klang, 2018-08-01

2 answers

Disclaimer: as seguintes utilizações confluentinc imagens de acoplador, não wurstmeister/kafa, embora exista uma configuração semelhante , Eu não a tentei. Também esta linha no acoplador compõe .

Aquele documento Confluente de arranque rápido assume que todos os pedidos de produção e consumo estarão dentro da rede Docker.

Você poderia corrigir o problema executando o seu código do cliente Kafka dentro do seu próprio container, mas caso contrário você terá que adicionar algumas mais variáveis de ambiente para expor o contêiner externamente, enquanto ainda tê-lo trabalhar dentro da rede Docker.

Primeiro adicione um mapeamento de Protocolo de {[2] } que irá mapear o protocolo ouvinte a um protocolo Kafka

-e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT

Em seguida, configurar dois ouvintes anunciados em diferentes portos. ({[4] } aqui refere-se ao nome do contentor do estivador). Repare que os protocolos correspondem aos valores do lado direito dos mapeamentos acima

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

Ao executar o contentor, adicionar -p 29092:29092 para o mapeamento da porta anfitriã

Ao executar qualquer cliente do Kafka fora da rede do acoplador, use localhost:29092

Ao executar uma aplicação na rede de acopladores , use kafka:9092

Veja o ficheiro de exemplo compor para a pilha de confluentes completa

 1
Author: cricket_007, 2018-09-21 16:50:16

Quando se ligar pela primeira vez a um nó do kafka, ele irá devolver-lhe todo o nó do kafka e o url onde se ligar. Em seguida, sua aplicação vai tentar se conectar a cada kafka diretamente.

A questão é sempre o que é que o kafka lhe dará como url ? É por isso que existe o {[[0]} que será usado por kafka para dizer ao mundo como ele pode ser acessado.

Agora, para o seu caso de uso, há várias pequenas coisas em que pensar: Digamos que estás pronto. plaintext://kafka:9092
  • isto não faz mal se tiver uma aplicação na composição do seu acoplador que use o kafka. Esta aplicação irá obter do kafka o URL com kafka que é resolúvel através da rede de acopladores.
  • se tentar ligar-se a partir do seu sistema principal ou de outro contentor que não esteja na mesma rede de acopladores, isto irá falhar, dado que o nome kafka não pode ser resolvido.

= = > para corrigir isso, você precisa ter um servidor DNS específico como um serviço de descoberta um, mas é grandes problemas para coisas pequenas. Ou você configura manualmente o nome kafka para o IP do contentor em cada /etc/hosts

Se marcar plaintext://localhost:9092

  • isto ficará bem no seu sistema se tiver um mapeamento de portas ( -p 9092:9092 ao lançar o kafka)
  • Isto irá falhar se testar a partir de uma aplicação num contentor (a mesma rede de acopladores ou não) (o localhost é o contentor em si e não o Kafka one) {[[21]}

= = > Se você tem isso e deseja usar um cliente kafka em outro container, um a maneira de corrigir isso é compartilhar a rede para ambos os container (mesmo ip)

Última opção : Definir um IP no nome: plaintext://x.y.z.a:9092

Isto vai ficar bem para todos... Mas como podes arranjar um nome para o X. Y. Z. ?

A única maneira é codificar este ip quando se lança o contentor: docker run .... --net confluent --ip 10.x.y.z .... Note que você precisa adaptar o ip a um ip válido na sub-rede confluent.

 2
Author: wargre, 2018-08-01 12:05:51