目标
- 在一台机器上配置三个Zookeeper服务。
- 启动服务并选出群首(Leader)
- 测试当有一个服务丢失时,客户端可以自动连接到其它服务上
配置说明
目录结构
- /zookeeper
- /z1/z1.cfg
- /z1/data/myid
- /z2/z2.cfg
- /z2/data/myid
- /z3/z3.cfg
- /z3/data/myid
/zookeeper
Zookeeper的程序
/z1/z1.cfg
第一台服务器的配置文件
tickTime=2000 initLimit=10 syncLimit=5 dataDir=./data clientPort=2181 server.1=127.0.0.1:2222:2223 server.2=127.0.0.1:3333:3334 server.3=127.0.0.1:4444:4445
dataDir
:是配置这个服务的数据文件存在哪个目录clientPort
:是给客户端用的server.X
:是配置这组集群都有哪些服务器(包含自己这台)- 第一段
127.0.0.1
:是集群服务器的IP,如果是局域网内其他机器上要配置成192.168.x.x或172.18.x.x等 - 第二段
2222
:是用于仲裁通信的接口(暂时还不明是干什么的),对应服务启动时会开启这个端口,如果是在一台机器上启动多个服务,必须设成不同的端口 - 第三段
2223
:是用户选举群首的接口
- 第一段
/z1/data/myid
这个文件用来标识是第几台服务器
1
里面只有一个1
说明这个服务对应的是/z1/z1.cfg
中的server.1
,将开启2181
,2222
,2223
这三个端口。
/data
这个目录也是在/z1/z1.cfg
中dataDir
配置的。
启动Zookeeper的时候应该会根据dataDir
找到myid
这个文件
/z2/z2.cfg
tickTime=2000 initLimit=10 syncLimit=5 dataDir=./data clientPort=2182 server.1=127.0.0.1:2222:2223 server.2=127.0.0.1:3333:3334 server.3=127.0.0.1:4444:4445
和/z1/z1.cfg
基本一致,只是clientPort
改为了2182
,因为同一台机器启动多个服务不能占用同一个端口。
启动服务时将开启2182
,3333
,3334
端口
/z2/data/myid
2
功能和/z1/data/myid
一样,只是内容改为了2
用来标识是第二个服务器
/z3/z3.cfg 和 /z3/data/myid
和z2一样,只是换掉了对应的端口和服务器id
启动服务
只启动一个服务
cd ./z1 ../zookeeper/bin/zkServer.sh start-foreground ./z1.cfg
进入./z1
目录启动zookeeper服务,因为配置文件里写的dataDir=./data
,会基于运行命令时的路径找data目录,所以需要先进入z1后再执行启动命令,如果dataDir
配置的是系统的绝对路径,则没有这个问题。
为了方便查看日志,使用了start-foreground
,以前台方式启动服务。正常情况下可以直接使用start
后台启动,日志会生成到同目录下的zookeeper.out
中。
./z1.cfg
是选用的配置文件,比如这里,他会开启2181
端口,然后找到./data/myid
,发现自己是1
号服务器,然后再根据server.1
的设置再开启2222
和2223
端口。同时会去尝试链接server.2
和server.3
启动后会一直抛出这样的错误:
2018-01-04 11:52:01,382 [myid:1] - WARN [WorkerSender[myid=1]:[email protected]] - Cannot open channel to 2 at election address /127.0.0.1:3334 java.net.ConnectException: Connection refused (Connection refused) at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:400) at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:243) at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:225) at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:402) at java.base/java.net.Socket.connect(Socket.java:591) at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:558) at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:534) at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:454) at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:435) at java.base/java.lang.Thread.run(Thread.java:844) 2018-01-04 11:52:01,385 [myid:1] - INFO [WorkerSender[myid=1]:[email protected]] - Resolved hostname: 127.0.0.1 to address: /127.0.0.1 2018-01-04 11:52:01,387 [myid:1] - WARN [WorkerSender[myid=1]:[email protected]] - Cannot open channel to 3 at election address /127.0.0.1:4445 java.net.ConnectException: Connection refused (Connection refused) at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:400) at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:243) at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:225) at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:402) at java.base/java.net.Socket.connect(Socket.java:591) at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:558) at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:534) at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:454) at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:435) at java.base/java.lang.Thread.run(Thread.java:844) 2018-01-04 11:52:01,388 [myid:1] - INFO [WorkerSender[myid=1]:[email protected]] - Resolved hostname: 127.0.0.1 to address: /127.0.0.1
这是因为现在只启动了一个服务,集群中配置了三个服务,要想达成选举,必须至少有两个存活的服务。这时,他会一直尝试连接另两个服务的选举端口3334
和4445
。
启动第二个服务
cd ./z2 ../zookeeper/bin/zkServer.sh start-foreground ./z2.cfg
启动第二个服务后,达成了选举条件。
其中一个服务会输出这样的信息:说明已经选举出自己为群首。
2018-01-04 11:52:59,961 [myid:2] - INFO [QuorumPeer[myid=2]/0:0:0:0:0:0:0:0:2182:[email protected]] - LEADING - LEADER ELECTION TOOK - 2312
其它服务会出现这样的信息:说明已经选举出群首,但不是自己,自己需要追随群首
2018-01-04 11:52:59,960 [myid:1] - INFO [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:[email protected]] - FOLLOWING - LEADER ELECTION TOOK - 58587
现在已达成目标2,选举出群首,为了达成目标3:”测试当有一个服务丢失时,客户端可以自动连接到其它服务上”, 先不启动第三个服务。
客户端连接服务
./zookeeper/bin/zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
客户端连接的时候需要指定需要使用集群中的哪些服务,目前将所有的服务都填进去。
因为是随机连接到某个服务,如果集群是跨机房的,可以只选择离自己近一些快一些的服务,但也有可能点儿背选的服务全挂了而其它服务都是好的。
成功连接后会出现这样的信息:
2018-01-04 12:00:30,748 [myid:] - INFO [main-SendThread(127.0.0.1:2182):[email protected]] - Socket connection established to 127.0.0.1/127.0.0.1:2182, initiating session
说明已经成功连接到了server.2
(127.0.0.1:2182
)。
quit
或Control+C
关掉客户端连接,反复重试几次,有可能出现这样的信息:
2018-01-04 12:00:35,228 [myid:] - INFO [main-SendThread(127.0.0.1:2183):[email protected]] - Opening socket connection to server 127.0.0.1/127.0.0.1:2183. Will not attempt to authenticate using SASL (unknown error) 2018-01-04 12:00:35,247 [myid:] - WARN [main-SendThread(127.0.0.1:2183):[email protected]] - Session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect java.net.ConnectException: Connection refused at java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) at java.base/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:1144) JLine support is enabled [zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTING) 0] 2018-01-04 12:00:35,357 [myid:] - INFO [main-SendThread(127.0.0.1:2181):[email protected]] - Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error) 2018-01-04 12:00:35,359 [myid:] - INFO [main-SendThread(127.0.0.1:2181):[email protected]] - Socket connection established to 127.0.0.1/127.0.0.1:2181, initiating session 2018-01-04 12:00:35,406 [myid:] - INFO [main-SendThread(127.0.0.1:2181):[email protected]] - Session establishment complete on server 127.0.0.1/127.0.0.1:2181, sessionid = 0x100081e1ee00001, negotiated timeout = 30000
说明客户端在尝试连接server.3
(127.0.0.1:2183
)的时候失败了,重新连接了另一台服务器server.1
(127.0.0.1:2181
)。