1. 程式人生 > >使用小記:Zookeeper中動態改變節點的功能

使用小記:Zookeeper中動態改變節點的功能

switch zkCli.sh enable idt setting zkserver 穩定 ack 模式

Zookeeper 3.5+提供了reconfig功能實現動態配置節點,官方的說明是,“你再也不需要進行全部節點重啟”就可以應用所有的修改:

http://zookeeper.apache.org/doc/r3.5.4-beta/zookeeperReconfig.html

我們不妨按照官方的說明嘗試一下。

根據文檔,我們先配置一個3節點集群好了,配置文件內容如下:

zoo1.cfg

reconfigEnabled=true
standaloneEnabled=false
tickTime=2000
dataDir=/tmp/zkcluster/zk1
initLimit=5
syncLimit=2
clientPort=2791
server.1=127.0.0.1:2780:2783:participant;2791
server.2=127.0.0.1:2781:2784:participant;2792
server.3=127.0.0.1:2782:2785:participant;2793

zoo2.cfg

reconfigEnabled=true
standaloneEnabled=false
tickTime=2000
dataDir=/tmp/zkcluster/zk2
initLimit=5
syncLimit=2
clientPort=2792
server.1=127.0.0.1:2780:2783:participant;2791
server.2=127.0.0.1:2781:2784:participant;2792
server.3=127.0.0.1:2782:2785:participant;2793

zoo3.cfg

reconfigEnabled=true
standaloneEnabled=false
tickTime=2000
dataDir=/tmp/zkcluster/zk3
initLimit=5
syncLimit=2
clientPort=2793
server.1=127.0.0.1:2780:2783:participant;2791
server.2=127.0.0.1:2781:2784:participant;2792
server.3=127.0.0.1:2782:2785:participant;2793

其實這三個配置文件基本相同,差別就是dataDir和clientPort不同。

請註意如下幾點:

1. reconfigEnabled=true,這個配置是用來實現動態配置的,一定要設置,否則集群啟動後會無法修改現有配置

2. standaloneEnabled=false,根據官方文檔:

http://zookeeper.apache.org/doc/r3.5.4-beta/zookeeperReconfig.html#sc_reconfig_standaloneEnabled

的"The standaloneEnabled flag"章節,文中提到的:

Prior to 3.5.0, one could run ZooKeeper in Standalone mode or in a Distributed mode. These are separate implementation stacks
, and switching between them during run time is not possible. By default (for backward compatibility) standaloneEnabled is set to true. The consequence of using this default is that if started with a single server the ensemble will not be allowed to grow, and if started with more than one server it will not be allowed to shrink to contain fewer than two participants. Setting the flag to false instructs the system to run the Distributed software stack even if there is only a single participant in the ensemble. To achieve this the (static) configuration file should contain: standaloneEnabled=false

因為Standalone和Ensemble模式使用的是不同的實現棧,為了讓我們的集群能夠動態增加和減少節點,並且集群節點能夠少於2,最好使用Ensemble模式。

3. clientPort=2793, 官方文檔不建議使用這個參數,但是我實在不知道如何配置連接用的端口,所以保留了這個參數

4. dataDir, 請為每個節點單獨配置一個數據目錄,且裏面建立一個名為“myid”的文件,內容為本節點的id(例如dataDir=/tmp/zkcluster/zk1的節點,在此目錄創建myid文件,內容為1)。這個目錄會存放集群數據的快照。

當我們設置好上述參數後,即可啟動節點:

技術分享圖片

上圖中,我寫了個腳本能夠只要輸入節點的編號即可啟動,實際上執行時,請使用:

zkServer.sh start /dir/to/zookeeper/conf/zooN.cfg

啟動

此時我們連上任何一個節點,可以看到集群已經啟動了:

zkCli.sh -server 127.0.0.1:2791

連上集群後使用config命令檢查節點:

技術分享圖片

至此為止都是基本操作,接下來到達最重要的部分:動態配置集群以實現增加或者減少節點

首先我們以下述配置文件再啟動一個節點:

reconfigEnabled=true
standaloneEnabled=false
tickTime=2000
dataDir=/tmp/zkcluster/zk4
initLimit=5
syncLimit=2
clientPort=2794
server.1=127.0.0.1:2780:2783:participant;2791
server.4=127.0.0.1:2801:2802:participant;2794

配置在前面的章節已經解釋過了,但是配置節點時只設置了兩個,這一點可能會令人迷惑,在這裏說明一下:大家如果參考文檔,會發現3.5+版本會自動把配置文件變為動態配置文件,靜態的部分還是放在原來的zooN.cfg當中,動態的部分放到了zooN.cfg.dynamic.xxx當中了,而且集群的配置文件在絕大多數時間中都是一致的,只有在重新配置的時候會經歷短暫的不一致,利用這一特性,讓新加入節點連接到集群上,然後從集群同步配置過來即可。

啟動這個節點後,連接上這個節點觀察集群:

技術分享圖片

大家可以看到,這個節點實際上是連接到集群的,但是從集群上同步的配置卻不包含本節點。

註意:前面提到過自動同步配置的機制,此時本節點(節點4)會將集群配置同步到本地,如果此時重啟節點,節點將沒有辦法再次被啟動,因為集群中不包含本節點。

現在連接到任何一個集群內節點(1,2,或者3),使用下述命令添加節點:

reconfig -add server.4=127.0.0.1:2801:2802:participant;2794

然後就。。。。。失敗了技術分享圖片

技術分享圖片

搜索一下Authentication is not valid,可以知道是因為服務器默認沒有/zookeeper/config的寫入權限導致的,此時需要添加寫入權限:

1. 先進入zookeeper的安裝目錄,然後執行下述命令產生認證使用的摘要信息:

java -cp ./lib/*:./* org.apache.zookeeper.server.auth.DigestAuthenticationProvider su:passwd

說明下,這條命令實際上在執行zookeeper的org.apache.zookeeper.server.auth.DigestAuthenticationProvider功能,

使用用戶名:su

和密碼:passwd

產生認證參數,執行完畢後程序返回:

su:passwd->su:gACzJ4L2A0F2ygTno5HQnfabuik=

2. 修改zkServer.sh,添加下述命令行:

SERVER_JVMFLAGS="-Dzookeeper.DigestAuthenticationProvider.superDigest=su:gACzJ4L2A0F2ygTno5HQnfabuik="

其中紅色部分是上一步(1)產生的摘要信息。

然後重啟集群中的一個節點

3. 連接步驟2中重啟的節點,執行下述命令:

addauth digest su:passwd
reconfig -add server.4=127.0.0.1:2801:2802:participant;2794

結果如圖:

技術分享圖片

此時我們連接到第四個節點,然後通過config檢查:

技術分享圖片

發現第四個節點確實已經在集群中了,圖中我還在第四個節點get了一下/k的值,這個值是在第一個節點設置的,可以看到,數據也同步過來了。

終於用上了zookeeper的動態配置功能,再也不用一個一個重啟實例來添加集群節點了技術分享圖片

最後,關於zookeeper集群的幾點思考:

1. 在整個集群中,保留幾個節點作為核心集群,當要添加、刪除節點時,從這些節點進行,這樣就不需要為所有的節點都提供/zookeeper/config的寫入權限,在生產環境中要是每個節點都獲取了寫入權限,很有可能導致非專職運維的成員能夠修改集群信息。當然,最重要的還是密碼的保護,要是密碼被非運維人員知道了,同時他也知道核心節點的地址,一樣可以修改集群配置。

2. 關於集群節點數量的問題,上面的例子中,我們向3節點的集群增加了一個節點,這只是一個說明動態配置zookeeper的例子,實際使用時集群節點數量最好為奇數,因為zookeeper是基於大多數節點可用時集群可用的,也就是說,當有5個節點時,可以容忍2個節點的失效,而當擁有4個節點時,只能容忍一個節點失效,和擁有3個節點效果一樣。

zookeeper的官方文檔中,有兩處描述了這個問題,第一處是:

http://zookeeper.apache.org/doc/r3.5.4-beta/zookeeperStarted.html#sc_RunningReplicatedZooKeeper

“Running Replicated ZooKeeper”章節的Note部分,明確說明了集群要使用奇數個節點,但是只是說了兩個節點系統沒有一個節點系統穩定

第二個就是(個人覺得這一段最明確):

http://zookeeper.apache.org/doc/r3.1.2/zookeeperAdmin.html#sc_designing

“Designing a ZooKeeper Deployment”章節的“Cross Machine Requirements”中,有集群中節點數量的計算公式:

2xF+1

其中F是集群容忍失效機器的數目,通過這個公式計算,3個節點的集群和4個節點的集群都只能容忍1個節點的失效

3. 關於動態向集群添加節點

其實有三種方式向集群添加節點(再次搬出官方文檔):

http://zookeeper.apache.org/doc/r3.5.4-beta/zookeeperReconfig.html#sc_reconfig_modifying

請看到“Adding servers”部分:

1. 通過配置文件將要添加的節點當作Observer加入集群(可以添加多個節點),然後再在系統中重新配置為Participant

2. 通過配置文件將要添加的節點當作Participant加入集群,每個節點的配置文件只能添加集群節點和自己,否則新加入的節點可能形成一個集群,導致發生腦裂,請參考下面的“Warning”部分

3. 僅將Leader節點和自己加入配置文件,然後通過reconfig將自身加入集群(本實例中使用的方法),這種方法有兩個前提條件:

a. 配置文件中只能出現自身節點和Leader節點

b. 如果添加節點的過程中Leader掛掉,此時自身的配置已經有問題了,需要下線本節點重新配置再加入

實際生產時,使用1是最可靠的。

使用小記:Zookeeper中動態改變節點的功能