ZooKeeper 服務器在啓動時從一個名爲 zoo.cfg 的配置文件讀取全部選項,多個服務器若是角色類似,同時基本配置信息同樣,就能夠共享一個文件。
data 目錄下的 myid 文件用於區分各個服務器,對每一個服務器來講,data 目錄是惟一的,所以這個目錄能夠更加方便地保持一些差別化文件。服務器ID 將 myid 文件做爲一個索引引入到配置文件中,一個特定的 ZooKeeper 服務器能夠知道如何配置本身參數。
配置參數經常經過配置文件的方式進行設置,本節後續部分,經過列表方式列出了這些參數。不少參數也能夠經過Java的系統屬性傳遞,其形式一般爲zookeeper.propertyName,在啓動服務器時,經過-D選項設置這些屬性。不過,系統屬性所對應的一個特定參數對服務來講是插入的配置,配置文件中的配置參數優先於系統屬性中的配置。
- clientPort
客戶端所鏈接的服務器所監聽的TCP端口,默認狀況下,服務端會監聽在全部的網絡鏈接接口的這個端口上,除非設置了clientPortAddress參數。客戶端端口能夠設置爲任何值,不一樣的服務器也能夠監聽在不一樣的端口上。默認端口號爲2181。
dataDir 和 dataLogDirjava
- dataDir:用於配置內存數據庫保存的模糊快照的目錄,若是某個服務器爲集羣中的一臺,id文件也保存在該目錄下。dataDir並不須要配置到一個專用存儲設備上,快照將會之後臺線程的方式寫入,且並不會鎖定數據庫,並且快照的寫入方式並非同步方式,直到寫完整快照爲止。
- dataLogDir:事務日誌對該目錄所處的存儲設備上的其餘活動更加敏感,服務端會嘗試進行順序寫入事務日誌,覺得服務端在確認一個事務前必須將數據同步到存儲中,該設備的其餘活動(尤爲是快照的寫入)可能致使同步時磁盤過於忙碌,從而影響寫入的吞吐能力。所以,最佳實踐是使用專用的日誌存儲設備,將dataLogDir的目錄配置指向該設備。
- tickTime
tick的時長單位爲毫秒,tick爲ZooKeeper使用的基本的時間度量單位,在9.7節已經介紹過,該值還決定了會話超時的存儲器大小。Zookeeper集羣中使用的超時時間單位經過tickTime指定,也就說,實際上tickTime設置了超時時間的下限值,由於最小的超時時間爲一個tick時間,客戶端最小會話超時事件爲兩個tick時間。
tickTime的默認值爲3000毫秒,更低的tickTime值能夠更快地發現超時問題,但也會致使更高的網絡流量(心跳消息)和更高CPU使用率(會話存儲器的處理)。
- preAllocSize
用於設置預分配的事務日誌文件(zookeeper.preAllocSize)的大小值,以KB爲單位。
當寫入事務日誌文件時,服務端每次會分配preAllocSize值的KB的存儲大小,經過這種方式能夠分攤文件系統將磁盤分配存儲空間和更新元數據的開銷,更重要的是,該方式也減小了文件尋址操做的次數。默認狀況下preAllocSize的值爲64MB,縮小該值的一個緣由是事務日誌永遠不會達到這麼大,由於每次快照後都會從新啓動一個新的事務日誌,若是每次快照之間的日誌數量很小,並且每一個事務自己也很小,64MB的默認值顯然就太大了。例如,若是咱們每1000個事務進行一次快照,每一個事務的平均大小爲100字節,那麼100KB的preAllocSize值則更加合適。默認的preAllocSize值的設置適用於默認的snapCount值和平均事務超過512字節的狀況。node
- snapCount
指定每次快照之間的事務數(zookeeper.snapCount)。
當Zookeeper服務器重啓後須要恢復其狀態,恢復時兩大時間因素分別是爲恢復狀態而讀取快照的時間以及快照啓動後所發生的事務的執行時間。執行快照能夠減小讀入快照文件後須要應用的事務數量,可是進行快照時也會影響服務器性能,即使是經過後臺線程的方式進行寫入操做。
snapCount的默認值爲100000,由於進行快照時會影響性能,因此集羣中全部服務器最好不要在同一時間進行快照操做,只要仲裁服務器不會一同進行快照,處理時間就不會受影響,所以每次快照中實際的事務數爲一個接近snapCount值的隨機數。
注意,若是snapCount數已經達到,但前一個快照正在進行中,新的快照將不會開始,服務器也將繼續等到下一個snapCount數量的事務後再開啓一個新的快照。
- autopurge.snapRetainCount
當進行清理數據操做時,須要保留在快照數量和對應的事務日誌文件數量。
ZooKeeper將會按期對快照和事務日誌進行垃圾回收操做,autopurge.snapRetainCount值指定了垃圾回收時須要保留的快照數,顯然,並非全部的快照均可以被刪除,由於那樣就不可能進行服務器的恢復操做。autopurge.snapRetainCount的最小值爲3,也是默認值的大小。
- autopurge.purgeInterval
對快照和日誌進行垃圾回收(清理)操做的時間間隔的小時數。若是設置爲一個非0的數字,autopurge.purgeInterval指定了垃圾回收週期的時間間隔,若是設置爲0,默認狀況下,垃圾回收不會自動執行,而須要經過ZooKeeper發行包中的zkCleanup.sh腳本手動運行。
- fsync.warningthresholdms
觸發警告的存儲同步時間閥值(fsync.warningthresholdms),以毫秒爲單位。
ZooKeeper服務器在應答變化消息前會同步變化狀況到存儲中。若是同步系統調用消耗了太長時間,系統性能就會受到嚴重影響,服務器會跟蹤同步調用的持續時間,若是超過fsync.warningthresholdms只就會產生一個警告消息。默認狀況下,該值爲1000毫秒。
- weight.x=n
該選項經常以一組參數進行配置,該選項指定組成一個仲裁機構的某個服務器的權重爲n,其權重n值指示了該服務器在進行投票時的權重值。在ZooKeeper中一些部件須要投票值,好比羣首選舉中和原子廣播協議中。默認狀況下,一個服務器的權重值爲1,若是定義的一組服務器沒有指定權重,全部服務器的權重值將默認分配爲1。
- traceFile
持續跟蹤ZooKeeper的操做,並將操做記錄到跟蹤日誌中,跟蹤日誌的文件名爲traceFile.year.month.day。除非設置了該選項(requestTraceFile),不然跟蹤功能將不會啓用。
該選項用來提供ZooKeeper所進行的操做的詳細視圖。不過,要想記錄這些日誌,ZooKeeper服務器必須序列化操做,並將操做寫入磁盤,這將爭用CPU和磁盤的時間。若是你使用了該選項,請確保不要將跟蹤文件放到日誌文件的存儲設備中。還須要知道,跟蹤選項還可能影響系統運行,甚至可能會很難重現跟蹤選項關閉時發生的問題。另外還有個有趣的問題,traceFile選項的Java系統屬性配置中不含有zookeeper前綴,並且系統屬性的名稱也與配置選項名稱不一樣,這一點請當心。
這些配置參數能夠限制服務器和客戶端之間的通訊,超時選項也在該節進行討論:
- globalOutstandingLimit
ZooKeeper中待處理請求的最大值(zookeeper.globalOutstandingLimit)。
ZooKeeper客戶端提交請求比ZooKeeper服務端處理請求要快不少,服務端將會對接收到的請求隊列化,最終(也許幾秒以內)可能致使服務端的內存溢出。爲了防止發生這個問題,ZooKeeper服務端中若是待處理請求達到globalOutstandingLimit值就會限制客戶端的請求。但globalOutstandingLimit值並非硬限制,由於每一個客戶端至少有一個待處理請求,不然會致使客戶端超時,所以,當達到globalOutstandingLimit值後,服務端還會繼續接收客戶端鏈接中的請求,條件是這個客戶端在服務器中沒有任何待處理的請求。
爲了肯定某個服務器的全侷限制值,咱們只是簡單地將該參數值除以服務器的數量,目前尚未更智能的方式去實現全局待處理操做數量的計算,並強制採用該參數所指定的限制值,所以,該限制值爲待處理請求的上限值,事實上,服務器之間完美的負載均衡解決方案還沒法實現,因此某些服務器運行得稍緩慢一點,或者處於更高的負載中,即便最終沒有達到全侷限制值也可能被限制住吞吐量。
該參數的默認值爲1000個請求,你可能並不會修改該參數值,但若是你有不少客戶端發送大數據包請求可能就須要下降這個參數值,但咱們在實踐中還未遇到須要修改這個參數的狀況。
- maxClientCnxns
容許每一個IP地址的併發socket鏈接的最大數量。Zookeeper經過流量控制和限制值來避免過載狀況的發生。一個鏈接的創建所使用的資源遠遠高於正常操做請求所使用的資源。咱們曾看到過某些錯誤的客戶端每秒建立不少ZooKeeper鏈接,最後致使拒絕服務(DoS),爲了解決這個問題,咱們添加了這個選項,經過設置該值,能夠在某個IP地址已經有maxClientCnxns個鏈接時拒絕該IP地址新的鏈接。該選項的默認值爲60個併發鏈接。
注意,每一個服務器維護着這個鏈接的數量,若是有一個5個服務器的集羣,而且使用默認的併發鏈接數60,一個欺詐性的客戶端會隨機鏈接到這5個不一樣的服務器,正常狀況下,該客戶端幾乎能夠從單個IP地址上創建300個鏈接,以後纔會觸發某個服務器的限制。
- clientPortAddress
限制客戶端鏈接到指定的接收信息的地址上。默認狀況下,一個ZooKeeper服務器會監聽在全部的網絡接口地址上等待客戶端的鏈接。
有些服務器配置了多個網絡接口,其中一個網絡接口用於內網通訊,另外一個網絡接口用於公網通訊,若是你並不但願服務器在公網接口接受客戶端的鏈接,只須要設置clientPortAddress選項爲內網接口的地址。
- minSessionTimeout
最小會話超時時間,單位爲毫秒。當客戶端創建一個鏈接後就會請求一個明確的超時值,而客戶端實際得到的超時值不會低於minSessionTimeout的值。
minSessionTimeout的默認值爲tickTime值的兩倍。配置該參數值太低可能會致使錯誤的客戶端故障檢測,配置該參數值太高會延遲客戶端故障的檢測時間。
- maxSessionTimeout
會話的最大超時時間值,單位爲毫秒。當客戶端創建一個鏈接後就會請求一個明確的超時值,而客戶端實際得到的超時值不會高於maxSessionTimeout的值。
雖然該參數並不會影響系統的性能,但卻能夠限制一個客戶端消耗系統資源的時間,默認狀況下maxSessionTimeout的時間爲tickTime的20倍。
當以一個集羣來構建ZooKeeper服務時,須要爲每臺服務器配置正確的時間和服務器列表信息,以便服務器之間能夠互相創建鏈接並進行故障監測,在ZooKeeper的集羣中,這些參數的配置必須一致:
- initLimit
對於追隨者最初鏈接到羣首時的超時值,單位爲tick值的倍數。
當某個追隨者最初與羣首創建鏈接時,它們之間會傳輸至關多的數據,尤爲是追隨者落後總體不少時。配置initLimit參數值取決於羣首與追隨者之間的網絡傳輸速度狀況,以及傳輸的數據量大小,若是ZooKeeper中保存的數據量特別大(即存在大量的znode節點或大數據集)或者網絡很是緩慢,就須要增大initLimit值,由於該值取決於環境問題,全部沒有默認值。須要爲該參數配置適當的值,以即可以傳輸所指望的最大快照,也許有時你須要屢次傳輸,你能夠配置initLimit值爲兩倍你所指望的值。若是配置initLimit值太高,那麼首次鏈接到故障的服務器就會消耗更多的時間,同時還會消耗更多的恢復時間,所以最好在你的網絡中進行追隨者與羣首之間的網絡基準測試,以你規劃所使用的數據量來測試出你所指望的時間。
- syncLimit
對於追隨者與羣首進行sync操做時的超時值,單位爲tick值的倍數。
追隨者老是會稍稍落後於羣首,可是若是由於服務器負載或網絡問題,就會致使追隨者落後羣首太多,甚至須要放棄該追隨者,若是羣首與追隨者沒法進行sync操做,並且超過了syncLimit的tick時間,就會放棄該追隨者。與initLimit參數相似,syncLimit也沒有默認值,與initLimit不一樣的是,syncLimit並不依賴於ZooKeeper中保存的數據量大小,而是依賴於網絡的延遲和吞吐量。在高延遲網絡環境中,發送數據和接收響應包會耗費更多時間,此時就須要調高syncLimit值。即便在相對低延遲的網絡中,若是某些相對較大的事務傳輸給追隨者須要必定的時間,你也須要提升syncLimit值。
- leaderServes
配置值爲「yes」或「no」標誌,指示羣首服務器是否爲客戶端提供服務(zookeeper.leaderServes)。
擔任羣首的ZooKeeper服務器須要作不少工做,它須要與全部追隨者進行通訊並會執行全部的變動操做,也就意味着羣首的負載會比追隨者的負載高,若是羣首過載,整個系統可能都會受到影響。
該標誌位若是設置爲「no」就能夠使羣首除去服務客戶端鏈接的負擔,使羣首將全部資源用於處理追隨者發送給它的變動操做請求,這樣能夠提升系統狀態變動操做的吞吐能力。換句話說,若是羣首不處理任何與其直連的客戶端鏈接,追隨者就會有更多的客戶端,由於鏈接到羣首的客戶端將會分散到追隨者上,尤爲注意在集羣中服務器數量比較少的時候。默認狀況下,leaderServes的值爲「yes」。
- server.x=[hostname]:n:n[:observer]
服務器x的配置參數。
ZooKeeper服務器須要知道它們如何通訊,配置文件中該形式的配置項就指定了服務器x的配置信息,其中x爲服務器的ID值(一個整數)。當一個服務器啓動後,就會讀取data目錄下myid文件中的值,以後服務器就會使用這個值做爲查找server.x項,經過該項中的數據配置服務器本身。若是須要鏈接到另外一個服務器y,就會使用server.y項的配置信息來與這個服務器進行通訊。
其中hostname爲服務器在網絡n中的名稱,同時後面跟了兩個TCP的端口號,第一個端口用於事務的發送,第二個端口用於羣首選舉,典型的端口號配置爲2888:3888。若是最後一個字段標記了observer屬性,服務器就會進入觀察者模式。
注意,全部的服務器使用相同的server.x配置信息,這一點很是重要,不然的話,因服務器之間可能沒法正確創建鏈接而致使整個集羣沒法正常工做。
- cnxTimeout
在羣首選舉打開一個新的鏈接的超時值(zookeeper.cnxTimeout)。
ZooKeeper服務器在進行羣首選舉時互相之間會創建鏈接,該選項值肯定了一個服務器在進行重試前會等待鏈接成功創建的時間爲多久,9.2節介紹了該超時的用途。默認的超時時間爲5秒,該值足夠大,也許你並不須要修改。
- electionAlg
選舉算法的配置選項。
爲了整個配置的完整性,咱們也列入了該選項。該選項用於選擇不一樣的羣首選舉算法,但除了默認的配置外,其餘算法都已經棄用了,因此並不須要配置這個選項。
該節中包括認證和受權相關的選型配置。對於Kerberos相關的配置選項信息,請參考6.1.2節:
zookeeper.DigestAuthenticationProvider.superDigest(只適用於Java系統屬性)該系統屬性指定了「super」用戶的密碼摘要信息(該功能默認不啓用),以super用戶認證的客戶端會跳過全部ACL檢查。該系統屬性的值形式爲super:encoded_digest。爲了生成加密的摘要,能夠使用org.apache.zookeeper.server.auth.DigestAuthenticationProvider工具,使用方式以下:
java -cp $ZK_CLASSPATH \ org.apache.zookeeper.server.auth.DigestAuthenticationProvider super:asdf
經過命令行工具生成一個 asdf 密碼的加密摘要信息:
super:asdf->super:T+4Qoey4ZZ8Fnni1Yl2GZtbH2W4=
爲了在服務器啓動中使用該摘要,能夠經過如下命令實現:
export SERVER_JVMFLAGS SERVER_JVMFLAGS=-Dzookeeper.DigestAuthenticationProvicder.superDigest= suer:T+4Qoey4ZZ8Fnni1Yl2GZtbH2W4= ./bin/zkServer.sh start
如今經過 zkCli 進行鏈接:
[zk: localhost:2181(CONNECTED) 0] addauth digest super:asdf [zk: localhost:2181(CONNECTED) 1]
此時,已經以super用戶的身份被認證,如今不會被任何ACL所限制。
【注意:不安全鏈接】算法
ZooKeeper客戶端與服務器之間的鏈接並未加密,所以不要在不可信的連接中使用super的密碼,使用super密碼的安全方式是在ZooKeeper服務器本機上使用super密碼運行客戶端。
- forceSync
經過「yes」或「no」選項能夠控制是否將數據信息同步到存儲設備上(zookeeper.forceSync)。
默認狀況下,forceSync配置yes時,事務只有在同步到存儲設備後纔會被應答,同步系統調用的消耗很大,並且也是事務處理中最大的延遲緣由之一。若是forceSync配置爲no,事務會在寫入到操做系統後就馬上被應答,在將事務寫入磁盤以前,這些事務經常緩存於內存之中,配置forceSync爲no能夠提升性能,但代價是服務器崩潰或停電故障時可恢復性。
- jute.maxbuffer(僅適用於Java系統屬性)
一個請求或響應的最大值,以字節爲單位。該選項只能經過Java的系統屬性進行配置,而且選項名稱沒有zookeeper前綴。
ZooKeeper中內置了一些健康檢查,其中之一就是對可傳輸的znode節點數據的大小的檢查,ZooKeeper被設計用於保存配置數據,配置數據通常由少許的元數據信息(大約幾百字節)所組成。默認狀況下,一個請求或響應消息若是大於1M字節,就會被系統拒絕,能夠使用該屬性來修改健康檢查值,調小檢查值,或者真的確認要調大檢查值。【注意:修改健康檢查值】
雖然經過jute.maxbuffer指定的限制值能夠進行大塊數據的寫入操做,但獲取一個znode節點的子節點,而同時該節點有不少子節點時就會出現問題。若是一個znode節點含有幾十萬個子節點,每一個子節點的名字長度平均爲10個字符,在試着返回子節點列表時就會命中默認最大緩衝大小檢查,此時就會致使鏈接被重置。數據庫
- skipACL
跳過全部ACL檢查(zookeeper.skipACL)。
處理ACL檢查會有必定的開銷,經過該選項能夠關閉ACL檢查功能,這樣作能夠提升性能,但也會將數據徹底暴露給任何一個能夠鏈接到服務器的客戶端。
- readonlymode.enabled(僅適用於Java系統屬性)
將該配置設置爲true能夠啓用服務器只讀模式功能,客戶端能夠以只讀模式的請求鏈接服務器並讀取信息(多是已過時的信息),即便該服務器在仲裁中因分區問題而被分隔。爲了啓用只讀模式,客戶端須要配置canBeReadOnly爲true。
該功能能夠使客戶端即便在網絡分區發生時也能讀取(不能寫入)ZooKeeper的狀態,在這種狀況下,被分區而分離的客戶端依然能夠繼續取得進展,並不須要等待分區問題被修復。特別注意,一個與集羣中其餘服務器失去鏈接ZooKeeper也許會終止以只讀模式提供過時的數據服務。
ZooKeeper採用SLF4J庫(JAVA簡易日誌門面)做爲日誌的抽象層,默認使用Log4J進行實際的日誌記錄功能。
Log4J的配置文件爲log4j.properties,系統會從classpath中加載這個文件,對於Log4J比較失望的是,若是對應路徑不存在log4j.properties文件,咱們會看到如下輸出信息:
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.serv ... log4j:WARN Please initialize the log4j system properly.
通常,log4j.properties會保存到classpath中的conf目錄下,在ZooKeeper中的log4j.properties文件的主要部分:
zookeeper.root.logger=INFO, CONSOLE ① zookeeper.console.threshold=INFO zookeeper.log.dir=. zookeeper.log.file=zookeeper.log zookeeper.log.threshold=DEBUG zookeeper.tracelog.dir=. zookeeper.tracelog.file=zookeeper_trace.log log4j.rootLogger=${zookeeper.root.logger} ② log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender ③ log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold} ④ log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout ⑤ log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - ... log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender ⑥ log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold} ⑦ log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file} log4j.appender.ROLLINGFILE.MaxFileSize=10MB log4j.appender.ROLLINGFILE.MaxBackupIndex=10 log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] -
①第一組配置中,全部配置項均以zookeeper.開頭,配置了該文件的默認值,這些配置項其實是系統屬性配置,能夠經過java命令行指定-D參數來覆蓋JVM的配置。第一行的日誌配置中,默認配置了日誌消息的級別爲INFO,即全部低於INFO級別的日誌消息都會被丟棄,使用的appender爲CONSOLE。你能夠指定多個appender,例如,你若是想將日誌信息同時輸出到CONSOLE和ROLLINGFILE時,能夠配置zookeeper.root.logger項爲INFO,CONSOLE,ROLLINGFILE。
②rootLogger指定了處理全部日誌消息的日誌處理器,由於咱們並不須要其餘日誌處理器。
③該行配置以CONSOLE名稱定義了一個類,該類會處理消息的輸出。在這裏使用的是ConsoleAppender類。
④在appender的定義中也能夠過濾消息,該行配置了這個appender會忽略全部低於INFO級別的消息,由於zookeeper.root.logger中定義了全局閥值爲INFO。
⑤appender使用的佈局類對輸出日誌在輸出前進行格式化操做。咱們經過佈局模式定義了輸出日誌消息外還輸出日誌級別、時間、線程信息和調用位置等信息。
⑥RollingFileAppender實現了滾動日誌文件的輸出,而不是不斷地輸出到一個單個日誌文件或控制檯。除非ROLLINGFILE被rootLogger引用,不然該appender會被忽略。
⑦定義ROLLINGFILE的輸出級別爲DEBUG,由於rootLogger過濾了全部低於INFO級別的日誌,因此,你若是你想看DEBUG消息,就必須將zookeeper.root.logger項的配置從INFO修改成DEBUG。
當考慮在服務器上運行ZooKeeper如何配置時,服務器自己的配置也很重要。爲了達到所指望的性能,能夠考慮使用專用的日誌存儲設備,就是說日誌目錄處於專屬的硬盤上,沒有其餘進程使用該硬盤資源,甚至週期性的模糊快照也不會使用該硬盤。
仲裁(quorum)的概念:該概念深深貫穿於ZooKeeper的設計之中。在複製模式下處理請求時以及選舉羣首時都與仲裁的概念有關,若是ZooKeeper集羣中存在法定人數的服務器已經啓動,整個集羣就能夠繼續工做。
觀察者(observer):與集羣一同工做,接收客戶端請求並處理服務器上的狀態變動,可是羣首並不會等待觀察者處理請求的響應包,同時集羣在進行羣首選舉時也不會考慮觀察者的通知消息。
當集羣中擁有足夠的 ZooKeeper 服務器來處理請求時,稱這組服務器的集合爲仲裁法定人數。
當配置多個服務器來組成ZooKeeper集羣時,咱們默認使用多數原則做爲仲裁法定人數。ZooKeeper會自動監測是否運行於複製模式,從配置文件讀取時肯定是否擁有多個服務器的配置信息,並默認使用多數原則的仲裁法定人數。
關於法定人數的一個重要屬性:
若是一個法定人數解散了,集羣中另外一個法定人數造成,這兩個法定人數中至少有一個服務器必須交集。
ZooKeeper也容許靈活的法定人數配置,這種特殊方案就是對服務器進行分組配置時,會將服務器分組成不相交的集合並分配服務器的權重,經過這種方案來組成法定人數,須要使多數組中的服務器造成多數投票原則。例如,有三個組,每一個組中有三個服務器,每一個服務器的權重值爲1,在這種狀況下,須要四個服務器來組成法定人數:某個組中的兩個服務器,另外一組中的兩臺服務器。
總之,其數學邏輯歸結爲:若是有G個組,所須要的服務器爲一個G組的服務器,知足|G|>|G|/2,同時對於G組中的服務器集合g,還須要集合g中的集合g知足集合g的全部權重值之和W'不小於集合g的權重值之和(如:W>W/2)。
經過如下配置選項能夠建立一個組:
group.x=n[:n]
啓用法定人數的分層構建方式。x爲組的標識符,等號後面的數字對應服務器的標識符,賦值操做符右側爲冒號分隔的服務器標識符的列表。注意,組與組之間不能存在交集,全部組的並集組成了整個ZooKeeper集羣,換句話說,集羣中的每一個服務器必須在某個組中被列出一次。
【下面的示例說明了9個服務器被分爲3組的狀況:】apache
group.1=1:2:3 group.2=4:5:6 group.3=7:8:9
這個例子中,每一個服務器的權重都同樣,爲了構成法定人數,須要兩個組及這兩個組中各取兩個服務器,也就是總共4個服務器。但根據法定人數多數原則,至少須要5個服務器來構成一個法定人數。注意,不能從任何子集造成法定人數的4個服務器,不過,一個組所有服務器加上另外一個組的一個單獨的服務器並不能構成法定人數。
當在跨多個數據中心部署ZooKeeper服務時,這種配置方式有不少優勢。例如,一個組可能表示運行於不一樣數據中心的一組服務器,即便這個數據中心崩潰,ZooKeeper服務也能夠繼續提供服務。
在跨三個數據中心部署的這種方式能夠容忍某個數據中心的故障問題,能夠在兩個數據中心中每個部署三個服務器,而只在第三個數據中心部署一個服務器,經過這種方式來使用多數原則,這樣,若是某個數據中心不可用,其餘兩個數據中心還能組成法定人數。這種配置方式的優勢是這七個服務器中的任何四個都構成一個法定人數,而缺點是一旦某個數據中心不可用,其餘數據中心中任何服務器的崩潰都沒法容忍。
若是隻有兩個數據中心可用,能夠使用 【權重值】來表示優先權,例如,基於每一個數據中心中的客戶端數量來配置權重值。只有兩個數據中心時,若是每一個服務器的權重值都同樣,就沒法容忍任何一個數據中心的失效,可是若是對某個服務器分配了更高的權重值,就能夠容忍這兩個數據中心中某個數據中心的失效。假設,在每一個數據中心中分配三個服務器,而且將這些服務器均放到同一組中:
group.1=1:2:3:4:5:6
由於全部的服務器默認狀況下權重值都同樣,所以只要6個服務器中有4個服務器有效時就能夠構成法定人數的服務器。固然,這也意味着若是某個數據中心失效,就不能造成法定人數,即便另外一個數據中心的三個服務器均有效。
【爲了給服務器分配不一樣的權重值,能夠經過如下選型進行配置:】數組
weight.x=n
與group選項一塊兒配合使用,經過該選項能夠爲某個服務器造成法定人數時分配一個權重值爲n。其值n爲服務器投票時的權重,ZooKeeper中羣首選舉和原子廣播協議中均須要投票。默認狀況下,服務器的權重值爲1,若是配置文件中定義了組的選項,但爲指定權重值,全部的服務器均會被分配權重值1。假設,某個數據中心只要其全部服務器都可用,即便在其餘數據中心失效時,這個數據中心也能夠提供服務,咱們暫且稱該數據中心爲D1,此時,能夠爲D1中的某個服務器分配更高權重值,以即可以更容易與其餘服務器組成法定人數。緩存
【假設D1中有服務器一、2和3,經過如下方式爲服務器1分配更高的權重值:】安全
weight.1=2
經過以上配置,就有了7個投票,在構成法定人數時,只須要4個投票。若是沒有weight.1=2參數,任何服務器都須要與其餘三個服務器來構成法定人數,但有了這個參數配置,服務器1與兩個服務器就能夠構成法定人數。所以,只要D1可用,即便其餘數據中心發生故障,服務器一、2和3也能構成法定人數並繼續提供服務。經過以上不一樣的法定人數配置的若干示例,看到該配置對部署的影響。提供的分層方案很是靈活,經過不一樣的權重值和組的管理能夠提供不一樣的分層配置。服務器
觀察者(observer)爲ZooKeeper服務器中不參與投票但保障狀態更新順序的特殊服務器。網絡
【配置ZooKeeper集羣使用觀察者,須要在觀察者服務器的配置文件中添加如下行】:
peerType=observer
【同時,還須要在全部服務器的配置文件中添加該服務器的:observer定義。以下】:
server.1:localhost:2181:3181:observer
圖10-1的場景,三個服務器(A、B、C)組成了整個集羣,服務器C因某些網絡擁塞問題稍稍落後於整個集羣,所以服務器C剛剛瞭解事務到<1,3>(其中1爲時間戳,3爲對應該時間戳的事務標識,但由於服務器A和B的通訊良好,因此服務器C稍稍落後並不會致使整個系統變慢,服務器A和B能夠提交事務到<1,6>)。
【圖10-1:含有3個服務器的集羣將要擴展到5個】
如今,假設將全部服務中止,添加服務器D和E到集羣中,固然這兩個新的服務器並不存在任何狀態信息,從新配置了服務器A、B、C、D、E成爲更大的集羣並啓動集羣恢復服務,由於如今有了五個服務器,至少須要三個服務器組成一個法定人數,而服務器C、D、E足夠構成法定人數,所以在圖10-2中看到當這些服務器構成法定人數並開始同步時都發生了什麼。這個場景能夠簡單重現,若是服務器A和B的啓動慢一些,好比服務器A和B比其餘三個服務器的啓動晚一些。一旦新的法定人數開始同步,服務器A和B就會與服務器C進行同步,由於法定人數中服務器C的狀態爲最新狀態,法定人數的三個成員服務器會同步到最後的事務<1,3>,而不會同步<1,4>、<1,5>和<1,6>這三個事務,由於服務器A和B並未構成法定人數的成員。
【圖10-2:5個服務器的集羣的法定人數爲3】
由於已經構成一個活躍的法定人數,這些服務器能夠開始提交新的事務,假設有兩個事務:<2,1>和<2,2>,如圖10-3所示,當服務器A和B啓動後鏈接到服務器C後,服務器C做爲羣首歡迎其加入到集羣之中,並在收到事務<2,1>和<2,2>後當即告知服務器A和B刪除事務<1,4>、<1,5>和<1,6>。
圖10-3:5個服務器的集羣丟失數據
這個結果很是糟糕,丟失了某些狀態信息,並且狀態副本與客戶端所看到的<1,4>、<1,5>、<1,6>也再也不一致。爲了不這個問題,ZooKeeper提供了重配置操做,這意味着運維人員並不須要手工進行重配置操做而致使狀態信息的破壞,並且,也不須要中止任何服務。
【重配置】不只能夠改變集羣成員配置,還能夠修改網絡參數配
置,由於ZooKeeper中配置信息的變化,須要將重配置參數與靜態的配置文件分離,單獨保存爲一個配置文件並自動更新該文件。dynamicConfigFile參數和連接這兩個配置文件。
【使用動態配置以前,回顧一下以前的配置文件:】
tickTime=2000 initLimit=10 syncLimit=5 dataDir=./data dataLogDir=./txnlog 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
【如今,將配置文件修改成動態配置方式:】
tickTime=2000 initLimit=10 syncLimit=5 dataDir=./data dataLogDir=./txnlog dynamicConfigFile=./dyn.cfg
【注意】,甚至從配置文件中刪除了clientPort參數配置,在dyn.cfg文件由服務器項的配置組成,同時還多了一些配置,服務器項的配置形式以下:
server.id=host:n:n[:role];[client_address:]client_port
與正常的配置文件同樣,列出了每一個服務器的主機名和端口號用於法定人數和羣首選舉消息。
【最終的dyn.cfg配置文件以下所示】:
server.1=127.0.0.1:2222:2223:participant;2181 server.2=127.0.0.1:3333:3334:participant;2182 server.3=127.0.0.1:4444:4445:participant;2183
使用重配置以前必須先建立這些文件,一旦這些文件就緒,就能夠經過reconfig操做來從新配置一個集羣,該操做能夠增量或全量(總體)地進行更新操做。
增量的重配置操做將會造成兩個列表:
- 待刪除的服務器列表
待刪除的服務器列表僅僅是一個逗號分隔服務器ID列表- 待添加的服務器項的列表
待添加的服務器項列表爲逗號分隔的服務器項列表,每一個服務器項的形式爲動態配置文件中所定義的形式。例如:
reconfig -remove 2,3 -add \ server.4=127.0.0.1:5555:5556:participant;2184,\ server.5=127.0.0.1:6666:6667:participant;2185
該命令將會刪除服務器2和3,添加服務器4和5。該操做成功執行還須要知足某些條件:
- 首先,與其餘ZooKeeper操做同樣,原配置中法定人數必須處於活動狀態;
- 其次,新的配置文件中構成的法定人數也必須處於活動狀態。
【注意:經過重配置從一個服務器到多個服務器】
當只有一個單獨的ZooKeeper服務器,該服務器以獨立模式運行,這種狀況稍微複雜一些,由於重配置不只改變了法定人數組成的元素,同時還會切換原來的服務器模式從獨立模式到仲裁模式,因此,不容許以獨立模式運行重配置操做,只有在仲裁模式時才能夠使用重配置功能。
ZooKeeper一次容許一個配置的變動操做請求,固然,配置操做會很是快地被處理,並且從新配置也不多發生,因此併發的重配置操做應該不是什麼問題。還能夠使用-file參數來指定一個新的成員配置文件來進行一次全量更新。例如:reconfig-file newconf命令會產生如上面命令同樣的增量操做結果,newconf文件爲:
server.1=127.0.0.1:2222:2223:participant;2181 server.4=127.0.0.1:5555:5556:participant;2184 server.5=127.0.0.1:6666:6667:participant;2185
經過-members參數,後跟服務器項的列表信息,能夠代替-file參數進行全量更新配置操做。
最後【-v】,全部形式的reconfig的爲從新配置提供了條件,若是經過-v參數提供了配置版本號,reconfig命令會在執行前確認配置文件當前的版本號是否匹配,只有匹配纔會成功執行。能夠經過讀取zookeeper/config節點來獲取當前配置的版本號,或經過zkCli工具來調用config獲取配置版本號信息。
客戶端也涉及一些相關的配置問題:鏈接串。
客戶端鏈接串經常表示爲逗號分隔的host:port對,其中host爲主機名或IP地址,經過主機名能夠提供服務器實際IP與所訪問的服務器的標識符之間的間接層的對應關係。
例如,運維人員能夠替換ZooKeeper服務爲另外一個,而不須要改變客戶端的配置。
不過,該靈活性有必定限制,運維人員能夠改變組成集羣的服務器機器,但不能改變客戶端所使用的服務器。
例如,如圖10-4所示,ZooKeeper能夠經過重配置很簡單地將集羣從三個服務器擴展到五個服務器,但客戶端仍然使用三個服務器,而不是五個。
【圖10-4:集羣從三個到五個服務器時,客戶端的重配置】
另外一種方式能夠使ZooKeeper的服務器數量更具彈性,而不須要改變客戶端的配置。對主機名很天然地想到能夠解析爲一個IP地址,但實際上,一個主機名能夠解析爲多個地址,若是主機名解析爲多個IP地址,ZooKeeper就能夠鏈接到其中的任何地址,在圖10-4中,假設服務器zk-a、zk-b和zk-c,解析爲三個獨立的IP地址:10.0.0.一、10.0.0.2和10.0.0.3,如今假設經過DNS配置了一個單獨的主機名:zk,解析爲這三個IP地址,只須要修改DNS的解析地址數量,以後啓動的任何客戶端均可以訪問這五個服務器,如圖10-5所示。
【圖10-5:集羣從三個到五個服務器時,使用DNS對客戶端的重配置】
在使用主機名解析爲多個地址方式時,還有一些注意事項:
- 首先,全部的服務器必須使用相同的客戶端端口號;
- 其次,主機名解析只有在建立鏈接時纔會發生,因此已經鏈接的客戶端沒法知道最新的名稱解析,只能對新建立的ZooKeeper客戶端生效。
【路徑信息】:
客戶端的鏈接還能夠包含路徑信息,該路徑指示瞭解析路徑名稱時的根路徑,其行爲與UNIX系統中的chroot命令類似,並且在ZooKeeper社區中也會常常聽到人們以「chroot」來稱呼這個功能。
例如,若是客戶端的鏈接串爲zk:2222/app/superApp,當客戶端鏈接並執行getData("/a.dat",...)操做時,實際客戶端會獲得/app/superApp/a.dat節點的數據信息(注意,鏈接串中指示的路徑必須存在,而不會建立鏈接串中所指示的路徑)。在鏈接串中添加路徑信息的動機在於一個ZooKeeper集羣爲多個應用程序提供服務,這樣不須要要求每一個應用程序添加其路徑的前綴信息。每一個應用程序能夠相似名稱獨享似的使用ZooKeeper集羣,運維人員能夠按他們的指望來劃分命名空間。
圖10-6的示例展現了不一樣的鏈接串能夠爲客戶端應用程序提供不一樣的根入口點。
【圖10-6:經過鏈接串指定ZooKeeper客戶端的根節點】
【注意:鏈接串的重疊】
當管理客戶端鏈接串時,注意一個客戶端的鏈接串永遠不要包含兩個不一樣的ZooKeeper集羣的主機名,這是最快速也是最簡單致使腦裂問題的方式。
ZooKeeper的另外一個可配置項爲配額,ZooKeeper初步提供了znode節點數量和節點數據大小的配額管理的支持。能夠經過配置來指定某個子樹的配額,該子樹就會被跟蹤,若是該子樹超過了配額限制,就會記錄一條警告日誌,但操做請求仍是能夠繼續執行。此時,ZooKeeper會檢測是否超過了某個配額限制,但不會阻止處理流程。配額管理的跟蹤功能經過/zookeeper子樹完成,因此應用程序不能在這個子樹中存儲本身的數據,這個子樹只應該保留給ZooKeeper使用,而 /zookeeper/quota 節點就是ZooKeeper管理配額的節點。爲了對應用程序/application/superApp建立一個配額項,須要在application/superApp節點下建立兩個子節點zookeeper_limits和zookeeper_stats。
對於znode節點數量的限制稱之爲count,而對於節點數據大小的限制則爲bytes。在zookeeper_limits和zookeeper_stats節點中經過count=n,bytes=m來指定配額,其中n和m均爲整數,在zookeeper_limits節點中,n和m表示將會觸發警告的級別(若是配置爲-1就不會觸發警告信息),在zookeeper_stats借點中,n和m分別表示當前子樹中的節點數量和子樹節點的數據信息的當前大小。
【注意:對元數據的配額跟蹤】
對於子樹節點數據的字節數配額跟蹤功能,並不會包含每一個znode節點的元數據的開銷,元數據的大小大約100字節,因此若是每一個節點的數據大小都比較小,跟蹤znode節點的數量比跟蹤znode數據的大小更加實用。能夠使用zkCli來建立/application/superApp節點,並配置配額限制:
[zk: localhost:2181(CONNECTED) 2] create /application "" Created /application [zk: localhost:2181(CONNECTED) 3] create /application/superApp super Created /application/superApp [zk: localhost:2181(CONNECTED) 4] setquota -b 10 /application/superApp Comment: the parts are option -b val 10 path /application/superApp [zk: localhost:2181(CONNECTED) 5] listquota /application/superApp absolute path is /zookeeper/quota/application/superApp/zookeeper_limits Output quota for /application/superApp count=-1,bytes=10 Output stat for /application/superApp count=1,bytes=5
建立了/application/superApp節點,且該節點的數據爲5個字節(一個單詞「super」),以後爲/application/superApp節點設置了配額限制爲10個字節,當列出/application/superApp節點配置限制是,發現數據大小的配額還有5個字節的餘量,而並未對這個子樹設置znode節點數量的配額限制,由於配額中count的值爲-1。若是發送命令get/zookeeper/quota/application/superApp/zookeeper_stats,能夠直接訪問該節點數據,而不須要使用zkCli工具,事實上,能夠經過建立或刪除這些節點來建立或刪除配額配置。若是運行如下命令:
create /application/superApp/lotsOfData ThisIsALotOfData
就會在日誌中看到以下信息:
Quota exceeded: /application/superApp bytes=21 limit=10
配額,提供了配置選項中的某些限制措施,而ACL策略更值得咱們考慮如何使用ZooKeeper來服務於多租賃(multitenancy)狀況。知足多租賃的一些使人信服的緣由以下:
- 爲了提供可靠的服務器,ZooKeeper服務器須要運行於專用的硬件設備之上,跨多個應用程序共享這些硬件設備更容易符合資本投資的指望。
- 發現,在大多數狀況下,ZooKeeper的流量很是具備突發性:配置或狀態的變化的突發操做會致使大量的負載,從而致使服務長時間的不可用。若是是沒有什麼關聯的應用程序的突發操做,將這些應用程序共享這個服務器更能有效利用硬件資源。不過仍是要注意失聯事件發生時所產生的峯值,某些寫得不太規範的應用程序在處理Disconnected事件時,產生的負載高於其所須要的資源。
- 對於硬件資源的分攤,能夠得到更好的故障容錯性:若是兩個應用程序,從以前各自三個服務器的集羣中轉移到一個由5臺服務器組成的集羣,總量上所使用的服務器更少了,對ZooKeeper也能夠容忍兩臺服務器的故障,而不是以前的只能容忍一個服務器故障。
當服務於多租賃的狀況下時,運維人員通常會將數據樹分割爲不一樣的子樹,每一個子樹爲某個應用程序所專用。開發人員在設計應用程序時能夠考慮在其所用的znode節點前添加前綴,但還有一個更簡單的方法來隔離各個應用程序:在鏈接串中指定路徑部分,10.3節中介紹了這方式。每一個應用程序的開發人員在進行應用程序的開發時,就像使用專用的ZooKeeper服務同樣。若是運維人員決定將應用程序部署到根路徑/application/newapp之下,應用程序能夠使用host:port/application/newapp鏈接串,而不只僅是host:port,經過這種方式,對應用程序所呈現的猶如使用專用服務同樣,與此同時,運維人員還能夠爲/application/newapp節點配置配額限制,以便跟蹤應用程序的空間使用狀況。
數據存儲有兩類:事務日誌文件和快照文件。
這些文件均以普通文件的形式保存到本地文件系統中,在進行關鍵路徑的事務處理時就會寫入事務日誌文件,因此強烈建議將這些文件保存到一個專用存儲設備上快照文件將會被寫入到DataDir參數所指定的目錄中,而事務日誌文件將會被寫入到DataLogDir參數所指定的目錄中。
首先,看一下事務日誌目錄中的文件,若是列出該目錄的信息,會發現只有一個子目錄,名爲version-2,對日誌和快照的格式只作出了一次重大改進,當改變其格式後,發現,將數據經過文件版本進行分離,對於處理版本間的數據遷移是很是有用的。
在運行一些小測試後的目錄內容,有兩個事務日誌文件:
-rw-r--r-- 1 breed 67108880 Jun 5 22:12 log.100000001 -rw-r--r-- 1 breed 67108880 Jul 15 21:37 log.200000001
能夠仔細觀察這些文件信息。首先,考慮到測試不多,而這些文件卻很是大(每一個都超過6MB);其次這些文件名的後綴中均有一個很大數字。ZooKeeper爲文件預分配大的數據塊,來避免每次寫入所帶來的文件增加的元數據管理開銷,若是經過對這些文件進行十六進制轉儲打印,會發現這些文件中所有以null字符(0)填充,只有在最開始部分有少許的二進制數據,服務器運行一段時間後,其中的null字符逐漸被日誌數據替換。
日誌文件中包含事務標籤zxid,但爲了減輕恢復負載,並且爲了快速查找,每一個日誌文件的後綴爲該日誌文件中第一個zxid的十六進制形式。經過十六進制表示zxid的一個好處就是能夠快速區分zxid中時間戳部分和計數器部分,因此在以前例子中的第一個文件的時間戳爲1,而第二個文件的時間戳爲2。
不過,還想繼續看一看文件中保存了什麼內容,對於問題診斷也很是有幫助。有時,開發人員宣稱ZooKeeper丟失了某些znode節點信息,此時只有經過查找事務日誌文件才能夠知道客戶端具體刪除過哪些節點。
能夠經過一下命令來查看第二個日誌文件:
java -cp $ZK_LIBS org.apache.zookeeper.server.LogFormatter version-2 log.200000001
這個命令的輸出信息以下:
7/15/13... session 0x13...00 cxid 0x0 zxid 0x200000001 createSession 30000 7/15/13... session 0x13...00 cxid 0x2 zxid 0x200000002 create '/test,#22746573746 ... 7/15/13... session 0x13...00 cxid 0x3 zxid 0x200000003 create '/test/c1,#6368696c ... 7/15/13... session 0x13...00 cxid 0x4 zxid 0x200000004 create '/test/c2,#6368696c ... 7/15/13... session 0x13...00 cxid 0x5 zxid 0x200000005 create '/test/c3,#6368696c ... 7/15/13... session 0x13...00 cxid 0x0 zxid 0x200000006 closeSession null
每一個日誌文件中的事務均以可讀形式一行行地展現出來。由於只有變動操做纔會被記錄到事務日誌,因此在事務日誌中不會看到任何讀事務操做。
快照文件的命名規則與事務日誌文件的命名規則類似,如下爲以前例子中的服務器的快照列表信息:
-rw-r--r-- 1 br33d 296 Jun 5 07:49 snapshot.0 -rw-r--r-- 1 br33d 415 Jul 15 21:33 snapshot.100000009
快照文件並不會被預分配空間,因此文件大小也更加準確地反映了其中包含的數據大小。其中後綴表示快照開始時當時的zxid值,以前已經介紹過,快照文件實際上爲一個模糊快照,直到事務日誌重現以後纔會成爲一個有效的快照文件。所以在恢復系統時,必須從快照後綴的zxid開始重現事務日誌文件,甚至更早的zxid開始重現事務。快照文件中保存的模糊快照信息一樣爲二進制格式,所以,能夠經過另外一個工具類來檢查快照文件的內容:
java -cp ZK_LIBS org.apache.zookeeper.server.SnapshotFormatter version-2 /snapshot.100000009
這個命令的輸出信息以下:
---- / cZxid = 0x00000000000000 ctime = Wed Dec 31 16:00:00 PST 1969 mZxid = 0x00000000000000 mtime = Wed Dec 31 16:00:00 PST 1969 pZxid = 0x00000100000002 cversion = 1 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x00000000000000 dataLength = 0 ---- /sasd cZxid = 0x00000100000002 ctime = Wed Jun 05 07:50:56 PDT 2013 mZxid = 0x00000100000002 mtime = Wed Jun 05 07:50:56 PDT 2013 pZxid = 0x00000100000002 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x00000000000000 dataLength = 3 ---- ....
只有每一個節點的元數據被轉儲打印出來,這樣,運維人員就能夠知道一個znode節點什麼時候發生了變化,以及哪一個znode節點佔用了大量內存。很遺憾,數據信息和ACL策略並無出如今輸出中,所以,在進行問題診斷時,記住將快照中的信息與日誌文件的信息結合起來分析問題所在。
ZooKeeper的持久狀態由兩個小文件構成,它們是兩個時間戳文件,其文件名爲acceptedEpoch和currentEpoch,以前已經討論過期間戳的概念,而這兩個文件則反映了某個服務器進程已接受的和正在處理的信息。雖然這兩個文件並不包含任何應用數據信息,但對於數據一致性卻相當重要,因此若是你在備份一個ZooKeeper服務器的原始數據文件時,不要忘了這兩個文件。
ZooKeeper數據存儲的一個優勢是,無論獨立模式的服務器仍是集羣方式的服務器,數據的存儲方式都同樣。以前已經介紹過經過事務日誌和快照的合併能夠獲得準確的數據視圖,能夠將事務日誌文件和快照文件拷貝到另外一臺設備上進行這些操做(例如在你的便攜電腦中),將這些文件放到一個獨立模式的服務器下空白的data目錄下,而後啓動服務,該服務就會真實反映出你所拷貝的那個服務器上的狀態信息。這項技術能夠從生產環境拷貝服務器的狀態信息,用於稍後的複查等用途。同時也意味着,只須要簡單地將這些數據文件進行備份,就能夠輕易地完成ZooKeeper服務器的備份,若是採用這種方式進行備份,還須要注意一些問題。首先,ZooKeeper爲複製服務,因此係統中存在冗餘信息,若是進行備份操做,只須要備份其中一臺服務器的數據信息。
當ZooKeeper服務器承認了一個事務,從這時起它就會承諾記錄下該狀態信息,必定要記住這一點,這一點很是重要。所以若是使用舊的備份文件恢復一個服務器,就會致使服務器違反其承諾。若是剛剛遭遇了全部服務器的數據丟失的狀況,這可能不是什麼大問題,但若是你的集羣在正常工做中,而你將某個服務器還原爲舊的狀態,你的行爲可能會致使其餘服務器也丟失了某些信息。
若是要對所有或大多數服務器進行數據丟失的恢復操做,最好的辦法是使用最新抓取的狀態信息(從最新的存活服務器中獲取的備份文件),並在啓動服務器以前將狀態信息拷貝到其餘全部服務器上。
四字母命令提供的這一簡單方法,可讓對系統進行各類各樣的檢查。四字母命令的主要目標就是提供一個很是簡單的協議,使使用簡單的工具,如telnet或nc,就能夠完成系統健康情況檢查和問題的診斷。爲簡單起見,四字母命令的輸出也是可讀形式,使得更容易使用這些命令。
對服務器添加一個新的命令也很容易,命令列表也就會增加。本節中將會介紹一些經常使用的命令,對於最新的所有命令列表信息,請參考ZooKeeper文檔。
- ruok
提供(有限的)服務器的狀態信息。若是服務器正在運行,就會返回imok響應信息。事實上「OK」狀態只是一個相對的概念,例如,服務器運行中,雖沒法與集羣中其餘服務器進行通訊,然而該服務器返回的狀態仍然是「OK」。對於更詳細信息及可靠的健康狀態檢查,須要使用stat命令。
- stat
提提供了服務器的狀態信息和當前活動的鏈接狀況,狀態信息包括一些基本的統計信息,還包括該服務器當前是否處於活動狀態,即做爲羣首或追隨者,該服務器所知的最後的zxid信息。某些統計信息爲累計值,能夠使用srst命令進行重置。
- srvr
提供的信息與stat同樣,只是忽略了鏈接狀況的信息。
- dump
提供會話信息,列出當前活動的會話信息以及這些會話的過時時間。該命令只能在羣首服務器上運行。
- conf
列出該服務器啓動運行所使用的基本配置參數。
- envi
列出各類各樣的Java環境參數。
- mntr
提供了比stat命令更加詳細的服務器統計數據。每行輸出的格式爲key<tab>value。(羣首服務器還將列出只用於羣首的額外參數信息)。
- wchs
列出該服務器所跟蹤的監視點的簡短摘要信息。
- wchc
列出該服務器所跟蹤的監視點的詳細信息,根據會話進行分組。
- wchp
列出該服務器所跟蹤的監視點的詳細信息,根據被設置監視點的znode節點路徑進行分組。
- cons,crst
cons命令列出該服務器上每一個鏈接的詳細統計信息,crst重置這些鏈接信息中的計數器爲0。
四字母命令能夠用於系統的監控,但卻沒有提供系統控制和修改的方法,ZooKeeper經過標準Java管理協議,JMX(Java管理擴展),提供了更強大的監控和管理功能。本節中,將會使用一個簡單的管理控制檯工具jconsole來探索經過JMX管理ZooKeeper功能。
jconsole爲Java中自帶的工具,實際上,相似jconsole這樣的JMX工具經常用於監控遠程的ZooKeeper服務器,但出於說明的目的,將會在ZooKeeper服務所運行的設備運行該工具。
首先、啓動第二個ZooKeeper服務器(即ID爲2的服務器),以後,只須要在命令行中簡單的輸入jconsole命令就能夠啓動jconsole工具,jconsole啓動後,就會看到相似圖10-7中所示的窗口。
注意到其中帶有「zookeeper」名稱的進程,對於本地進程,jconsole會自動發現可鏈接的進程。
【圖10-7:jconsole啓動界面】如今,只須要在列表中雙擊該進程就能夠鏈接到ZooKeeper進程上,由於沒有啓用SSL,此時會提示關於非安全鏈接的選項,單擊非安全鏈接按鈕,以後屏幕中就會出現圖10-8所示的窗口。
【圖10-8:進程管理的第一個窗口】從這個界面中看到,能夠經過該工具獲取關於ZooKeeper服務器的各類各樣有趣的統計信息。JMX支持經過MBean(託管Bean)來將自定義信息暴露給遠程管理者,雖然名字聽起來比較笨拙,但倒是暴露信息和操做的一個很是靈活的方式。jconsole會在最右側的信息標籤中列出進程暴露的全部MBean信息,如圖10-9所示。
【圖10-9:jconsole中MBean信息】在MBean列表中能夠看到ZooKeeper所使用且暴露出來的組件信息,比較關心ZooKeeperService的信息,所以雙擊該列表項,將會看到一個分級的列表副本以及這些副本的信息,若是打開某些列表中的子項,會看到圖10-10所示的信息。
【圖10-10:jconsole中關於服務器2的信息】經過瀏覽replica.2的信息,注意到這些信息中還包括其餘副本
的信息,但只是一些通訊信息,由於服務器2對其餘副本所知信息並很少,因此服務器2沒法展現更多其餘副本信息,而服務器2很瞭解本身的信息,因此它能夠暴露更多的信息。當啓動服務器1,服務器2就能夠與服務器1構成一個法定人數,此時就能夠看到服務器2的更多信息。啓動服務器1,以後再次經過jconsole檢查服務器2信息。圖10-11展現了經過JMX暴露的一些額外信息,能夠看到服務器2當前角色爲追隨者,還能夠看到數據數的信息。
圖10-11還展現了服務器1的一些信息,看到,服務器1的角色爲羣首角色,同時還有一些額外信息,僅在羣首服務器中,FollowerInfo中還會展現追隨者的列表。當點擊該按鈕,會看到鏈接到服務器1的其餘ZooKeeper服務器的原始列表信息。
【圖10-11:jconsole中關於服務器1的信息】到目前爲止,看到相比四字母命令,經過JMX所看到的信息更加優美直觀,可是尚未看到有什麼新功能,如今看看JMX能夠作到而四字母命令沒法作到的功能。啓動zkCli腳本工具,鏈接到服務器1,以後運行如下命令:
create -e /me "foo"經過該命令,會建立一個臨時性的znode節點,圖10-11所示的服務器1的JMX信息中,能夠看到出現了一個關於鏈接的新信息項,鏈接的屬性中列出了各類各樣的信息,這些信息對於調試運行問題很是有用。這個視圖中,還看到兩個有意思的操做:terminateSession和terminateConnection。
terminateConnection操做會關閉ZooKeeper客戶端到服務器之間的鏈接,而會話依然處於活躍狀態,因此此時客戶端還能夠從新鏈接到另外一個服務器,客戶端會收到失去鏈接的事件,但能夠輕易恢復。
與之相反,terminateSession操做會聲明會話已經死亡,客戶端與服務器之間的鏈接將會被關閉,且會話也將因過時而停止,客戶端也不能再使用這個會話與其餘服務器創建鏈接。所以,使用terminateSession操做時須要當心,由於該操做會在會話超時以前就致使會話過時,因此在該進程本身發現過時前,其餘進程可能已經發現了該進程的會話死亡的狀況。
JMX代理器運行於ZooKeeper服務器的JVM之中,若是鏈接遠程的ZooKeeper服務器,須要配置好JMX代理器。對與遠程鏈接的JMX協議有若干參數須要配置,本節中,展現了一種JMX的配置方式,來看看JMX提供了什麼樣功能。若是在生產環境使用JMX,可能須要使用另外一種JMX配置——具體參考如何配置更高級的安全功能。
對JMX的配置能夠經過系統屬性的方式進行配置,在用於啓動ZooKeeper服務器的zkServer.sh腳本中,使用SERVER_JVMFLAGS環境變量來配置這些系統屬性。
例如,如下面的配置啓動服務,就能夠遠程鏈接服務器3的55555端口。
SERVER_JVMFLAGS="-Dcom.sun.management.jmxremote.password.file=passwd \ -Dcom.sun.management.jmxremote.port=55555 \ -Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.access.file=access" _path_to_zookeeper_/bin/zkServer.sh start _path_to_server3.cfg_系統屬性參數中用到了密碼文件和訪問控制文件,這些文件的格式很是簡單。首先,建立passwd文件,方式以下:
# user password admin <password>注意,密碼文件中的密碼信息爲明文保存,所以只能給密碼文件的全部者分配讀寫權限,若是不這樣作,Java就沒法啓動服務。同時,關閉了SSL功能,這意味着密碼信息在網絡上會以明文的方式進行傳輸,若是須要更強的安全級別,JMX也提供了更強有力的選項,但這些已經超出本書所涉及的範圍。
對於訪問控制文件,將會給admin用戶賦予readwrite權限,建立該文件的方式以下:
admin readwrite
在ZooKeeper發行包的contrib目錄中,能夠找到一些軟件,這些軟件能夠幫你集成ZooKeeper到其餘的檢測系統中去。列出了一部分最受歡迎的軟件或工具:
- 經過C綁定實現的Perl和Python語言的綁定庫。
- ZooKeeper日誌可視化的軟件。
- 一個基於網頁的集羣節點瀏覽和ZooKeeper數據修改功能的軟件。
- ZooKeeper中自帶的zktreeutil和guano都可以從GitHub下載。這些軟件能夠對ZooKeeper的數據進行導入和導出操做。
- zktop,也能夠從GitHub下載,該軟件監控ZooKeeper的負載,並提供Unix的top命令相似的輸出。
- ZooKeeper冒煙測試,能夠從GitHub上下載。該軟件對ZooKeeper集羣提供了一個簡單的冒煙測試客戶端,這個工具對於開發人員熟悉ZooKeeper很是不錯。