參考
過程
從github clone到本地
git clone https://github.com/apache/zookeeper.git
commit的版本是:ae7f72d31e4dc9c6e307b1c14271e74950b022dc
idea maven導入,然後mvn compile一把
增加必要的配置
在conf文件夾里加入配置: zoo1.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper/z1/data # 創建好data目錄
dataLogDir=/tmp/zookeeper/z1/log # 定義好日誌文件
clientPort=2181
將log4j.properties複製到我們要用的server文件夾裏:
github/zookeeper/zookeeper-server/src/main/resources/log4j.properties
然後配置好啓動server:
debug方式啓動server。
我遇到的坑
log4j jar包找不到
Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
at org.apache.zookeeper.server.quorum.QuorumPeerMain.<clinit>(QuorumPeerMain.java:76)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
如果遇到找不到log4j的情況,是因爲沒有真正把log4j相關的jar包引入到
classpath裏。可以通過配置 java -cp xxx.jar 引入
找不到log4j.properties
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.server.quorum.QuorumPeerConfig).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
是因爲idea沒有將github/zookeeper/zookeeper-server/src/main/resources
這個文件夾標誌爲resources文件夾,所以拷貝進去了也沒用。idea裏右鍵標記一把。
同理配置好啓動client:
成功運行
成功了!折騰了半天終於搞定!
集羣模式
將conf裏的zoo1.cfg 分別拷貝出zoo2.cfg和zoo3.cfg;同時要給每個節點創建一個myid文件,填入當前server的id
zoo1.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper/z1/data
dataLogDir=/tmp/zookeeper/z1/log
clientPort=2181
server.1=127.0.0.1:2887:3887
server.2=127.0.0.1:2888:3888
server.3=127.0.0.1:2889:3889
mkdir -p /tmp/zookeeper/z1/data
echo 1 > /tmp/zookeeper/z1/data/myid
zoo2.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper/z2/data
dataLogDir=/tmp/zookeeper/z2/log
clientPort=2182
server.1=127.0.0.1:2887:3887
server.2=127.0.0.1:2888:3888
server.3=127.0.0.1:2889:3889
mkdir -p /tmp/zookeeper/z2/data
echo 2 > /tmp/zookeeper/z2/data/myid
zoo3.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper/z3/data
dataLogDir=/tmp/zookeeper/z3/log
clientPort=2183
server.1=127.0.0.1:2887:3887
server.2=127.0.0.1:2888:3888
server.3=127.0.0.1:2889:3889
mkdir -p /tmp/zookeeper/z3/data
echo 3 > /tmp/zookeeper/z3/data/myid
分別在idea裏配置不同的application裏的命令行參數,然後運行
那就可以看到驗證了我們理論上的:
順序啓動,中間server是leader
選舉流程是:
1、server1啓動,投票給自己,發送選票給其他小夥伴,其他小夥伴沒有反應,只好不斷重試
2、server2啓動,投票給自己,收到了server1的自薦選票,發現server1並沒有自己牛皮(排序規則:epoch>zxid>serverid,server2贏在了serverid),於是發送投自己的選票給其他小夥伴
2020-05-12 17:00:48,122 [myid:2] - INFO [WorkerReceiver[myid=2]:FastLeaderElection$Messenger$WorkerReceiver@389] - Notification: my state:LOOKING; n.sid:1, n.state:LOOKING, n.leader:1, n.round:0x1, n.peerEpoch:0x0, n.zxid:0x0, message format version:0x2, n.config version:0x0
2020-05-12 17:00:48,124 [myid:2] - INFO [WorkerReceiver[myid=2]:FastLeaderElection$Messenger$WorkerReceiver@389] - Notification: my state:LOOKING; n.sid:1, n.state:LOOKING, n.leader:2, n.round:0x1, n.peerEpoch:0x0, n.zxid:0x0, message format version:0x2, n.config version:0x0
2020-05-12 17:00:48,326 [myid:2] - INFO [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2182)(secure=disabled):QuorumPeer@857] - Peer state changed: leading
3、server1收到了server2的自薦,發現自己確實沒server1牛皮,於是乖乖改自己選票也選server1
4、達到了quorum條件,server1和server2都知道誰是老大了,於是server2成功當了老大,LEADING,server1乖乖FOLLOWING
5、那麼server3再啓動的時候是怎樣的呢?
如日誌所示,server3啓動的時候,會給server1和server2廣播,要選自己當老大;server1和server2都已經選好了當然不答應:
代碼:
server1和server2收到server3的選票,一看兄弟你這epoch跟不上潮流,就把最新的選票發給server3了,於是server3可以收到來自server1和server2的選票,就知道自己不是當老大的料
然後就灰溜溜的改成FOLLOWING了。
通過debug模式再確認下,server1和3用run的,server2用debug
斷點打在上面的代碼
server3啓動之後,server2果然在上面斷點了,server2果然收到了server3自薦的選票
THE END
環境搭好了以後可以看下寫請求的細節了,美滋滋。