kafka集群搭建

网络上的博客质量参差不齐,对新手很不友好,我参考了一些博客文档后,重新写了一遍kafka的搭建教程,包括zookeeper的搭建教程,还附上了遇到的一些常见错误的解决方案。
我使用了3台虚拟机,因为kafka需要zookeeper的支持,所以虚拟机上需要事先搭建好zookeeper的集群,具体步骤见 《搭建zookeeper集群》。主要参考了这两个教程: 教程一(三台虚拟机)教程二(两台虚拟机)

1. 软件环境

  1. CenOS7 虚拟机三台。
  2. 已经搭建好的zookeeper集群。
  3. 软件版本:kafka_2.11-1.0.0

2. 创建目录并下载安装软件

1.创建目录

cd /opt mkdir kafka #创建项目目录
cd kafka mkdir kafkalogs #创建kafka消息目录,主要存放kafka消息

  1. 下载软件
    我用的是xshell工具将下载好的软件传送到虚拟机的,放在了/opt/kafka/目录下,并解压:

tar -zxvf kafka_2.11-1.0.0.tgz

3. 修改配置文件

3.1 进入到config目录

cd /opt/kafka/kafka_2.11-1.0.0/config/

我们主要关心的文件只有一个:server.properties,我们可以发现在这个目录下有很多文件,还有zookeeper的文件。我们可以直接使用kafka自带的zookeeper集群来启动,但是考虑到未来的项目需求,建议使用独立的zookeeper集群。

-rw-r--r--. 1 root root 906 Oct 27 08:56 connect-console-sink.properties
-rw-r--r--. 1 root root 909 Oct 27 08:56 connect-console-source.properties
-rw-r--r--. 1 root root 5807 Oct 27 08:56 connect-distributed.properties
-rw-r--r--. 1 root root 883 Oct 27 08:56 connect-file-sink.properties
-rw-r--r--. 1 root root 881 Oct 27 08:56 connect-file-source.properties
-rw-r--r--. 1 root root 1111 Oct 27 08:56 connect-log4j.properties
-rw-r--r--. 1 root root 2730 Oct 27 08:56 connect-standalone.properties
-rw-r--r--. 1 root root 1221 Oct 27 08:56 consumer.properties
-rw-r--r--. 1 root root 4727 Oct 27 08:56 log4j.properties
-rw-r--r--. 1 root root 1919 Oct 27 08:56 producer.properties
-rw-r--r--. 1 root root 7030 Nov 22 18:10 server.properties
-rw-r--r--. 1 root root 1032 Oct 27 08:56 tools-log4j.properties
-rw-r--r--. 1 root root 1023 Oct 27 08:56 zookeeper.properties

3.2 修改配置文件server.properties

需要说明的是,我现在是在虚拟机1上进行的操作,同样的操作要在三台虚拟机上都执行,只是有些细微的配置不同,其他配置信息完全相同。对于不同虚拟机上有差异的部分,我会一一指出。下面修改配置文件:

// 打开配置文件
vim server.properties // 修改配置文件
broker.id=1 /* 这是这台虚拟机上的值,在另外两台虚拟机上应该是2或者3,这个值是唯一的,每台虚拟机或者叫服务器不能相同。 /
/
设置本机IP和端口。 我这里设置的是listeners,也可以直接设置host.name=192.168.172.10,port=19292,这个IP地址也是与本机相关的,每台服务器上设置为自己的IP地址。 /
listeners=PLAINTEXT://192.168.172.10:19092 // 该端口默认是9092,我为了加深理解,没有设置为默认值。
// 在og.retention.hours=168下面新增下面三项
message.max.byte=5242880
default.replication.factor=2
replica.fetch.max.bytes=5242880
/ 设置zookeeper的连接端口,新版本的kafka不再使用zookeeper而是通过brokerlist的配置让producer直接连接broker,这个brokerlist可以配置多个,只要有一个能连接上,就可以让producer获取道集群中的其他broker的信息,绕过了zookeeper。因此这个zookeeper.connect可以设置多个值 */
zookeeper.connect=192.168.172.12:12181,192.168.172.11:12181,192.168.172.10:12181

也就是说,zookeeper.connect 指的是zookeeper集群的地址,可以是多个,多个之间用逗号分割
配置文件的详细信息见参考链接

4. 启动kafka集群并测试

4.1 启动服务

首先要启动kafka集群,并且是三台都要手动去启动。

// 进入kafka的bin目录
cd /opt/kafka/kafka_2.11-1.0.0/bin/ // 启动kafka
./kafka-server-start.sh -daemon ../config/server.properties

-daemon代表着以后台模式运行kafka集群,这样kafka的启动就不会影响我们继续在控制台输入命令。

4.2 检查服务是否启动

执行命令jps,显示出了正在运行Kafka这个进程,进程号是4855。在运行这个命令时,你可能会出现错误,显示jps command not found。文章的最后给出了解决方案。

jps 4161 QuorumPeerMain
4855 Kafka
6809 Jps

4.3 创建topic来验证是否创建成功

  1. 创建topic

./kafka-topics.sh --create --zookeeper 192.168.172.10:12181 --replication-factor 2 --partitions 1 --topic my-topic

参数解释:

--replication-factor 2 // 复制两份
--partitions 1 // 创建1个分区
--topic // 主题为my-topic
-- --zookeeper // 此处为为zookeeper监听的地址

  1. 创建生产者producer

./kafka-console-producer.sh --broker-list 192.168.172.10:19092 --topic my-topic //`这个IP地址可以写brokerlist中的任意一个

此时,console处于阻塞状态,可以直接输入数据。

  1. 创建消费者
    此时要切换到另一台虚拟机的shell界面输入以下命令:

./kafka-console-consumer.sh --zookeeper 192.168.172.10:12181 --topic my-topic --from-beginning

此时,一旦有数据生成,此处的console中就会显示数据。

5. 遇到的问题

5.1 端口输入错误

[root@localhost bin]# ./kafka-topics.sh --create --zookeeper 192.168.172.10 --replication-factor 2 --partitions 1 --topic my-topic
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
[2017-11-22 17:45:59,726] WARN Session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect (org.apache.zookeeper.ClientCnxn) java.net.ConnectException: Connection refused
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)

at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:361)  
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1141)

这是因为在输入创建topic命令时,端口输入错误了,./kafka-topics.sh --create --zookeeper 192.168.172.10 --replication-factor 2 --partitions 1 --topic my-topic。这里边只输入了IP地址192.168.172.10,没有输入端口号:12181。这个IP地址+端口号是在/opt/kafka/kafka_2.11-1.0.0/config/server.properties文件中的zookeeper.connect=192.168.172.12:12181,192.168.172.11:12181,192.168.172.10:12181设置的任意一个地址即可。
参考链接: 主参考辅助参考,还有一个参考

5.2 topic名字写错

[root@localhost bin]# ./kafka-console-producer.sh --broker-list 192.168.172.10:19092--topic
shuaige
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Missing required argument "[topic]"

这个问题是因为我的topic名字写错了。我是照着这两个教程搭建kafka集群的:Kafka【第一篇】Kafka集群搭建kafka集群环境搭建。第二篇几乎是抄的第一篇。由于这两个文档的topic名字不一样,我在虚拟机1上创建的topic名字是用的教程一的my-topic,创建生产者时用的却是教程二的shuaige,所以才报错。可见kafka的生产者和消费者是通过topic进行连接的,而不是kafka的IP地址。
PS:教程一Kafka【第一篇】Kafka集群搭建是目前为止看到的写的最好的kafka集群搭建的教程,其他博客都有错误,无法复现。

5.3 启动console消费者后界面卡住不动

创建consumer后不能消费生产者的消息,卡住了

[root@localhost bin]# ./kafka-console-consumer.sh --zookeeper 192.168.172.10:12181 --topic my-topic --from-beginning
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Using the ConsoleConsumer with old consumer is deprecated and will be removed in a future major release. Consider using the new consumer by passing [bootstrap-server] instead of [zookeeper].
// 卡在了上边这句话不动 了

其中下面这段提示不用管它。跟JVM有关系,是一些openJDK默认的设置,具体我也没懂。感兴趣这里有解释:参考1参考2

OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N

产生错误的原因是我在虚拟机1启动生产者的时候用的命令:./kafka-console-producer.sh --broker-list 192.168.172.10:12181 --topic my-topic,注意这里我写的端口号是12181。当我将生产者启动时的端口参数设为19092,消费者启动时的端口参数设为12181时,就可以成功的进行生产者和消费者的通信。

关于生产者和消费者的端口设置,这个教程里有比较简明的讲解:kafka快速上手
在zookeeper的配置文件zoo.cfg中,zookeeper会开发一个clientPort=12181(这是我自己设置的值)端口给消费者使用,其实也可以给生产者使用,但是在0.8.0版本后,producer不再通过zookeeper连接broker,而是通过brokerlist的配置(在kafka的server.properties文件中,我设置的值为zookeeper.connect=192.168.172.12:12181,192.168.172.11:12181,192.168.172.10:12181)直接和broker连接,只要能和一个broker连接上,就能够获取到集群中其他broker的信息,绕过了zookeeper。

5.4 linux下jps command not found

jps命令可以列出本机所有java进程的pid (jps命令讲解)。我运行jps命令时出现:

-bash: jps: command not found

网上好多例子都是说因为jdk里有jps可执行文件,只是没有放在环境变量里。使用root身份vi /etc/profile,然后在下面加一行export PATH="usr/java/jdk160_05/bin:$PATH"(其中jdk160_05是你的安装目录,依你自己的安装情况所决定),然后source /etc/profile即可解决。
但是对我的CentOS7虚拟机不起作用,我觉得这是当你自己安装jdk后jps命令无法运行时可以这样解决,但是有人试验过,自己安装jdk成功后,一般jps命令就已经好使了。
所以说,一般输入jps后报-bash: jps: command not found的都是Linux自带的jdk,下面以我的CentOS7的解决方法为例。需要安装java-1.X.X-openjdk-devel这个包,他提供了jps这个工具。

[root@localhost lib]# yum list | grep jdk-devel
 java-1.8.0-openjdk-devel.x86_64 1:1.8.0.151-1.b12.el7_4 @updates
 java-1.6.0-openjdk-devel.x86_64 1:1.6.0.41-1.13.13.1.el7_3 base
 java-1.7.0-openjdk-devel.x86_64 1:1.7.0.151-2.6.11.1.el7_4 updates
 java-1.8.0-openjdk-devel.i686 1:1.8.0.151-1.b12.el7_4 updates
 java-1.8.0-openjdk-devel-debug.i686 1:1.8.0.151-1.b12.el7_4 updates
java-1.8.0-openjdk-devel-debug.x86_64 1:1.8.0.151-1.b12.el7_4 updates
 [root@localhost lib]# java -version
 openjdk version "1.8.0_151"
 OpenJDK Runtime Environment (build 1.8.0_151-b12)
 OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
 在这里可以看到我的jdk的版本是"1.8.0_151",所以我安装了java-1.8.0-openjdk-devel-debug.x86_64
 [root@localhost lib]# yum -y install java-1.8.0-openjdk-devel-debug.x86_6

4

安装完毕后,问题解决,jps可以正常运行。