在過去的幾十年裏,互聯網改變了我們的生活方式。通過互聯網提供的服務通常由複雜的軟件系統支持,經常跨過地理位置分開的大量服務器。這樣的系統在計算機科學術語上被稱爲分佈式系統。爲了正確有效地運行這些大型系統,在這些系統彼此之間的進程應該有某種協議,該協議也稱爲分佈式協調。達成協議的組件構成了分佈式系統的總體目標,或者一項協議完成一些子任務,最終達成總目的。這不像聽起來那麼簡單,因爲進程不僅必須同意,而且也要確認別的同級進程是否同意。
儘管聽起來在一個大的分佈式系統中協調任務和流程很簡單,實際上當談到實現容錯的正確方式時,這是一個非常棘手的問題。ApacheZooKeeper,Apache軟件基金會的一個項目,旨在解決設計和開發分佈式系統時的這些協調問題,通過一個簡單 API 提供一組可靠原語。
在這一章,我們將討論以下主題:
什麼是分佈式系統及其特點
爲什麼分佈式系統協調很困
介紹 ApacheZooKeeper
下載和安裝 ApacheZooKeeper
使用 ZooKeeper shell 連接 ZooKeeper
多節點 ZooKeeper 集羣配置
定義一個分佈式系統
分佈式系統被定義爲一個軟件系統,由獨立的計算實體通過計算機網絡連接在一起,這些組件爲實現一個共同目標進行相互交流和協調。一個e-mail系統,例如Gmail 或Yahoo!Mail就是這樣的一個分佈式系統例子。多玩家在線遊戲,有能力的玩家處於地理分開的位置,這是另一個分佈式系統例子。
爲了確定一個分佈式系統,以下是你需要尋找的特徵:
資源共享:這是指系統使用資源的可能性,例如存儲空間、計算能力、數據,和從任何地方到來的服務,等等
可擴展性:這是指逐步擴展和改善系統的可能性,從硬件和軟件兩個角度
併發性:這是指系統由多用戶同時使用來完成相同任務或不同任務的能力
性能和可伸縮性:這可以確保系統不因爲總體負載的增加降低響應時間
容錯:這將確保系統始終可用,即使一些組件失敗或以降級模式運行
通過API 抽象:這確保系統各個組件對最終用戶隱藏,只向他們暴露最終服務
設計一個分佈式系統很難,編程集合獨立計算實體功能在一起更難。設計和開發人員常常做出一些假設,也稱爲分佈式計算謬論。這些謬論列表最初由 Sun Microsystems公司工程師在初始設計網絡文件系統(NFS)時編制,你可以參考這些:
假設 | 現實 |
網絡可靠 | 現實中,組件之間的網絡或互連可能由於系統內部錯誤或由於電源故障等外部因素而失敗 |
反應爲零 | 分佈式系統用戶可以從世界任何地方連接到它,並且也需要花費時間將數據從一個地方移動到另一個地方。網絡的服務質量也會影響應用程序的延遲 |
寬帶無限 | 在最近網絡寬帶提高了很多,但是在世界各地這並不是統一的。寬帶取決於網絡的類型(T1、LAN、WAN、移動網絡,等等) |
網絡安全 | 網絡從來不安全。對於一個在設計應用程序時不重視安全方 面的系統經常會遇到拒絕服務*** |
拓撲不變 | 現實中,拓撲從來都不是常數。隨着時間推移,組件被添加/刪除,系統應該容忍這種變化 |
擁有管理 | 分佈式系統從未在隔離功能。它們與其他外部系統交互功能;這超出了管理控制 |
傳輸代價零 | 遠非如此,到處都是成本,從建立網絡到從源到目的地發送網絡數據包。CPU週期成本以實際美元的形式支付給網絡服務提供商 |
網絡是均勻的 | 網絡由大量不同實體組成。因此,對於正確地運行一個應用程序,需要與各個組件進行互操作,網絡類型、操作系統,甚至是實現語言。 |
分佈式系統設計人員在設計系統時需要記住所有之前的點。除此之外,未來棘手的問題還有要解決多計算實體或獨立程序的參與,協調它們的動作。通常,要實現這種協調邏輯,開發人員和設計人員都會陷入困境;導致不正確和低效的系統設計。而 ApacheZooKeeper就是被設計和開發協調這種動作的,這使得一個高度可靠的分佈式協調成爲可能。
ApacheZooKeeper爲開發一個高度可伸縮、可靠、健壯的集中服務實現分佈式系統協調,開發人員可以直接通過他們應用程序使用一個非常簡單的接口,一個集中的協調服務。它使應用程序開發人員可以集中精力在他們的應用程序核心業務邏輯上,完全依賴 ZooKeeper 服務協調部分正確開始他們的應用。它簡化了應用程序開發過程,使它更加靈活。
使用 ZooKeeper,開發人員可以實現常見的分佈式協調任務,如下所示:
配置管理
命名服務
分佈式同步,如鎖和障礙
集羣成員操作,如檢測節點離開/節點加入
任何分佈式應用程序都需要這些服務這樣或那樣的方式,實現協調和同步它們從頭開始經常導致應用程序行爲不正常的錯誤。Zookeeper 減輕了需要在分佈式應用程序實現的協調和同步服務,通過一組豐富的 API 提供了簡單和優雅的原語。
爲何分佈式系統協調如此具有挑戰性
在介紹了 ApacheZooKeeper及其在設計和開發分佈式應用程序時的角色後,讓我們來更深入研究爲什麼協調在分佈式系統中是如此困難。讓我們做一個配置管理分佈式應用程序的例子,由多個同時運行的獨立軟件組件組成,跨過多個物理服務器。現在,有一個主節點(master node)集羣配置存儲,其他從節點(worker nodes)從這個主節點下載自動配置自己,看起來這似乎是一個簡單和優雅的解決方案。但是,這種解決方案會因爲主節點的一個潛在問題就變成單點故障。即便我們假設主節點有容錯設計,設計一個當配置信息變更時動態傳播給所有從節點的系統也並非易事。
分佈式系統中另一個協調問題是服務的發現。通常,爲維持負載提高應用程序的可用性,我們會給系統添加更多的物理服務器。不過,我們需要讓客戶端或從節點知道在集羣中成員的這些變化和在集羣中主機不同服務的新機器可用性。這需要客戶端本身精心的設計和實現邏輯。
可伸縮性提高可用性,但是它複雜協調。水平可伸縮的分佈式系統,跨越成千上萬臺物理服務器,經常容易出錯,如硬件故障、系統崩潰、通信鏈路故障,等等。這些類型的失敗不遵循任何模式,因此,在應用程序邏輯裏處理此類故障,和設計系統的容錯性確實是一個難題。
因此,從指出到現在,很明顯,設計一個分佈式系統並不那麼容易。製作出正確、快速、可伸縮集羣協調,是困難而且經常容易出錯,從而導致整個集羣不一致。在這裏,ApacheZooKeeper爲設計和開發分佈式系統帶來了一個健壯的協調服務。
ApacheZooKeeper 介紹
ApacheZooKeeper是 Apache軟件基金會的一個軟件項目,它爲大型分佈式系統的各種協調問題提供了一個開源解決方案。ZooKeeper最初由雅虎開發。
ZooKeeper,作爲一個集中式協調服務,運行在一個叫做 ZooKeeper服務集羣集合裏,分散並且高度可靠。分佈式同步、組管理、領導人選擇已經被服務實現,因此應用程序不需要通過自己重新發明輪子通過實現。另外,應用程序可以使用 ZooKeeper暴露的原語構建更強大的抽象來解決各種各樣的問題。我們將會在第4章“執行常見分佈式系統任務”深入研究這些概念。
ApacheZooKeeper使用 Java 編寫。附帶了 C、Java、Perl 和Python 客戶端綁定。社區也貢獻了可供其它語言使用的有效客戶端庫,例如 Go、Scala、Erlang,等等。
ApacheZooKeeper被大量組織廣泛使用,例如 Yahoo! Inc.、Twitter、Netflix 和Facebook,在它們的分佈式應用程序平臺上作爲一個協調服務。在第7章“ZooKeeper實戰”中我們將探討更多關於如何在真實世界的使用。
Apache ZooKeeper 親手實踐
在本節,我們將向你展示如何下載和安裝 ApacheZooKeeper,以便我們可以馬上開始使用ZooKeeper。本章旨在通過開發人員使用 ZooKeeper的親手實踐,爲他們的分佈式應用程序給予詳細安裝和使用說明。我們將從一個ZooKeeper單節點安裝開始,熟悉基本配置,其次學習 ZooKeeper shell。最後,你將學會如何搭建一個多節點的 ZooKeeper集羣。
下載和安裝
ZooKeeper支持多種平臺。GNU/Linux 和Oracle Solaris作爲服務端和客戶端開發和生產平臺都被支持。Windows和MacOS X 建議只作爲服務器和客戶端開發平臺。
ZooKeeper使用 Java編寫,需要Java6 或以上更高版本運行。儘管推薦使用 Oracle 版本 Java,OpenJDK也可以正常工作,正確執行 ZooKeeper功能和本書中的許多代碼示例。
可以從這裏下載 Oracle Java
http://www.oracle.com/technetwork/java/javase/downloads/index.html
ZooKeeper作爲一個 ZooKeeper服務整體感知運行。在生成集羣,三個 ZooKeeper服務器是一個整體的最小推薦數量,建議你在單獨的機器上允許它們。不過,通過在一臺單獨機器上以獨立模式安裝,你可以學習和評估 ZooKeeper。
下載
讓我們從喬治亞理工大學的Apache 鏡像下載穩定版本(http://b.gatech.edu/1xElxRb):
$ wget
http://www.gtlib.gatech.edu/pub/apache/zookeeper/stable/zookeeper-3.4.6.tar.gz
$ ls -alh zookeeper-3.4.6.tar.gz
-rw-rw-r-- 1 saurav saurav 17M Feb 20 2014zookeeper-3.4.6.tar.gz
安裝
一旦我們下載了 ZooKeepertar 包,安裝設置一個單獨的 ZooKeeper節點相當簡單明瞭。讓我們將壓縮的tar 文件提取到/usr/share:
$ tar -C/usr/share -zxf zookeeper-3.4.6.tar.gz
$ cd/usr/share/zookeeper-3.4.6/
$ ls
bin CHANGES.txt contrib docs ivy.xml LICENSE.txt
README_packaging.txt recipes zookeeper-3.4.6.jar zookeeper-3.4.6.jar.md5
build.xml conf dist-maven ivysettings.xml lib
NOTICE.txt README.txt src zookeeper-3.4.6.jar.asc
zookeeper-3.4.6.jar.sha1
在本例中,ZooKeeper壓縮文件被提取到了/usr/share/zookeeper-3.4.6,按如下方式導出 ZK_HOME:
$ exportZK_HOME=/usr/share/zookeeper-3.4.6
配置
一旦我們提取了 tar 包,下一步就是配置 ZooKeeper。conf文件夾擁有 ZooKeeper 的配置文件。 ZooKeeper 需要從 ZooKeeper 文件夾裏conf 文件夾中一個名爲zoo.cfg的配置文件。這裏有一個示例配置文件,其中包含一些供參考的配置參數。
讓我們使用下面最小參數創建我們的配置文件,並將它保存在conf文件夾裏:
$ cat conf/zoo.cfg
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
配置參數的含義解釋如下:
tickTime:以毫秒爲單位:用於會話註冊和客戶端對 ZooKeeper 服務端心跳檢測。最小會話超時是兩倍tickTime值。
dataDir:ZooKeeper 狀態內存存儲位置;包括數據庫快照和更新數據庫的事務日誌。提取 ZooKeeper文檔不會創建這個目錄,因此如果這個目錄不在系統中,你需要創建並設置可寫權限。
clientPort:這個端口監聽客戶端連接,它是ZooKeeper客戶端發起連接的地方。客戶端端口可以被設置爲任意數字,配置不同的服務端監聽不同的端口。默認端口是 2181。
在第5章“Apache ZooKeeper 管理”中我們將學習各種存儲、網絡和 ZooKeeper 集羣配置詳細參數。
如前所述,ZooKeeper需要一個 Java運行環境來工作。
運行下面命令,看看在你係統上安裝的 Java:
$ java–version
如果已經安裝Java並正確配置了路徑,根據 Java 的發行版本(Oracle 或OpenJDK),前面的命令將顯示在你係統上安裝運行的Java版本。例如,在我的系統上,我安裝了Java1.7.0.67,因此,使用前面的命令,在我的系統上將會返回以下輸出:
$ java-version
javaversion "1.7.0_67"
Java(TM)SE Runtime Environment (build 1.7.0_67-b01)
JavaHotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
ZooKeeper需要正確地設置JAVA_HOME環境變量。運行以下命令,看看你的系統是否設置:
$ echo$JAVA_HOME
在我的系統,JAVA_HOME被設置爲/usr/java/latest,因此,我得到如下輸出:
$ echo$JAVA_HOME
/usr/java/latest
啓動 ZooKeeper 服務
現在,考慮到 Java已經安裝和工作正常,讓我們繼續並開啓ZooKeeper服務。使用下面命令,所有ZooKeeper啓動/停止服務和調用 ZooKeeper命令shell的管理腳本都跟着壓縮文件被送到bin文件夾下:
$ pwd
/usr/share/zookeeper-3.4.6/bin
$ ls
README.txt zkCleanup.sh zkCli.cmd zkCli.sh zkEnv.cmd zkEnv.sh
zkServer.cmd zkServer.sh
在Unix平臺(GNU/Linux,MacOSX,等等)使用.sh 擴展腳本,對於MicrosoftWindows 操作系統使用NaNd 擴展腳本。
在GNU/Linux 系統上啓動 ZooKeeper服務,你需要按照下面執行zkServer.sh腳本。這個腳本給出了一個啓動、停止、重啓,和查看 ZooKeeper 服務狀態的操作:
$./zkServer.sh
JMX enabledby default
Usingconfig: /usr/share/zookeeper-3.4.6/bin/../conf/zoo.cfg
Usage:./zkServer.sh
{start|start-foreground|stop|restart|status|upgrade|print-cmd}
爲避免到 ZooKeeper安裝目錄運行這些腳本,你可以使用如下命令將它設置到你的PATH變量:
exportPATH=$PATH:/usr/share/zookeeper-3.4.6/bin
使用start 參數執行zkServer.sh啓動 ZooKeeper服務。成功啓動的服務將顯示下面輸出:
$ zkServer.sh start
JMX enabled by default
Using config: /usr/share/zookeeper-3.4.6/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
你可以使用 ps 命令,檢查ZooKeeper服務是否已經開啓:
$ ps –ef| grep zookeeper | grep –v grep | awk '{print $2}'
5511
如果你的系統安裝了jps命令,你可以使用如下命令檢查 ZooKeeper 服務的啓動:
$ which jps
jps is /usr/bin/jps
$ jps
5511 QuorumPeerMain
5565 Jps
ZooKeeper進程被列爲QuorumPeerMain。在這種情況下,作爲jps 的報道,ZooKeeper服務運行在與進程 ID 5511相匹配的 ps 命令報道。
如下所示,可以通過zkServer.sh 腳本檢查ZooKeeper服務的狀態:
$zkServer.sh status
JMXenabled by default
Usingconfig: /usr/share/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode:standalone
你可以爲同樣的腳本使用 stop 參數,停止服務進程:
$zkServer.sh stop
JMXenabled by default
Usingconfig: /usr/share/zookeeper-3.4.6/bin/../conf/zoo.cfg
Stoppingzookeeper ... STOPPED
當ZooKeeper已經停止或不運行時檢查狀態將顯示如下結果:
$zkServer.sh status
JMXenabled by default
Usingconfig: /usr/share/zookeeper-3.4.6/bin/../conf/zoo.cfg
Errorcontacting service. It is probably not running.
一旦我們ZooKeeper實例已經運行,接下來要做的就是連接它。ZooKeeper附帶一個默認的基於Java 命令行shell連接到一個 ZooKeeper實例。這裏也有一個 C客戶端,我們將在後面的小節討論。
用基於 Javashell 連接到ZooKeeper
開啓基於 Java 的ZooKeeper命令行shell,如下,我們僅僅只需使用服務 ID 和端口運行ZK_HOME/bin 文件夾的 zkCli.sh:
${ZK_HOME}/bin/zkCli.sh–server zk_server:port
在我們的例子中,我們已經在同一臺機器上運行了我們的ZooKeeper服務,所以 ZooKeeper服務是localhost,或回送地址是127.0.0.1。我們配置的默認端口是2181:
$zkCli.sh -server localhost:2181
連接上運行的 ZooKeeper實例,我們將在終端上看到類似如下的輸出(省略一些輸出):
Connectingto localhost:2181
...............
............... Welcome
to ZooKeeper! JLine
support is enabled
...............
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk:localhost:2181(CONNECTED) 0]
看看 ZooKeeperJavashell 支持的命令清單,你可以在 shell 終端運行help命令:
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
connect host:port
get path [watch]
ls path [watch]
set path data [version]
rmr path
delquota[-n|-b] path
quit
printwatches on|off
create [-s][-e] path data acl
stat path [watch]
close
ls2 path [watch]
history
listquota path
setAcl path acl
getAcl path
sync path
redo cmdno
addauth scheme auth
delete path [version]
setquota -n|-b val path
我們可以通過命令行接口執行一些簡單的命令。讓我們開始運行ls命令,在 Unix,使用清單如下:
[zk: localhost:2181(CONNECTED) 1] ls / [zookeeper]
現在,ls命令返回一個叫做zookeeper 的字符串,它是 ZooKeeper 的專用術語znode。注意,我們將會在下一章,第2章瞭解“ApacheZooKeeper內部工作原理”介紹ZooKeeper數據模型。如下,我們可以通過ZooKeepershell 創建一個 znode:
首先,讓我們創建一個HelloWorld空數據 znode:
[zk: localhost:2181(CONNECTED) 2] create /HelloWorld""
Created /HelloWorld
[zk: localhost:2181(CONNECTED) 3] ls / [zookeeper,HelloWorld]
如下,我們使用delete 命令可以刪除創建的 znode:
[zk:localhost:2181(CONNECTED) 4] delete /HelloWorld
[zk: localhost:2181(CONNECTED) 5] ls /
[zookeeper]
在之後章節,這裏顯示的操作將更清晰我們瞭解的關於 ZooKeeper 架構、數據模型,命名空間和內部結構的知識。讓我們看看基於 C語言的 ZooKeeper 命令行shell。
用基於 C shell 連接到ZooKeeper
ZooKeeper附帶了一個基於 C語言的命令行shell。但是,要使用這個 shell,我們需要在${ZK_HOME}/src/c. AGNU/GCC命令裏構建 C來源。要構建它們,只需在前面的忙碌運行三個命令:
$./configure
$ make
$ makeinstall
默認情況下,C客戶端庫安裝在/usr/local/lib。C客戶端庫能夠構建單線程和多線程庫。單線程庫以_st 爲後綴,而多線程庫以_mt爲後綴。
基於 C 的ZooKeepershell使用這些庫來執行。這樣,前面的構建完成後,叫做cli_st和cli_mt的兩個可執行檔在當前文件夾生成。這兩個二進制文件分別是單線程和多線程命令行 shell。當cli_mtis運行時,我們會得到以下輸出:
$ cli_mt
USAGEcli_mt zookeeper_host_list
[clientid_file|cmd:(ls|ls2|create|od|...)]
Version:ZooKeeper cli (c client) version 3.4.6
使用基於 Cshell連接到ZooKeeper服務實例,在你的終端執行下面的命令:
$ cli_mtlocalhost:2181
Watcher SESSION_EVENT state = CONNECTED_STATE
Got a newsession id: 0x148b540cc4d0004
基於CZooKeepershell還支持多個命令,比如 Java版本。執行help 命令,讓我們看看下面的可用命令:
help
create[+[e|s]] <path>
delete<path>
set<path> <data>
get <path>
ls <path>
ls2 <path>
sync<path>
exists <path>
wexists <path>
myid
verbose
addauth <id> <scheme>
quit
prefix the command with the character 'a' to run the command
asynchronously.run the 'verbose' command to toggle verbose logging.
i.e.'aget /foo' to get /foo asynchronously
我們可以發出相同的一組命令列出 znode,創建一個 znode,最後刪除它:
ls /
time = 3msec
/: rc = 0
zookeeper
time = 5 msec
create /HelloWorld
Creating[/HelloWorld] node
Watcher CHILD_EVENT state = CONNECTED_STATE for path /
[/HelloWorld]: rc = 0
name = /HelloWorld
ls /
time = 3msec
/: rc = 0
zookeeper
HelloWorld time = 3 msec
delete/HelloWorld
Watcher CHILD_EVENT state = CONNECTED_STATE for path /
ls /
time = 3 msec
/: rc = 0
zookeeper
time = 3msec
基於 CZooKeepershell格式化輸出顯示命令執行的時間以及返回代碼(rc)。返回代碼爲零,表示命令成功執行。
我們之前構建和安裝在/usr/local/ lib的C靜態和共享庫是必需的,可以用ZooKeeperC 編程語言爲分佈式應用程序 ZooKeeper 編程。Perl 和Python 客戶端也附帶分發在 ZooKeeper 的這個基於 C 接口上。
建立多節點ZooKeeper 集羣
到目前爲止,我們已經建立了一個單機模式的 ZooKeeper服務實例。一個單機實例是一個潛在的單點故障。如果 ZooKeeper服務失效,我們使用這個實例的整個分佈式協調應用程序都將失效,停止運轉。因此,以單機模式運行 ZooKeeper是不適合生產的,但是爲了開發和評估,這個服務也是需要的。
在生產環境中,ZooKeeper 應該以複製模式運行在多個服務器上,也叫 ZooKeeper 集合。推薦最小的服務器數量是 3,在生產環境中 5 臺服務器是最常見的。複製的服務器在同一個應用程序域中稱爲仲裁(quorum)。在這種模式下,ZooKeeper服務實例運行在多個不同機器上,仲裁中的所有的服務都有相同的配置文件的副本。在一個仲裁中,ZooKeeper實例運行在一個羣首/追隨模式下。其中一個實例是民選領袖,其他人成爲追隨者。如果羣首失效,發生新羣首選舉,另一個正在運行的實例成爲羣首。不過,這些複雜性對於使用ZooKeeper的應用程序和開發人員卻完全是隱藏的。
羣集模式下 ZooKeeper 配置文件與我們使用的單機模式是一樣的,除了少數幾條。這裏顯示了一個示例配置文件:
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
initLimit=5 syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
解釋一下這裏的兩個配置參數:
initLimit:這是追隨者最初連接羣首超時值,單位爲 tick 值倍數
syncLimit:追隨者與羣首進行 sync 操作時的超時值,單位爲 tick 值倍數
這兩個單位中指定超時時間爲tickTime。因此,在我們的示例中,initLimit 的超時時間是5 倍2000毫秒,或者是 10秒。
前面示例中其他三個實體以server.id=host:port:port 格式的服務器列表構成法定人數。.id 標識符是一個數字,用於仲裁中服務器的主機名。在我們是示例配置中,zoo1仲裁成員分配到的標識符是1。
標識符是需要在服務器一個名爲myid的數據據文件夾指明的。很重要,myid 文件應該有一個只包含服務 ID 文字(ASCII)的單行文本。ID 必須在集羣中唯一,同時值在 1 到255 之間。
再次,我們有了兩個端口好之後,每臺服務主機就成爲:2888和3888。這裏有關於它們的說明:
第一個端口,2888,主要用於集羣中點對點通信,如追隨者連接到領導者。追隨者使用這個端口打開一個 TCP 到領導者的連接
第二個端口,3888,用於羣首選舉,防止仲裁出現新羣首。所有通信通過TCP,第二個端口需要響應仲裁內部羣首選舉。
啓動服務器實例
爲仲裁中的每個服務配置文件後,我們需要啓動 ZooKeeper服務實例。這個過程與單機模式是一樣的。執行下面命令行,我們必須連接到每一臺機器:
${ZK_HOME}/bin/zkServer.shstart
一旦實例啓動成功,我們將執行下面命令檢查每臺機器實例狀態:
${ZK_HOME}/bin/zkServer.shstatus
例如,看看下一個法定人:
[zoo1] #${ZK_HOME}/bin/zkServer.sh status
JMXenabled by default
Usingconfig: /usr/share/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode:follower
[zoo2] #${ZK_HOME}/bin/zkServer.sh status
JMXenabled by default
Usingconfig: /usr/share/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode:leader
[zoo3] #${ZK_HOME}/bin/zkServer.sh status
JMXenabled by default
Usingconfig: /usr/share/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode:follower
如前所述,zoo2是集羣羣首,zoo1和zoo3是追隨者。通過命令行shell 連接到 ZooKeeper集羣也和單機模式相同,除了我們現在以一個連接字符串 host1:port2, host2:port2 … 格式指定的到服務端${ZK_HOME}/bin/zkCli.sh參數:
$zkCli.sh -server zoo1:2181,zoo2:2181,zoo3:2181
Connectingto zoo1:2181, zoo2:2181, zoo3:2181
… … … …
Welcometo ZooKeeper!
… … … …
[zk:zoo1:2181,zoo2:2181,zoo3:2181 (CONNECTED) 0]
一旦 ZooKeeper集羣建立和運行起來,有兩種方式來監控它,一種是使用 Java 管理擴展(JMX)通過客戶端端口發送一些命令,也稱爲四字單詞(Four Letter Words)。第5章“Apache ZooKeeper管理”中我們將探討有關ZooKeeper監控更多細節。
運行 ZooKeeper 多節點模式
在單機下運行 ZooKeeper多節點模式也是可能的。這是用於測試目的的。多節點模式在同一臺機器上運行,我們需要調整配置;例如,我們可以將服務器名稱設置爲localhost同時指定唯一仲裁和羣首選舉端口。
讓我們使用下面配置文件設置單臺機器上多節點 ZooKeeper 集羣:
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/var/lib/zookeeper
clientPort=2181
server.1=localhost:2666:3666
server.2=localhost:2667:3667 server.3=localhost:2668:3668
前面的小節中已經解釋過,每一個服務實體 X 代表 XZooKeeper 服務上的地址和端口。第一個字段是服務 X主機名或 IP 地址,第二個和第三個字段分別是仲裁連接和羣首選舉的 TCP 端口。由於我們在同一臺機器上啓動三個 ZooKeeper服務實例,我們需要爲每一個服務實體使用不同的端口號。
當我們在同一臺機器上運行不止一個ZooKeeper服務進程時,我們需要爲每一個實例配置不同的客戶端端口。
最後但並非最不重要,我們必須爲我們正在運行的每個實例自定義dataDir參數。
將這些放在一起,一個集羣中有 ZooKeeper集羣中有 3 個實例,我們將創建 3 個不同配置文件。我們調用這些zoo1.cfg,zoo2.cfg,和zoo3.cfg,並且把它們保存在${ZK_HOME}的conf文件夾。我們將創建 3 個不同實例的數據文件夾,叫做zoo1,zoo2,和zoo3,在/var/lib/zookeeper。至此,三個配置文件如下所示:
這裏,你將看到第一個實例的配置文件:
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/var/lib/zookeeper/zoo1
clientPort=2181
server.1=localhost:2666:3666 server.2=localhost:2667:3667
server.3=localhost:2668:3668
第二個配置文件在這裏:
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/var/lib/zookeeper/zoo2
clientPort=2182
server.1=localhost:2666:3666 server.2=localhost:2667:3667
server.3=localhost:2668:3668
最後一個實例第三個配置文件在這裏:
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/var/lib/zookeeper/zoo3
clientPort=2183
server.1=localhost:2666:3666 server.2=localhost:2667:3667
server.3=localhost:2668:3668
我們還需要解決 myid 文件中服務器實例 ID 參數正確問題。可以使用如下三個命令:
$ echo 1> /var/lib/zookeeper/zoo1/myid
$ echo 2> /var/lib/zookeeper/zoo2/myid
$ echo 3> /var/lib/zookeeper/zoo3/myid
現在,我們已經準備就緒啓動 ZooKeeper實例。如下,讓我們啓動實例:
$ ${ZK_HOME}/bin/zkServer.shstart ${ZK_HOME}/conf/zoo1.cfg
$${ZK_HOME}/bin/zkServer.sh start ${ZK_HOME}/conf/zoo2.cfg
$${ZK_HOME}/bin/zkServer.sh start ${ZK_HOME}/conf/zoo3.cfg
一旦所有實例啓動,我們可以使用zkCli.sh腳本連接到多節點 ZooKeeper集羣,像我們之前那樣:
$${ZK_HOME}/bin/zkCli.sh –server \
localhost:2181, localhost:2182, localhost:2183
看!在一臺機器 ZooKeeper集羣上我們運行有三個節點!
小結
在這一章中,你瞭解了一般分佈式系統的定義和爲什麼組成一個大型系統之間的實體協調如此困難,還有這是一個需要被解決的非常重要問題。你學習了 ApacheZooKeeper對於分佈式系統設計和開發人員如何是一個很好的解決協調問題的工具。本章提供在不同模式下安裝和配置一個 ZooKeeper 的細節,如單機、集羣,同時也談到了如何用 ZooKeepershell從命令行連接到一個 ZooKeeper服務。
在下一章,你將瞭解到 Apache ZooKeeper 的內部和架構,你將詳細瞭解 ZooKeeper數據模型和由 ZooKeeper服務暴露的 API 接口。下一章中介紹的概念將幫助你掌握 ZooKeeper的設計語義,增加讀者在他們的分佈式應用程序中使用配置使用 ZooKeeper信心。
注:本文翻譯自《Apache ZooKeeper Essentials》(Packt 出版有限公司,2015年1月)第1章
轉載請註明出處