代码之家  ›  专栏  ›  技术社区  ›  Sasha Shpota A-Bag

从本地计算机连接到Docker中运行的Kafka

  •  3
  • Sasha Shpota A-Bag  · 技术社区  · 6 年前

    我在本地计算机上使用docker设置单节点基本Kafka部署,如中所述 the Confluent Kafka documentation (步骤2-3)。

    此外,我还公开了zookeeper的端口2181和kafka的端口9092,以便能够从运行在本地计算机上的java客户端连接到它们:

    $ 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
    

    问题: 当我试图从主机连接到kafka时,连接失败,因为它无法解析地址:kafka:9092。

    这是我的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();
    

    例外情况:

    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
    

    问题: 如何从主机连接到Docker中运行的kafka?

    注意:我知道理论上我可以玩DNS设置和 /etc/hosts 但这是一个解决办法-不应该是那样的。

    还有类似的问题 here ,但是它基于 ches/kafka 形象。我用 confluent 基于不同的图像。

    2 回复  |  直到 6 年前
        1
  •  11
  •   OneCricketeer Gabriele Mariotti    5 年前

    免责声明 : 以下用途 confluentinc docker图像 ,不是 wurstmeister/kafka ,尽管 there is a similar configuration ,我没有试过。如果用那个图像, read their Connectivity wiki .

    debezium/kafka 上面的文档 are mentioned here .

    我试过 bitnami 卡夫卡的照片 these settings

    一天结束的时候, 都是阿帕奇·卡夫卡 在容器中运行。你只是依赖 如何配置 .

    有关补充阅读和网络图,请参阅 this blog by @rmoff

    合并的快速启动文档假设所有的生产和消费请求都在Docker网络中。

    您可以通过在自己的容器中运行Kafka客户机代码来解决这个问题,但是如果不这样做,您需要添加更多的环境变量,以便在外部公开容器,同时让它在Docker网络中工作。

    首先添加 PLAINTEXT_HOST:PLAINTEXT 将侦听器协议映射到卡夫卡协议

    -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT

    然后在不同端口上设置两个播发的侦听器。( kafka:9092 这里指的是docker容器名)。注意,协议与上面映射的右边值匹配

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

    运行容器时,添加 -p 29092:29092 对于主机端口映射

    tl;博士 (使用上述设置)

    运行任何Kafka客户端时 外部 Docker网络(包括您可能在本地安装的CLI工具)使用 localhost:29092 对于引导服务器和 localhost:2181 动物园管理员

    运行应用程序时 在Docker网络中 ,使用 卡夫卡:9092 对于引导服务器和 zookeeper:2181 动物园管理员

    See the example Compose file for the full Confluent stack

        2
  •  4
  •   wargre    6 年前

    当您第一次连接到kafka节点时,它将返回所有kafka节点和连接的url。然后您的应用程序将尝试直接连接到每个卡夫卡。

    问题总是卡夫卡会给你什么网址?这就是为什么 KAFKA_ADVERTISED_LISTENERS 它将被卡夫卡用来告诉世界如何访问它。

    现在,对于您的用例,有许多小问题需要考虑:

    假设你准备好了 plaintext://kafka:9092

    • 如果你的docker撰写中有一个使用kafka的应用程序,这是可以的。此应用程序将从kafka获取 kafka 这可以通过docker网络解决。
    • 如果您尝试从主系统或不在同一docker网络中的另一个容器连接,这将失败,因为 卡夫卡 无法解析名称。

    ==>要解决此问题,您需要有一个特定的DNS服务器,如服务发现服务器,但对于小的东西来说,这是个大麻烦。或者手动设置 卡夫卡 每个中容器ip的名称 /etc/hosts

    如果你设置 plaintext://localhost:9092

    • 如果您有端口映射(启动kafka时为-p 9092:9092),这在您的系统上是可以的
    • 如果从容器上的应用程序进行测试(是否与docker网络相同)(localhost是容器本身,而不是kafka网络),则此操作将失败

    ==>如果您有此功能并希望在另一个容器中使用kafka客户端,解决此问题的一种方法是共享两个容器的网络(相同的ip)

    最后一个选项:在名称中设置IP: plaintext://x.y.z.a:9092

    这对每个人都没关系。。。但是你怎么知道x.y.z.a的名字?

    唯一的方法是在启动容器时硬编码此ip: docker run .... --net confluent --ip 10.x.y.z ... . 注意,您需要将ip调整为 confluent 子网。

    推荐文章