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.
2 answers
Disclaimer: as seguintes utilizações
confluentinc
imagens de acoplador, nãowurstmeister/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
-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
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
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
.