Публикация сообщения для Kafka, работающего внутри докера

Я запускаю Kafka внутри док-контейнера. Я запускаю свой контейнер, используя следующую команду

docker run --rm -p 2181:2181 -p 9092:9092 -p 8081:8081 --env 
ADVERTISED_HOST=\`docker-machine ip \\`docker-machine active\\`` --env 
ADVERTISED_PORT=9092 -v  
/Users/abhishek.srivastava/MyProjects/KafkaTest/target/scala-2.11:/app 
-it --  name kafka spotify/kafka bash

Я написал простую программу, которую я могу скопировать внутри контейнера и выполнить ее, и она отлично работает.

object KafkaProducerString {

  def SendStringMessage(msg: String) : Unit = {
    val inputRecord = new ProducerRecord[String, String]("test", null, msg)
    val producer: KafkaProducer[String, String] = CreateProducerString
    val rm = producer.send(inputRecord).get(10, SECONDS)
    println(s"offset: ${rm.offset()} partition: ${rm.partition()} topic: ${rm.topic()}")
    producer.close()
  }

  private def CreateProducerString: KafkaProducer[String, String] = {
    val props = new Properties()
    props.put("bootstrap.servers", "localhost:9092")
    props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer")
    props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer")
    props.put("batch.size", "0")
    props.put("client.id", "1")
    val producer = new KafkaProducer[String, String](props)
    producer
  }
}

Но если я запускаю эту же программу из-за пределов контейнера (с моего Mac). [Я заменяю "localhost" выводом из docker-machine ip]

я получаю эту ошибку

[error] (run-main-0) java.util.concurrent.TimeoutException: Timeout after waiting for 10000 ms.
java.util.concurrent.TimeoutException: Timeout after waiting for 10000 ms.
    at org.apache.kafka.clients.producer.internals.FutureRecordMetadata.get(FutureRecordMetadata.java:50)
    at org.apache.kafka.clients.producer.internals.FutureRecordMetadata.get(FutureRecordMetadata.java:25)
    at com.abhi.KafkaProducerString$.SendStringMessage(KafkaProducerString.scala:23)
    at com.abhi.KafkaMain$$anonfun$main$1.apply$mcVI$sp(KafkaMain.scala:19)
    at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
    at com.abhi.KafkaMain$.main(KafkaMain.scala:17)
    at com.abhi.KafkaMain.main(KafkaMain.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)

Насколько я понимаю, для удаленного производителя kafka мне нужно открыть только порты 2181 (zookeeper) и 9092 (kafka), и вы можете видеть, что я их открыл.

Но все же та же программа при выполнении вне контейнера истекает, но работает внутри контейнера (с локальным хостом).

Изменить:: Основываясь на приведенных ниже предложениях, я попробовал следующее

docker run --rm -p 127.0.0.1:2181:2181 -p 127.0.0.1:9092:9092 -p 
127.0.0.1:8081:8081 --env ADVERTISED_HOST=`docker-machine ip \`docker-machine 
active\`` --env ADVERTISED_PORT=9092 -v 
/Users/abhishek.srivastava/MyProjects/KafkaTest/target/scala-2.11:/app -it --
name kafka kafka_9.0 bash

и

docker run --rm -p 0.0.0.0:2181:2181 -p 0.0.0.0:9092:9092 -p 0.0.0.0:8081:8081 
--env ADVERTISED_HOST=`docker-machine ip \`docker-machine active\`` --env 
ADVERTISED_PORT=9092 -v 
/Users/abhishek.srivastava/MyProjects/KafkaTest/target/scala-2.11:/app -it --
name kafka kafka_9.0 bash

Но это не решило проблему. Я получаю точно такую ​​​​же проблему


person Knows Not Much    schedule 18.05.2016    source источник
comment
Привет, я также столкнулся с той же проблемой. ты разобрался?   -  person maverick    schedule 31.01.2017
comment
Я сдался :) попробую еще раз, когда у меня будет время. проверьте решение ниже. дайте мне знать, если это работает :)   -  person Knows Not Much    schedule 31.01.2017
comment
Я использую докер wurstmeister kafka. Все работает внутри докера, но мой код для производителя/потребителя, который находится на хост-компьютере, не может подключиться к брокеру kafka. Я исправляю это, если что-то случится, я дам вам знать   -  person maverick    schedule 31.01.2017
comment
Даже я сталкиваюсь с той же проблемой. Пожалуйста, обновите, если вы нашли какое-либо решение для этого. Или если какой-либо альтернативный подход, который сработал для вас.   -  person sutanu dalui    schedule 28.07.2017


Ответы (2)


Вам нужно будет привязать свой док-контейнер к локальной машине. Это можно сделать, используя docker run as:

docker run --rm -p 127.0.0.1:2181:2181 -p 127.0.0.1:9092:9092 -p 127.0.0.1:8081:8081 ....

В качестве альтернативы вы можете использовать запуск докера с привязкой IP:

docker run --rm -p 0.0.0.0:2181:2181 -p 0.0.0.0:9092:9092 -p 0.0.0.0:8081:8081 .....

Если вы хотите, чтобы Docker-контейнер был маршрутизируемым в вашей сети, вы можете использовать:

docker run --rm -p <private-IP>:2181:2181 -p <private-IP>:9092:9092 -p <private-IP>:8081:8081 ....

Или, наконец, вы можете отказаться от контейнеризации своего сетевого интерфейса, используя:

docker run --rm -p 2181:2181 -p 9092:9092 -p 8081:8081 --net host ....
person t6nand    schedule 18.05.2016
comment
Я попробовал первые два, и они не решили мою проблему. - person Knows Not Much; 19.05.2016
comment
Вы указали соответствующие порты в своем Dockerfile? - person t6nand; 19.05.2016
comment
вот файл докера github.com/spotify/docker-kafka/blob /master/kafka/Dockerfile - person Knows Not Much; 19.05.2016
comment
Вам нужно будет открыть порт 8081, который вы пытаетесь связать в первую очередь. Также проверьте, запущен ли контейнер Docker с помощью docker ps. И убедитесь, что если контейнер Docker запущен, вы можете подключиться по telnet к вашему хосту через открытые порты, которые вы привязали к хост-компьютеру. - person t6nand; 19.05.2016
comment
пробовал... та же проблема. Интересно, можете ли вы загрузить мой проект с github, а затем попытаться запустить его (из внешнего контейнера докеров) github.com/abhitechdojo/KafkaTest - person Knows Not Much; 20.05.2016

Хотя я сам сталкиваюсь с подобной проблемой, я могу попытаться объяснить это поведение.

Производитель Kafka будет искать лидера раздела в Zookeeper, прежде чем опубликовать запись в теме. Zookeeper будет иметь запись хоста-лидера, отмеченную сервером Kafka, который работает внутри контейнера Docker.

В связи с этим IP-адрес, отмеченный сервером, будет внутренним IP-адресом Docker, а не IP-адресом хоста. Что, конечно, не будет разрешено с клиентской машины и, следовательно, истечет время ожидания.

Вероятным решением может быть установка advertised.host.name на IP-адрес хоста машины Docker. Однако это создаст еще одну проблему (с которой я столкнулся!)

Извлечение метаданных брокера сервером теперь начнет давать сбой. Это связано с тем, что теперь запись Zookeeper имеет IP-адрес хоста, который невозможно разрешить изнутри контейнера. Как следствие, любое пользовательское приложение теперь будет получать LEADER_NOT_AVAILABLE предупреждений.

Это тупиковая ситуация, и решение в основном зависит от используемой стратегии разрешения узла. Я хотел бы знать, как люди предложили бы пойти о здесь.

Редактировать: наконец, мы использовали хост-сеть [--net=host] и использовали статический IP-адрес узла, чтобы обойти проблему.

person sutanu dalui    schedule 28.07.2017
comment
Вы, вероятно, указали на проблему, с которой я столкнулся - person Khanh Hua; 02.10.2018