1.zookeeper安装(单机环境)
1.1下载zookeeper的安装包
http://apache.fayea.com/zookeeper/stable/zookeeper-3.4.10.tar.gz
1.2 用SecureCRT 上传文件
- Alt+p 进入sftp
- lpwd 查看硬盘共享文件目录
- lcd 修改硬盘共享文件目录
- put 上传文件
sftp> lpwd D:/Worke Software/SecureCRT/SecureCRT sftp> lcd E:/ sftp> lpwd E:/ sftp> put zookeeper-3.4.10.tar.gz
1.3解压zookeeper
tar -zxvf zookeeper-3.4.10.tar.gz
1.4复制修改配置文件
cd到zookeeper-3.4.10/conf 目录下,copy一份zoo.cfg
cp zoo_sample.cfg zoo.cfg
1.5启动zookeeper
- cd到zookeeper-3.4.10/bin目录下:
- sh zkServer.sh start 启动
- sh zkServer.sh stop 关闭
- sh zkServer.sh restart 重启
- sh zkServer.sh status 查看当前服务状态
- tail -f zookeeper.out 查看日志
- sh zkCli.sh 打开zookeeper客户端(进行节点维护)
2..zookeeper安装(集群环境)
本文用的是三台虚拟服务器:ip分别为192.168.255.128;192.168.255.129;192.168.255.130.三台服务器的配置方法相同1.zookeeper安装(单机环境),之后的配置也相同如下:
2.1 配置三台服务器的zoo.cfg文件(在文件后加)
server.1=192.168.255.128:2888:3888
server.2=192.168.255.129:2888:3888
server.3=192.168.255.130:2888:3888
解释:server.id=ip:port:port
id的取值范围: 1~255; 用id来标识该机器在集群中的机器序号
ip:三台服务器的ip
2888是zookeeper的端口;
3888表示leader选举的端口
2.2配置myid(服务器对应的id)
在根目录tmp目录下建立zookeeper文件夹 在zookeeper文件夹下创建myid文件
vi myid 并且写入1
解释:写入的1是上配置zoo.cfg对应的id所以
192.168.255.128服务器配置 vi myid 并且写入1
192.168.255.129服务器配置 vi myid 并且写入2
2.3关闭防火墙192.168.255.130服务器配置 vi myid 并且写入3
centos6.0
查看防火墙状态:service iptables status
关闭防火墙:chkconfig iptables off #开机不启动防火墙服务
centos7.0
(默认是使用firewall作为防火墙,如若未改为iptables防火墙,使用以下命令查看和关闭防火墙)
查看防火墙状态:firewall-cmd --state
关闭防火墙:systemctl stop firewalld.service
3.配置文件讲解2.4分配启动服务
# The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit=10 # The number of ticks that can pass between # sending a request and getting an acknowledgement syncLimit=5 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. dataDir=/tmp/zookeeper # the port at which the clients will connect clientPort=2181 # the maximum number of client connections. # increase this if you need to handle more clients #maxClientCnxns=60 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance # # The number of snapshots to retain in dataDir #autopurge.snapRetainCount=3
-
- tickTime=2000 zookeeper中最小的时间单位长度 (ms)
- initLimit=10 follower节点启动后与leader节点完成数据同步的时间
- syncLimit=5 leader节点和follower节点进行心跳检测的最大延时时间
- dataDir=/tmp/zookeeper 表示zookeeper服务器存储快照文件的目录
- dataLogDir 表示配置 zookeeper事务日志的存储路径,默认指定在dataDir目录下
- clientPort 表示客户端和服务端建立连接的端口号: 2181
4.客户端脚本
a.执行命令
sh zkCli.sh
b.输出如下信息表示成功链接
WatchedEventstate:SyncConnected type:None path:null
[zk:localhost:2181(CONNECTED) 0]
c.链接指定的zookeeper服务请可以用如下命令
sh zkCli.sh –server ip:port
4. 1 zookeeper的命令操作
ZooKeeper -server host:port cmd args stat path [watch] set path data [version] ls path [watch] delquota [-n|-b] path ls2 path [watch] setAcl path acl setquota -n|-b val path history redo cmdno printwatches on|off delete path [version] sync path listquota path rmr path get path [watch] create [-s] [-e] path data acl addauth scheme auth quit getAcl path close connect host:port
注意:因为zookeeper没有cd命令,这里的path指的是节点的全路径,
1.新增(create)
create [-s] [-e] path dataacl
-s 表示节点是否有序
-e 表示是否为临时节点
默认情况下,是持久化节点
2.删除(delete)
delete path [version]
注意:删除父节点一定要先删除子节点
3.修改(set)
set path data [version]
修改节点 path对应的data
注意:修改后stat中的版本信息会改变
4.查看(ls和get)
ls path [watch]
注意zookeeper没有cd命令所以需要查看子目录需要子目录的全路径 ls /father/son
get path [watch]
获得指定 path的信息
4.2 stat信息(zookeeper维护节点的数据结构)
[zk: localhost:2181(CONNECTED) 18] stat /father cZxid = 0x100000018 节点被创建时的事务ID ctime = Mon Jun 04 17:50:32 CST 2018 mZxid = 0x100000018 节点最后一次被更新的事务ID mtime = Mon Jun 04 17:50:32 CST 2018 pZxid = 0x400000005 当前节点下的子节点最后一次被修改时的事务ID cversion = 1 子节点的版本号 dataVersion = 0表示的是当前节点数据的版本号 aclVersion = 0 表示acl的版本号,修改节点权限 ephemeralOwner = 0x0创建临时节点的时候,会有一个sessionId 。 该值存储的就是这个sessionid dataLength = 3 数据值长度 numChildren = 1 子节点数
5.java API的使用
5.1导入jar包
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.8</version> </dependency>
5.2用java api实现zookeeper的基本操作,并建立监听事件
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @author zpoison * @data 2018/6/6/006 15:39 */ public class Exist_API_sync_Usage implements Watcher { private final static String CONNECTSTRING ="192.168.255.128:2181,192.168.255.129:2181," +"192.168.255.130:2181"; private static CountDownLatch countDownLatch=new CountDownLatch(1); private static ZooKeeper zk; private static Stat stat=new Stat(); public static void main(String[] args) throws IOException, InterruptedException, KeeperException { String path = "/zk-book"; zk=new ZooKeeper(CONNECTSTRING, 5000, new Exist_API_sync_Usage()); //确保链接成功 countDownLatch.await(); //判断path节点是否存在并开启Watcher(监听事件) zk.exists(path,true); //创建节点 zk.create(path,"1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); //修改节点数据 zk.setData(path,"2".getBytes(),-1); //创建子节点 zk.create(path+"/c1","3".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); //删除子节点 zk.delete(path+"/c1",-1); //删除节点 zk.delete(path,-1); Thread.sleep(Integer.MAX_VALUE); } @Override public void process(WatchedEvent watchedEvent) { //如果当前的连接状态是连接成功的,那么通过计数器去控制 if( watchedEvent.getState() == Event.KeeperState.SyncConnected ){ System.out.println("watched状态-->"+watchedEvent.getType()); if(Event.EventType.None==watchedEvent.getType()&&null==watchedEvent.getPath()){ countDownLatch.countDown(); System.out.println(watchedEvent.getState()+"-->"+watchedEvent.getType()); }else if(watchedEvent.getType()== Event.EventType.NodeDataChanged){ try { System.out.println("数据变更触发路径:"+watchedEvent.getPath()+"->改变后的值:"+ new String(zk.getData(watchedEvent.getPath(),true,stat))); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } }else if(watchedEvent.getType()== Event.EventType.NodeChildrenChanged){//子节点的数据变化会触发 try { System.out.println("子节点数据变更路径:"+watchedEvent.getPath()+"->节点的值:"+ new String(zk.getData(watchedEvent.getPath(),true,stat))); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } }else if(watchedEvent.getType()== Event.EventType.NodeCreated){//创建子节点的时候会触发 try { System.out.println("节点创建路径:"+watchedEvent.getPath()+"->节点的值:"+ new String(zk.getData(watchedEvent.getPath(),true,stat))); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } }else if(watchedEvent.getType()== Event.EventType.NodeDeleted){//子节点删除会触发 System.out.println("节点删除路径:"+watchedEvent.getPath()); } } } }
输出结果:
watched状态-->None SyncConnected-->None watched状态-->NodeCreated 节点创建路径:/zk-book->节点的值:1 watched状态-->NodeDataChanged 数据变更触发路径:/zk-book->改变后的值:2 watched状态-->NodeDeleted 节点删除路径:/zk-book
通过上面的案例的到如下结论:
- 无论指点节点是否存在,通过调用exists接口都可以注册Watcher。
- exists接口中注册的Watcher,能够对节点创建、节点删除和节点数据更新事件进行监听
- 对于指定子节点的各种变化,都不会通知客户端
6.权限控制
在zookeeper的实际应用中,我的做法往往是搭建一个公用的集群,统一为若干个应用提供服务。在这种情况下,不同的应用之间 往往是不会存在共享数据的使用场景的,因此需要权限解决不同应用的问题。