一背景
zookeeper是一個開源的分布式應用程序協調服務,是Apache Hadoop 的一個子項目。它是一個為分布式應用提供一致性服務的軟件,提供的功能包括:配置維護、名字服務、分布式同步、組服務等。其原理是基於google發表的《The Chubby lock service for loosely-coupled distributed systems》論文。網上關於zookeeper的博客也很多,但很多講的不細致,如如何測試部署成功。在學習別人的博客進行部署的過程中遇到了一些問題。所以寫這篇博客主要是總結zookeeper的部署方法及在這過程中遇到的問題,提供更加詳細的部署方案,希望能為其他初學者提供一些參考。
二所需環境和包
1. JDK 環境:
java JDK包可以到官網下載(這里提供所有版本的JDK下載地址:http://www.oracle.com/technetwork/java/archive-139210.html)
JDK安裝可參考:
tar.gz方式:http://blog.csdn.net/zhangxh1013/article/details/7320860
rpm方式: http://alan-hjkl.iteye.com/blog/1527179
JDK 環境是必須的,zookeeper是用java開發的,所以需要在JDK環境下運行。所以建議首先安裝JDK,本人就是因為以為自己電腦上已經安裝JDK,就直接部署zookeeper,在測試時並不成功,結果各種排錯。
2. zookeeper 包:
下載地址:http://www.apache.org/dyn/closer.cgi/zookeeper/
三單機部署
1.創建工作目錄
mkdir /usr/lib/zookeeper
- 1
2.創建data,logs文件
data :下存放節點ID
logs:用於下存放相關日志文件
mkdir/usr/lib/zookeeper/data
mkdir/usr/lib/zookeeper/logs
- 1
- 2
3.解壓zookeeper到工作目錄下
下載zookeeper的安裝包之后, 解壓到工作目錄下(本文解壓到/usr/lib/zookeeper).
tar -zxvf zookeeper-3.4.6.tar.gz/usr/lib/zookeeper
- 1
4.創建zoo.cfg
進入zookeeper目錄下的conf子目錄, 復制zoo_sample.cfg 並命名為zoo.cfg。
zookeeper服務器啟動默認加載zoo.cfg文件,當然也可以命名為其他文件,但是在運行是需要指定cfg文件名。如命名為zk1.cfg時,啟動zookeeper命令為:./zkServer.sh start zk1.cfg 。如果是zoo.cfg 啟動時命令為:./zkServer.sh start
打開zoo.cfg 並修改相關配置
sudovi /usr/lib/zookeeper/zookeeper-3.4.6/conf/zoo.cfg
- 1
設置配置文件中的相關參數:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/lib/zookeeper/data
dataLogDir=/usr/lib/zookeeper/logs
clientPort=2181
參數說明:
- tickTime: zookeeper中使用的基本時間單位, 毫秒值
- initLimit: Follower在啟動過程中,會從Leader同步所有最新數據,然后確定自己能夠對外服務的起始狀態。Leader允許Follower在initLimit時間內完成這個工作
- syncLimit:在運行過程中,Leader負責與ZK集群中所有機器進行通信,如果L發出心跳包在syncLimit之后,還沒有從F那里收到響應,那么就認為這個F已經不在線了。
- dataDir: 數據目錄. 可以是任意目錄.本文制定/usr/lib/zookeeper/data
- dataLogDir: log目錄, 同樣可以是任意目錄. 如果沒有設置該參數, 將使用和dataDir相同的設置.
- clientPort: 監聽client連接的端口號
更多參數信息參考:http://www.cnblogs.com/ggjucheng/p/3352591.html
在某些博客中還會涉及設置環境變量這一步。
在/etc/profile 文件中加入如下的內容:
#Set ZooKeeper Enviroment
exportZOOKEEPER_HOME=/usr/lib/zookeeper/zookeeper-3.4.6/
exportPATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf
但我經過嘗試后發現,其實並不需要進行環境的設置就可以部署成功。單機部署就到此完成了,接下來就是驗證下是否部署成功了。
五測試
這一步就是檢驗之前所部署的zookeeper是否能夠成功運行。
1.啟動服務:
首先進入到zookeeper-3.4.6的bin文件夾下,再啟動zkServer.sh
cd/usr/lib/zookeeper/zookeeper-3.4.6/bin
./zkServer.sh start
或
/usr/lib/zookeeper/zookeeper-3.4.6/bin/zkServer.shstart
運行結果:
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkServer.sh start
JMXenabled by default
Usingconfig:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
Startingzookeeper ... STARTED.
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin#
這里需要注意的是啟動時命令為./zkServer.sh start。如果是啟動zkServer.sh start的話會報錯找不到命令錯誤。這點初學者需要小心。
2.檢查運行狀態
通過./zkServer.sh status來檢查服務器運行狀態
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkServer.sh status
JMXenabled by default
Usingconfig:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode:standalone
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin#
Mode:standalone 表明當前是單機模式,也表明部署成功。如果出現下面的情況說明部署不成功:
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkServer.sh status
JMXenabled by default
Usingconfig:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
Errorcontacting service. Itis probablynotrunning.
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin#
如果出現這種情況檢查以下幾個方面:
1.JDK環境是否搭建好
2.檢查zoo.cfg中的dataDir,dataLogDir路徑是否有錯誤
3.啟動客戶端
如果確認沒錯的話,便可啟動客戶端進行交互測試。
運行bin下的zkCli.sh 文件,
具體指令:./zkCli.sh -server localhost:2181
localhost 表示指向本地地址(服務器地址)
2181 即是在配置文件zoo.cfg 中設置的clientPort端口號
意思是要建立與地址為localhost,端口號為2181的服務進行通信。如果運行該指令顯示的結果如下,說明以及鏈接成功(即光標停止不動或最后一行顯示[zk: localhost:2181(CONNECTED) 0] )
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkCli.sh -server localhost:2181
Connecting tolocalhost:2181
2015-08-0709:39:06,957[myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.6-1569965, built on02/20/201409:09GMT
2015-08-0709:39:06,961[myid:] - INFO [main:Environment@100] - Client environment:host.name=jaylon
2015-08-0709:39:06,961[myid:] - INFO [main:Environment@100] - Client environment:java.version=1.7.0_80
2015-08-0709:39:06,965[myid:] - INFO [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2015-08-0709:39:06,965[myid:] - INFO [main:Environment@100] - Client environment:java.home=/usr/java/jdk1.7.0_80/jre
2015-08-0709:39:06,965[myid:] - INFO [main:Environment@100] - Client environment:java.class.path=/usr/lib/zookeeper/zookeeper-3.4.6/bin/../build/classes:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../build/lib/*.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/slf4j-log4j12-1.6.1.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/slf4j-api-1.6.1.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/netty-3.7.0.Final.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/log4j-1.2.16.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/jline-0.9.94.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../zookeeper-3.4.6.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../src/java/lib/*.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf:
2015-08-0709:39:06,966[myid:] - INFO [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/i386:/lib:/usr/lib
2015-08-0709:39:06,966[myid:] - INFO [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2015-08-0709:39:06,966[myid:] - INFO [main:Environment@100] - Client environment:java.compiler=<NA>
2015-08-0709:39:06,967[myid:] - INFO [main:Environment@100] - Client environment:os.name=Linux
2015-08-0709:39:06,967[myid:] - INFO [main:Environment@100] - Client environment:os.arch=i386
2015-08-0709:39:06,967[myid:] - INFO [main:Environment@100] - Client environment:os.version=3.13.0-32-generic
2015-08-0709:39:06,968[myid:] - INFO [main:Environment@100] - Client environment:user.name=root
2015-08-0709:39:06,968[myid:] - INFO [main:Environment@100] - Client environment:user.home=/root
2015-08-0709:39:06,968[myid:] - INFO [main:Environment@100] - Client environment:user.dir=/usr/lib/zookeeper/zookeeper-3.4.6/bin
2015-08-0709:39:06,972[myid:] - INFO [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181sessionTimeout=30000watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@e01430
Welcome toZooKeeper!
2015-08-0709:39:07,015[myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@975] - Opening socket connection toserver localhost/127.0.0.1:2181.Will notattempt toauthenticate usingSASL (unknown error)
JLine support isenabled
2015-08-0709:39:07,034[myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@852] - Socket connection established tolocalhost/127.0.0.1:2181, initiating session
[zk: localhost:2181(CONNECTING)0] 2015-08-0709:39:07,065[myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1235] - Session establishment complete onserver localhost/127.0.0.1:2181, sessionid = 0x14f05cde0f10001, negotiated timeout = 30000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
4 進行通信
現在進行客戶端與服務端的通信,該步在3步基礎上進行。在命令行輸入help 會顯示一些常用的通信指令:
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
connect host:port
getpath [watch]
ls path [watch]
setpath 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
[zk: localhost:2181(CONNECTED) 1]
查看文件列表:
[zk: localhost:2181(CONNECTED) 1] ls/
[zookeeper]
新建文件:
[zk: localhost:2181(CONNECTED) 4] create/node node
Created /node
獲取文件:
[zk: localhost:2181(CONNECTED) 5] get /node
node
cZxid= 0x100000008
ctime= Fri Aug 07 09:51:40 CST 2015
mZxid= 0x100000008
mtime= Fri Aug 07 09:51:40 CST 2015
pZxid= 0x100000008
cversion= 0
dataVersion= 0
aclVersion= 0
ephemeralOwner= 0x0
dataLength= 4
numChildren= 0
其他操作可以查看help。到這里已經完成了單機下的部署與測試了。接下就是要關閉服務。
5.關閉服務
操作完成記得關閉服務,不然端口一直被占用。在沒有關閉服務的情況下再重啟開啟則會顯示該服務正在運行。關閉代碼如下:
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkServer.sh stop
JMXenabled by default
Usingconfig:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
Stoppingzookeeper ... STOPPED
四偽集群模式部署
簡單的說偽集群是指在單台機器中啟動多個zookeeper進程, 並組成一個集群來模擬多台機器上的集群操作. 本文以啟動3個zookeeper進程(節點)為例.
節點個數最好是奇數個,zookeeper集群是以宕機個數過半才會讓整個集群宕機的,所以奇數個集群更佳。你可以設置3,5,7 個,原理上說節點越多越穩定。
1.創建虛擬節點
在本地建立三個節點,即三個文件夾來存放不同的節點配置
mkdir /usr/lib/zk/
mkdir /usr/lib/zk/server1
mkdir /usr/lib/zk/server2
mkdir /usr/lib/zk/server3
並在每個節點文件夾下建立data,logs文件夾,類似單機模式。將zookeeper軟件包分別解壓到三文件夾下(server1,server2,server3)。和單模式下一樣,在每個節點的zookeeper-3.4.6/conf下創建zoo.cfg 。做法與單機模式一樣。
2.配置不同節點的zoo.cfg
現在有3個節點,有三個配置文件(zoo.cfg)。所以需要對三個配置文件分別進行配置。
節點1
/usr/lib/zk/server1/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/lib/zk/server1/data #注意這邊路勁的不同
dataLogDir=/usr/lib/zk/server1/logs #注意這邊路勁的不同
clientPort=2181 #端口號每個節點不同
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
與單機模式不同的是底下加入了三行配置:
server.服務號=服務地址:服務端口:通信端口
- 1
服務號:為每個節點分配對應的id
服務地址:服務所在地址,因為現在用的是單機所以地址都是本地
服務端口:和clientPort端口是不同的
在設置過程中服務端口和通信端口應該不同,每個節點的服務端口和通信端口也不同,以防止端口沖突。
其他文件節點zoo.cfg配置基本一樣,不同的在於dataDir,dataLogDir和clientPort
節點2
/usr/lib/zk/server2/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/lib/zk/server2/data #注意這邊路勁的不同server2
dataLogDir=/usr/lib/zk/server2/logs #注意這邊路勁的不同server2
clientPort=2182 #端口號每個節點不同2182
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
節點3
/usr/lib/zk/server3/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/lib/zk/server3/data #注意這邊路勁的不同server3
dataLogDir=/usr/lib/zk/server3/logs #注意這邊路勁的不同server3
clientPort=2183 #端口號每個節點不同2183
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
3.配置不同節點上的myid
在每個節點的data文件夾下分別創建myid文件(沒有后綴)。並在每個myid文件里只寫上該節點的id如:
server1/data/myid 里寫1
server2/data/myid 里寫2
server3/data/myid 里寫3
4.啟動
與單機模式不同,集群模式需要同時啟動所有節點上的服務
建議在/root 下建立一個start.sh 文件到時只需要啟動該文件則可以將三個服務同時啟動,則不用分別進入每個文件夾下啟動zkServer.sh 。
start.sh 文件內容如下:
/usr/lib/zk/server1/zookeeper-3.4.6/bin/zkServer.shstart
/usr/lib/zk/server2/zookeeper-3.4.6/bin/zkServer.shstart
/usr/lib/zk/server3/zookeeper-3.4.6/bin/zkServer.shstart
啟動服務:
root@jaylon:~# gedit start.sh
root@jaylon:~# ./start.sh
JMX enabled by default
Using config: /usr/lib/zk/server1/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ...STARTED
JMX enabled by default
Using config: /usr/lib/zk/server2/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ...STARTED
JMX enabled by default
Using config: /usr/lib/zk/server3/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ...STARTED
5.測試
檢查服務是否正常啟動。我們可以寫一個指令文件status.sh 內容如下(和start.sh 不同的在於將start改成status):
/usr/lib/zk/server1/zookeeper-3.4.6/bin/zkServer.sh status
/usr/lib/zk/server2/zookeeper-3.4.6/bin/zkServer.sh status
/usr/lib/zk/server3/zookeeper-3.4.6/bin/zkServer.sh status
啟動檢查:
root@jaylon-Lenovo-G460:~# ./status.sh
JMX enabled bydefault
Usingconfig: /usr/lib/zk/server1/zookeeper/bin/../conf/zoo.cfg
Mode: leader
JMX enabled bydefault
Usingconfig: /usr/lib/zk/server2/zookeeper/bin/../conf/zoo.cfg
Mode: follower
JMX enabled bydefault
Usingconfig: /usr/lib/zk/server3/zookeeper/bin/../conf/zoo.cfg
Mode: follower
從mode中可以看到每個節點的狀態。節點1 是leader 其他兩個節點是follower。
ZooKeeper需要在所有的服務(可以理解為服務器)中選舉出一個Leader,然后讓這個Leader來負責管理集群。此時,集群中的其它服務器則成為此Leader的Follower。並且,當Leader故障的時候,需要ZooKeeper能夠快速地在Follower中選舉出下一個Leader
6.通信
從任意節點下啟動一個客戶端鏈接任意節點的服務端口。
如啟動節點3的客戶端鏈接節點2的服務:
cd/usr/lib/zk/server3/zookeeper-3.4.6/bin
./zkCli.sh -server localhost:2182
鏈接成功后的通信與鏈接失敗的問題解決也可以參考單機模式。
7.關閉服務
root@jaylon:/usr/lib/zk/server1/zookeeper-3.4.6/bin/zkServer.sh stop
root@jaylon:/usr/lib/zk/server2/zookeeper-3.4.6/bin/zkServer.sh stop
root@jaylon:/usr/lib/zk/server3/zookeeper-3.4.6/bin/zkServer.sh stop
四問題總結
安裝過程中常遇到的問題就是部署完如何檢驗部署成功,這也是很多博文沒有提供的。另外就是部署不成功,問題如何解決。以下總結自己遇到的問題,及覺得容易忽略的問題:
- JDK沒有安裝好就啟動了zookeeper服務
- 配置文件zoo.cfg 中的路徑寫錯了,與具體文件沒對應上
- 每個節點的clientPort 設置相同了
- 每個節點的myid文件的內容是否和對應節點id一樣
- zoo.cfg 的服務端口和通信端口設置是否正確,端口是否被占用
五參考資料
http://coolxing.iteye.com/blog/1871009
http://blog.chinaunix.net/uid-20498361-id-3184380.html
http://blog.csdn.net/cuiran/article/details/8509429