Kafka 快速入门,advertised.host.name 给出 kafka.common.LeaderNotAvailableException

Kafka QuickStart, advertised.host.name gives kafka.common.LeaderNotAvailableException

我能够得到一个简单的单节点 Kafka (kafka_2.11-0.8.2.1) 在一台 linux 机器上本地工作,但是当我尝试 运行远程制作人我遇到了一些令人困惑的错误。

我正在按照 http://kafka.apache.org/documentation.html#quickstart. I stopped the kafka processes and deleted all the zookeeper & karma files in /tmp. I am on a local 10.0.0.0/24 network NAT-ed with an external IP address, so I modified server.properties to tell zookeeper how to broadcast my external address, as per https://medium.com/@thedude_rog/running-kafka-in-a-hybrid-cloud-environment-17a8f3cfc284 上的快速入门指南进行操作:

advertised.host.name=MY.EXTERNAL.IP

然后我运行宁此:

$ bin/zookeeper-server-start.sh config/zookeeper.properties
--> ...
$ export KAFKA_HEAP_OPTS="-Xmx256M -Xms128M" # small test server!
$ bin/kafka-server-start.sh config/server.properties
--> ...

我在远程机器上为我的生产者打开了防火墙,并创建了一个新主题并验证了它:

$ bin/kafka-topics.sh --create --zookeeper MY.EXTERNAL.IP:2181 --replication-factor 1 --partitions 1 --topic test123
--> Created topic "test123".
$ bin/kafka-topics.sh --list --zookeeper MY.EXTERNAL.IP:2181
--> test123

但是,我 运行ning 的制作人远程给我错误:

$ bin/kafka-console-producer.sh --broker-list MY.EXTERNAL.IP:9092 --topic test123
--> [2015-06-16 14:41:19,757] WARN Property topic is not valid (kafka.utils.VerifiableProperties)
My Test Message
--> [2015-06-16 14:42:43,347] WARN Error while fetching metadata [{TopicMetadata for topic test123 -> 

由于主题 [test123] 的 kafka.common.LeaderNotAvailableException}],主题 test123 没有分区元数据:class kafka.common.LeaderNotAvailableException (kafka.producer.BrokerPartitionInfo) --> (重复几次)

(我禁用了整个防火墙以确保这不是问题所在。)

karma-startup 中的标准输出错误重复出现:[2015-06-16 20:42:42,768] INFO Closing socket connection to /MY.EXTERNAL.IP. (kafka.network.Processor)

然后 controller.log 给了我这个,好几次:

java.nio.channels.ClosedChannelException
    at kafka.network.BlockingChannel.send(BlockingChannel.scala:100)
    at kafka.controller.RequestSendThread.liftedTree1(ControllerChannelManager.scala:132)
    at kafka.controller.RequestSendThread.doWork(ControllerChannelManager.scala:131)
    at kafka.utils.ShutdownableThread.run(ShutdownableThread.scala:60)
[2015-06-16 20:44:08,128] INFO [Controller-0-to-broker-0-send-thread], Controller 0 connected to id:0,host:MY.EXTERNAL.IP,port:9092 for sending state change requests (kafka.controller.RequestSendThread)
[2015-06-16 20:44:08,428] WARN [Controller-0-to-broker-0-send-thread], Controller 0 epoch 1 fails to send request Name:LeaderAndIsrRequest;Version:0;Controller:0;ControllerEpoch:1;CorrelationId:7;ClientId:id_0-host_null-port_9092;Leaders:id:0,host:MY.EXTERNAL.IP,port:9092;PartitionState:(test123,0) -> (LeaderAndIsrInfo:(Leader:0,ISR:0,LeaderEpoch:0,ControllerEpoch:1),ReplicationFactor:1),AllReplicas:0) to broker id:0,host:MY.EXTERNAL.IP,port:9092. Reconnecting to broker. (kafka.controller.RequestSendThread)

运行 这似乎表明在 0:

处有一个领导者
$ ./bin/kafka-topics.sh --zookeeper MY.EXTERNAL.IP:2181 --describe --topic test123
--> Topic:test123   PartitionCount:1    ReplicationFactor:1 Configs:
Topic: test123  Partition: 0    Leader: 0   Replicas: 0 Isr: 0

我重新运行了这个测试,我的 server.log 表明在 0:

有一个领导者
...
[2015-06-16 21:58:04,498] INFO 0 successfully elected as leader (kafka.server.ZookeeperLeaderElector)
[2015-06-16 21:58:04,642] INFO Registered broker 0 at path /brokers/ids/0 with address MY.EXTERNAL.IP:9092. (kafka.utils.ZkUtils$)
[2015-06-16 21:58:04,670] INFO [Kafka Server 0], started (kafka.server.KafkaServer)
[2015-06-16 21:58:04,736] INFO New leader is 0 (kafka.server.ZookeeperLeaderElector$LeaderChangeListener)

当我从生产者发送消息时,我在日志中看到这个错误:

[2015-06-16 22:18:24,584] ERROR [KafkaApi-0] error when handling request Name: TopicMetadataRequest; Version: 0; CorrelationId: 7; ClientId: console-producer; Topics: test123 (kafka.server.KafkaApis)
kafka.admin.AdminOperationException: replication factor: 1 larger than available brokers: 0
    at kafka.admin.AdminUtils$.assignReplicasToBrokers(AdminUtils.scala:70)

我认为这意味着由于某种原因找不到经纪人?我很困惑这是什么意思...

在你安装了 Kafka 的机器上,检查它是否启动并运行。错误状态,0 个代理可用,这意味着 Kafka 没有启动并且 运行。

在 linux 机器上,您可以使用 netstat 命令检查服务是否 运行。

netstat -an|grep port_kafka_is_Listening(默认为 9092)

总而言之,解决这个问题的方法是通过 NAT 添加路由,以便机器可以访问自己的外部 IP 地址。

Zookeeper 使用它在 advertised.host.name 中找到的地址来告诉客户在哪里可以找到代理以及与代理本身进行通信。报告的错误并没有说明这一点,而且令人困惑,因为客户端打开 TCP 连接没有问题。

将 advertised.host.name 设置为主机 name,而不是 IP 地址。默认是 return a FQDN 使用 getCanonicalHostName(),但这只是尽力而为,回退到 IP。见 java docs for getCanonicalHostName().

诀窍是让主机名始终解析为正确的 IP。对于小型环境,我通常会在 /etc/hosts 中设置所有主机及其所有内部 IP。这样所有机器都知道如何通过名称通过内部网络相互交谈。事实上,现在也可以通过名称而不是 IP 配置您的 Kafka 客户端。如果管理所有 /etc/hosts 文件是一个负担,那么设置一个内部 DNS 服务器来集中它,但是内部 DNS 应该 return 内部 IP。这些选项中的任何一个都比将 IP 地址分散在各种机器上的各种配置文件中更有效。

一旦一切都通过名称进行通信,剩下的就是使用外部 IP 配置外部 DNS,一切正常。这包括使用服务器 names 而不是 IPs 配置 Kafka 客户端。

从上面得到提示:对于我的单个节点(同时仍在学习),我修改了 server.properties 包含文本 "advertised.host.name" 的文件到 value=127.0.01 .所以最后看起来像这样

advertised.host.name=127.0.0.1

虽然启动生产者它仍然显示警告,但现在它至少可以工作,同时我可以在消费者终端上看到消息完美地发送

对于最新版本的 Kafka(撰写本文时为 0.10.0),您根本不想使用 advertised.host.name。事实上,甚至 [documentation] 也声明 advertised.host.name 已被弃用。此外,Kafka 不仅会将其用作 producers/consumers 的 "advertised" 主机名,还会将其用作 其他代理 的主机名(在多代理环境中)。 ..如果您为经纪人使用不同的(可能是内部的)DNS,这会有点痛苦……而且您真的不想从事向个人添加条目的业务 /etc/hosts经纪人(呃!)

因此,基本上,您会希望代理使用内部名称,但对生产者和消费者使用外部 FQDN 。为此,您将改为更新 advertised.listeners

conf/server.属性: host.name 已弃用:仅在未设置 listeners 时使用。请改用 listeners。经纪人的主机名。如果设置了,它将只绑定到这个地址。如果未设置,它将绑定到所有接口