如何先启动Zookeeper,再启动Kafka?

How to start Zookeeper and then Kafka?

我开始使用 Confluent Platform,它需要 运行 Zookeeper (zookeeper-server-start /etc/kafka/zookeeper.properties),然后是 Kafka (kafka-server-start /etc/kafka/server.properties)。我正在编写一个应该 运行 Kafka 和 Zookeeper 的 Upstart 脚本。问题是 Kafka 应该阻塞直到 Zookeeper 准备好(因为它依赖于它)但是我找不到可靠的方法来知道 Zookeeper 何时准备好。以下是 运行 启动 Zookeeper 服务器后的一些伪代码尝试:

  1. 使用硬编码块

    sleep 5   
    

    在较慢的计算机上无法可靠地工作and/or等待的时间比需要的时间长。

  2. 检查什么时候(希望是 Zookeeper)运行正在端口 2181

    wait until $(echo stat | nc localhost ${port}) is not none
    

    这似乎没有用,因为它等待 Zookeeper 接受 Kafka 连接的时间不够长。

  3. 查看日志

     wait until specific string in zookeeper log is found
    

    这是粗略的,甚至没有一个字符串也不能在错误中找到(例如 "binding to port [...]")。

有没有可靠的方法知道 Zookeeper 何时准备好接受 Kafka 连接?否则,我将不得不求助于 1 和 2 的组合。

您评论中的 Kafka 错误消息绝对相关:

FATAL [Kafka Server 0], Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server.KafkaServer) java.lang.RuntimeException: A broker is already registered on the path /brokers/ids/0. This probably indicates that you either have configured a brokerid that is already in use, or else you have shutdown this broker and restarted it faster than the zookeeper timeout so it appears to be re-registering.

这表明 ZooKeeper 已启动并且 运行,并且 Kafka 能够连接到它。正如我所料,技术 #2 足以验证 ZooKeeper 是否已准备好接受连接。

相反,问题似乎出在 Kafka 方面。它已经注册了一个 ZooKeeper ephemeral node 来代表起始的 Kafka 代理。当客户端的 ZooKeeper 会话过期时(例如,进程终止因此它停止向 ZooKeeper 发送心跳),临时节点将被自动删除。但是,这是基于超时。如果 Kafka broker 快速重启,那么在重启后,它会看到代表该 broker 的 znode 已经存在。对于新进程启动,这看起来已经有一个代理启动并在该路径上注册。由于经纪人应具有唯一 ID,因此它会中止。

在 ZooKeeper 会话过期后等待一段时间是对此问题的适当响应。如有必要,您可以调整会话过期以更快地发生,如 ZooKeeper Administrator's Guide 中所述。 (请参阅 tickTimeminSessionTimeoutmaxSessionTimeout 的讨论。)但是,将会话过期时间调得太快可能会导致客户端在正常操作期间遇到虚假的会话过期时间。

我对Kafka的了解比较少,但也许在Kafka这边也可以做点什么。我知道像 Apache Ambari 这样的一些管理工具会采取措施保证在配置时为每个代理分配一个唯一的 ID。

我发现使用计时器并不可靠。第二个选项(等待端口)对我有用:

bin/zookeeper-server-start.sh -daemon config/zookeeper.properties && \
while ! nc -z localhost 2181; do sleep 0.1; done && \
bin/kafka-server-start.sh -daemon config/server.properties