kafka-console-consumer 参数 --zookeeper 不可用 与 The coordinator is not available的问题

本秂侑毒 提交于 2020-02-25 00:42:42

事情起因是这样的。我们环境需要用到kafka,现在都是使用容器化的部署,大佬就找了个github星最多docker-kafka连接给我,建议我用这个来搭建。我们开发环境已经有了zk,所以就让我用kafka连上面的zk。kafka搭起来了,生产者可以生产。但是消费者始终是消费不到消息。使用tcpdump抓包也可以确认,消息已经发送到kafka。但是消费者始终无法消费。猜想是不是那个步骤执行错了。所以就按照https://github.com/wurstmeister/kafka-docker的官方文档一步一步来做。

wurstmeister docker-kafka tutorial:http://wurstmeister.github.io/kafka-docker/

发现里面有一步骤怎么也走不通:

$KAFKA_HOME/bin/kafka-console-consumer.sh --topic=topic --zookeeper=$ZK

本地查看脚本的帮助,也没有这个参数,类似功能的是--bootstrap-server的参数:

D:\Programs\kafka_2.11-2.4.0\bin\windows>kafka-console-consumer.bat --help
This tool helps to read data from Kafka topics and outputs it to standard output
.
Option                                   Description

------                                   -----------

--bootstrap-server <String: server to    REQUIRED: The server(s) to connect to.

  connect to>

--consumer-property <String:             A mechanism to pass user-defined

  consumer_prop>                           properties in the form key=value to

                                           the consumer.

--consumer.config <String: config file>  Consumer config properties file. Note

                                           that [consumer-property] takes

                                           precedence over this config.

--enable-systest-events                  Log lifecycle events of the consumer

                                           in addition to logging consumed

                                           messages. (This is specific for

                                           system tests.)

--formatter <String: class>              The name of a class to use for

                                           formatting kafka messages for

                                           display. (default: kafka.tools.

                                           DefaultMessageFormatter)

--from-beginning                         If the consumer does not already have

                                           an established offset to consume

                                           from, start with the earliest

                                           message present in the log rather

                                           than the latest message.

--group <String: consumer group id>      The consumer group id of the consumer.

--help                                   Print usage information.

--isolation-level <String>               Set to read_committed in order to

                                           filter out transactional messages

                                           which are not committed. Set to

                                           read_uncommittedto read all

                                           messages. (default: read_uncommitted)

--key-deserializer <String:

  deserializer for key>

--max-messages <Integer: num_messages>   The maximum number of messages to

                                           consume before exiting. If not set,

                                           consumption is continual.

--offset <String: consume offset>        The offset id to consume from (a non-

                                           negative number), or 'earliest'

                                           which means from beginning, or

                                           'latest' which means from end

                                           (default: latest)

--partition <Integer: partition>         The partition to consume from.

                                           Consumption starts from the end of

                                           the partition unless '--offset' is

                                           specified.
                                          
--property <String: prop>                The properties to initialize the

                                           message formatter. Default

                                           properties include:
        print.
                                           timestamp=true|false
        print.
                                           key=true|false
        print.
                                           value=true|false
        key.separator=<key.
                                           separator>
        line.separator=<line.
                                           separator>
        key.deserializer=<key.
                                           deserializer>
        value.
                                           deserializer=<value.deserializer>

                                           Users can also pass in customized

                                           properties for their formatter; more

                                           specifically, users can pass in

                                           properties keyed with 'key.

                                           deserializer.' and 'value.

                                           deserializer.' prefixes to configure

                                           their deserializers.

--skip-message-on-error                  If there is an error when processing a

                                           message, skip it instead of halt.

--timeout-ms <Integer: timeout_ms>       If specified, exit if no message is

                                           available for consumption for the

                                           specified interval.

--topic <String: topic>                  The topic id to consume on.

--value-deserializer <String:

  deserializer for values>

--version                                Display Kafka version.

--whitelist <String: whitelist>          Regular expression specifying

                                           whitelist of topics to include for

                                           consumption.

查了官方文档,也没有这个参数,类似功能的是一个--bootstrap-server的参数,在api config 里面是bootstrap.servers

kafka doc

于是很确认地,这个文档应该是写错了,于是给项目提了一个issue,建议他们修正tutorial的错误。

https://github.com/wurstmeister/kafka-docker/issues/564

然后收到一个开发者的回复说:

cricket007: --zookeeper actually is an option. Both will work equally until Zookeper is removed from Kafka

cricket007: That doesn’t mean it’s removed yet.

还附上了添加这个使用--bootstrap-server替代--zookeeper的官方wiki:

KIP-500: Replace ZooKeeper with a Self-Managed Metadata Quorum

大概的意思就是说,过去kafka的partitions(分区)和brokers(经纪人)的元数据存储在zk里面,而且是使用zk来选举那个broker(经纪人)做controller(控制者)。为了解决consumer对zk依赖产生其他的限制,所以就让consumer从broker获取元数据信息了。

于是我大概明白了。好的软件如果要因为更改架构设计而更改接口或者参数,会有一个弃用的过渡期。在这个过渡期一般会兼容过去的接口和参数。在过渡期中旧接口被标记为弃用,新的用户使用会逐渐减少对旧接口的依赖。经过一个过渡期后,在某一个大版本的迭代直接移除旧的接口和功能。

Elasticsearch移除type就是一个很好的例子。

所以我猜测,最新版本consumer接口的zookeeper.connect配置已经配移除了。

于是我查询kafka各个版本的文档,果然证实了自己的想法。

在kafka 0.10.0版本的时候,consumer接口新加了bootstrap.server配置,与此同时zookeeper.connect被标记为弃用(deprecated)。

在kafka 2.1.0版本的时候,consumer接口的zookeeper.connect参数再也找不到了。自然连接的脚本也无法使用这个参数了。

综上所述,如果你使用的是kafka v0.10.0版本以前的kafka,则使用kafka-console-consumer.sh只能够通过--zookeeper参数连接kafka集群。如果你使用的是kafka v0.10.0kafka v2.1.0以前的版本,则可以使用--bootstrap-server--zookeeper两个参数连接kafka集群。如果你使用的是kafka v2.1.0及以上的版本,则只能够通过--bootstrap-server参数连接kafka集群。

与此同时,我一开始遇到的问题,貌似也有头绪。因为我搭建环境的时候zookeeper已经存在的话,可能已经有kafka把元数据信息放在了zookeeper。由于之前连上的版本是kafka v0.10.0之前的版本,所以消费者必须直连zookeeper获取kafka的元数据信息。但是我后面注册到zookeeperkafka broker是基于2.4.0版本的,必须通过broker获取元数据信息。按比较好的设计来说,集群里多个版本的代码启动的服务,应该都降级到集群中最低版本的功能来运行。但是2.4.0的kafka broker已经无法使用低版本的broker controller election(经纪人控制者选举),估计是2.1.0移除的。所以导致消费者一直无法正确与kafka broker建立连接的问题,并且报出 The coordinator is not available的问题。

最终,在服务器另外启了一个干净的zookeeper解决了这个问题。。。当然这是开发环境的解决方案。如果是生产环境,同一个集群最好还是不要混用kafka版本。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!