这一节我们来真正搭建一个Zookeeper集群。
搭建Zookeeper集群
首先要做的就是再租赁两个服务器,参照搭建单机Kafka章节中的步骤,租赁阿里云服务器、安装JDK、下载配置Kafka、配置安全组规则。
Zookeeper配置信息
在搭建单机Kafka章节中,启动的是单机Zookeeper,所以/root/kafka_2.12-2.0.0/config
目录下的zookeeper.properties
配置文件中只配置了dataDir
,也就是存储各种数据、日志、快照的路径。
在搭建Zookeeper时,就需要额外再配置一些参数了。同样打开/root/kafka_2.12-2.0.0/config
目录下的zookeeper.properties
配置文件,额外添加如下内容:
maxClientCnxns=0 tickTime=2000 initLimit=10 syncLimit=5 quorumListenOnAllIPs=true server.1=zookeeper.server.1:2888:3888 server.2=zookeeper.server.2:2888:3888 server.3=zookeeper.server.3:2888:3888 |
逐一解释一下这些配置信息:
maxClientCnxns
:该参数表示允许客户端最大连接数。如果设置为0则表示不做限制。tickTime
:该参数表示Zookeeper服务之间进行心跳监测的间隔时间,单位是毫秒。设置为2000,表示每隔2秒,Zookeeper服务器之间会进行一次心跳监测。initLimit
:该参数表示Zookeeper集群中的Follower在启动时需要在多少个心跳时间内从Leader同步数据。设置为10,表示要在10个心跳时间内,也就是在20秒内,要完成Leader数据的同步。syncLimit
:该参数表示超过多少个心跳时间收不到Follower的响应,Leader就认为此Follower已经下线。设置为5,表示在5个心跳时间内,也就是判断Follower是否存活的响应时间是10秒。
Zookeeper集群节点列表
首先节点列表的配置规则为server.N=IP:Port1:Port2
:
N
表示Zookeeper节点编号。IP
表示Zookeeper节点的服务器IP,既阿里云ECS的外网IP。Port1
表示该Zookeeper集群中的Follower节点与Leader节点通讯时使用的端口。作为Leader时监听该端口。Port2
表示选举新的Leader时,Zookeeper节点之间互相通信的端口,比如当Leader挂掉时,其余服务器会互相通信,选出新的Leader。Leader和Follower都会监听该端口。
这里的节点编号是数字类型,需要我们在/root/kafka_2.12-2.0.0/data/zookeeper
目录下创建名为myid
的文件,然后将编号配置在里面。server.N
这里的N
要和myid
文件中配置的编号保持一致。
另外还需要注意的是,如果要在一台服务器上搭建伪集群,那么每个Port1
和每个Port2
要不一样才可以,因为IP
都是一样的。这里我们是分别用三台不同的阿里云ECS,所以IP
肯定是不一样的,而每个Port1
是一致的,每个Port2
也是一致的。
为了方便起见,我们可以在服务器的/etc/hosts
文件中设置一下域名映射,比如:
[阿里云ECS-1 IP] zookeeper.server.1 [阿里云ECS-2 IP] zookeeper.server.2 [阿里云ECS-3 IP] zookeeper.server.3 |
这样在配置Zookeeper集群节点列表时就可以写成如下形式了:
server.1=zookeeper.server.1:2888:3888 server.2=zookeeper.server.2:2888:3888 server.3=zookeeper.server.3:2888:3888 |
阿里云ECS服务监听所有网卡
如果现在通过/root/kafka_2.12-2.0.0/bin/zookeeper-server-start.sh config/zookeeper.properties
启动Zookeeper,肯定会报一大堆错误,比如:
[myid:0] - WARN [WorkerSender[myid=0]:QuorumCnxManager@588] - Cannot open channel to 1 at election address /zookeeper.server.1:3888 java.net.ConnectException: Connection refused at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ....... |
这是因为阿里云ECS都是采用虚拟化技术创建的服务器实例,而虚拟机中并没有物理网卡,所以Zookeeper服务启动后,进程并没有监听到3888
端口,而是会随机生成一个端口进行监听。所以会报上面的错。解决的办法就是让Zookeeper服务进程监听0.0.0.0
的IP地址,也就是监听所有网卡。那么就需要在zookeeper.properties
配置文件加入quorumListenOnAllIPs=true
配置信息,来保证Zookeeper服务进程能监听到我们设定的3888
端口。
Zookeeper集群配置总结
在启动Zookeeper集群前,先来总结一下配置工作:
- 租赁三台阿里云ECS,下载JDK、Kafka、配置安全组规则。
- 在
/root/kafka_2.12-2.0.0/data/zookeeper
目录下创建名为myid
的文件,配置Zookeeper节点编号。 - 在服务器的
/etc/hosts
文件中设置一下域名映射:[阿里云ECS-1 IP] zookeeper.server.1 [阿里云ECS-2 IP] zookeeper.server.2 [阿里云ECS-3 IP] zookeeper.server.3
- 在
/root/kafka_2.12-2.0.0/config/zookeeper.properties
配置文件中添加如下配置(server.N
中的N
要和myid
中配置的节点编号保持一致):maxClientCnxns=0 tickTime=2000 initLimit=10 syncLimit=5 quorumListenOnAllIPs=true server.1=zookeeper.server.1:2888:3888 server.2=zookeeper.server.2:2888:3888 server.3=zookeeper.server.3:2888:3888
在三台阿里云ECS中都完成上述工作后,就可以逐一启动Zookeeper了,命令如下:
/root/kafka_2.12-2.0.0/bin/zookeeper-server-start.sh config/zookeeper.properties & |
检验Zookeeper集群
三个Zookeeper节点都启动后,我们可以通过下面两个方法对Zookeeper集群进行基础的验证。
查看端口监听状态
我们可以使用nc
命令看看端口都有没有被成功监听,选择任意一台服务器,通过下面的命令查看:
nc -vz zookeeper.server.1 2181 Connection to zookeeper.server.1 2181 port [tcp/*] succeeded! nc -vz zookeeper.server.1 3888 Connection to zookeeper.server.1 3888 port [tcp/*] succeeded! nc -vz zookeeper.server.1 2888 nc: connect to zookeeper.server.1 port 2888 (tcp) failed: Connection refused nc -vz zookeeper.server.2 2181 Connection to zookeeper.server.2 2181 port [tcp/*] succeeded! nc -vz zookeeper.server.2 3888 Connection to zookeeper.server.2 3888 port [tcp/*] succeeded! nc -vz zookeeper.server.2 2888 nc: connect to zookeeper.server.2 port 2888 (tcp) failed: Connection refused nc -vz zookeeper.server.3 2181 Connection to zookeeper.server.3 2181 port [tcp/*] succeeded! nc -vz zookeeper.server.3 3888 Connection to zookeeper.server.3 3888 port [tcp/*] succeeded! nc -vz zookeeper.server.3 2888 Connection to zookeeper.server.3 2888 port [tcp/*] succeeded! |
从上面的信息中可以看出,三个Zookeeper都成功启动了,并且可以知道zookeeper.server.1
和zookeeper.server.2
是Follower,zookeeper.server.3
是Leader,因为前两个节点并没有监听2888
端口。
通过Zookeeper CLI验证
我们还可以通过Zookeeper Client连接到集群来检验。我们选择任意一台服务器,首先连接zookeeper.server.1
节点:
/root/kafka_2.12-2.0.0/bin/zookeeper-shell.sh zookeeper.server.1:2181 |
连接成功后,我们创建一个zNode:
create /my_zNode "some data" Created /my_zNode |
查看zookeeper.server.1
节点中所有的zNode:
ls / [cluster, brokers, my_zNode, zookeeper, admin, isr_change_notification, log_dir_event_notification, controller_epoch, kafka-manager, consumers, latest_producer_id_block, config] |
我们看到了刚才创建的my_zNode
。然后退出连接,再连接zookeeper.server.2
节点:
/root/kafka_2.12-2.0.0/bin/zookeeper-shell.sh zookeeper.server.2:2181 |
然后查看zookeeper.server.2
节点中的所有zNode:
ls / [cluster, controller_epoch, brokers, my_zNode, zookeeper, kafka-manager, admin, isr_change_notification, consumers, log_dir_event_notification, latest_producer_id_block, config] |
我们同样发现了my_zNode
。查看my_zNode
中的数据:
get /my_zNode some data cZxid = 0x500000009 ctime = Wed Jan 09 15:38:39 CST 2019 mZxid = 0x500000009 mtime = Wed Jan 09 15:38:39 CST 2019 pZxid = 0x500000009 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 9 numChildren = 0 |
看到是在zookeeper.server.1
节点中创建时添加的some data
数据。
同样我们再连接zookeeper.server.3
节点查看zNode情况:
/root/kafka_2.12-2.0.0/bin/zookeeper-shell.sh zookeeper.server.3:2181 ls / [cluster, controller_epoch, brokers, my_zNode, zookeeper, kafka-manager, admin, isr_change_notification, consumers, log_dir_event_notification, latest_producer_id_block, config] get /my_zNode some data cZxid = 0x500000009 ctime = Wed Jan 09 15:38:39 CST 2019 mZxid = 0x500000009 mtime = Wed Jan 09 15:38:39 CST 2019 pZxid = 0x500000009 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 9 numChildren = 0 |
我们在zookeeper.server.3
节点中修改my_zNode
中的数据:
set /my_zNode "new data" get /my_zNode new data cZxid = 0x500000009 ctime = Wed Jan 09 15:38:39 CST 2019 mZxid = 0x50000000e mtime = Wed Jan 09 15:46:29 CST 2019 pZxid = 0x500000009 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 8 numChildren = 0 |
然后再连接zookeeper.server.1
节点查看my_zNode
的数据:
/root/kafka_2.12-2.0.0/bin/zookeeper-shell.sh zookeeper.server.1:2181 get /my_zNode new data cZxid = 0x500000009 ctime = Wed Jan 09 15:38:39 CST 2019 mZxid = 0x50000000e mtime = Wed Jan 09 15:46:29 CST 2019 pZxid = 0x500000009 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 8 numChildren = 0 |
看到zookeeper.server.1
节点中my_zNode
的数据也变成了new data
。
上面的过程虽然比较繁琐,但是充分说明了我们的Zookeeper集群是搭建成功的。无论从哪个Zookeeper节点创建的zNode,都可以同步到集群中的其他节点。无论从哪个Zookeeper节点修改的zNode中的数据,也可以同步到起群中的其他节点。
Zookeeper The Four Letter Words Commands
Zookeeper提供了一些能够查看节点Server状态、Client连接Server的状态、节点健康状态的命令。因为命令大多都是四个字母的简写,所以称为The Four Letter Words Commands,我称为四字真言。
首先来看看整体的命令格式:
echo "xxxx" | nc IP Port |
xxxx
就是四字真言命令。IP
是Zookeeper节点的IP。Port
自然是Zookeeper监听的2181端口。
下面来具体看看这些命令。
查看Zookeeper节点配置
该命令可以查看指定节点的配置信息:
echo "conf" | nc zookeeper.server.1 2181 clientPort=2181 dataDir=/root/kafka_2.12-2.0.0/data/zookeeper/version-2 dataLogDir=/root/kafka_2.12-2.0.0/data/zookeeper/version-2 tickTime=2000 maxClientCnxns=0 minSessionTimeout=4000 maxSessionTimeout=40000 serverId=1 initLimit=10 syncLimit=5 electionAlg=3 electionPort=3888 quorumPort=2888 peerType=0 |
这个命令可以很方便的查看Zookeeper节点zookeeper.properties
中的配置信息,以及默认的配置信息。
查看连接到Zookeeper节点的Client信息
该命令可以查看连接到指定Zookeeper节点的Client信息:
echo "cons" | nc zookeeper.server.1 2181 /[Client IP]:35764[1](queued=0,recved=1,sent=1,sid=0x10000b81b7d0003,lop=SESS,est=1547024407028,to=30000,lcxid=0x0,lzxid=0x500000012,lresp=22061060,llat=11,minlat=0,avglat=11,maxlat=11) /[Zookeeper Server IP]:42946[0](queued=0,recved=1,sent=0) |
查看Session及临时节点信息
该命令可以查看指定Zookeeper节点建立Session的信息以及临时节点的信息:
echo "dump" | nc zookeeper.server.3 2181 SessionTracker dump: Session Sets (3): 0 expire at Fri Jan 02 07:13:54 CST 1970: 0 expire at Fri Jan 02 07:14:04 CST 1970: 1 expire at Fri Jan 02 07:14:14 CST 1970: 0x10000b81b7d0003 ephemeral nodes dump: Sessions with Ephemerals (0): |
该命令只有指定了Leader节点才有效。
查看Zookeeper节点的环境变量
该命令可以查看指定Zookeeper节点的环境变量信息:
echo "envi" | nc zookeeper.server.3 2181 |
监测Zookeeper节点可用状态
该命令可以查看指定Zookeeper节点是否正常:
echo "ruok" | nc zookeeper.server.3 2181 imok |
如果节点正常则返回imok
,如果不正常则没有任何响应。
查看Zookeeper节点的信息
该命令可以查看指定Zookeeper节点的信息:
echo "srvr" | nc zookeeper.server.3 2181 Zookeeper version: 3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03, built on 06/29/2018 00:39 GMT Latency min/avg/max: 0/1/8 Received: 34 Sent: 33 Connections: 1 Outstanding: 0 Zxid: 0x500000012 Mode: leader Node count: 164 Proposal sizes last/min/max: 36/32/90 |
查看Zookeeper节点的信息以及连接Client信息
该命令可以查看指定Zookeeper节点的信息,以及连接该节点的Client信息:
echo "stat" | nc zookeeper.server.1 2181 Zookeeper version: 3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03, built on 06/29/2018 00:39 GMT Clients: /[Client IP]:35764[1](queued=0,recved=54,sent=54) /[Zookeeper Server IP]:42956[0](queued=0,recved=1,sent=0) Latency min/avg/max: 0/0/17 Received: 223 Sent: 222 Connections: 2 Outstanding: 0 Zxid: 0x500000012 Mode: follower Node count: 164 |
查看Zookeeper节点的监控状态信息
该命令可以查看指定Zookeeper节点的监控状态信息:
echo "mntr" | nc zookeeper.server.1 2181 zk_version 3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03, built on 06/29/2018 00:39 GMT zk_avg_latency 0 zk_max_latency 17 zk_min_latency 0 zk_packets_received 236 zk_packets_sent 235 zk_num_alive_connections 2 zk_outstanding_requests 0 zk_server_state follower zk_znode_count 164 zk_watch_count 0 zk_ephemerals_count 0 zk_approximate_data_size 13322 zk_open_file_descriptor_count 116 zk_max_file_descriptor_count 65535 zk_fsync_threshold_exceed_count 0 |
我们可以使用以上这些命令方便的查看Zookeeper节点以及Client的各种信息,提高效率。
小结
这一章节带大家实践搭建了真正的Zookeeper集群,为之后搭建Kafka集群打基础,同时还复习了Zookeeper CLI的使用方式以及很重要的Zookeeper四字真言。希望能给小伙伴们带来帮助。