Zookeeper 是 Apache 的一个分布式服务框架
它主要是用来解决分布式应用中经常遇到的一些数据管理问题, 如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等
简单来说 zookeeper=文件系统+监听通知机制
在ZooKeeper中,znode是一个跟Unix文件系统路径相似的节点,可以向节点存储数据或者获取数据。Zookeeper 底层是一套数据结构。这个存储结构是一个树形结构,其上的每一个节点, 我们称之为“znode” Zookeeper 中的数据是按照“树”结构进行存储的。而且 znode 节点还分为 4 中不同 的类型。每一个 znode 默认能够存储 1MB 的数据**(对于记录状态性质的数据来说,够了)**
ZooKeeper是使用观察者设计模式来设计的
当客户端注册监听它关心的目录节点时,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,ZooKeeper会通知客户端
在使用ZooKeeper之前,Linux系统中需要有jdk环境,在这里我就不过多赘述了。
[root@localhost temp]# tar -zxf zookeeper-3.6.0.tar.gz
[root@localhost temp]# cp zookeeper-3.6.0 /usr/local/zookeeper -r
ZooKeeper在启动时默认的去conf目录下去查找一个名称为zoo.cfg的配置文件。但是conf目录中没有这个文件,只有zoo_sample.cfg,顾名思义,这就是要寻找的zoo.cfg文件的模板。我们需要基于该文件配置zoo.cfg
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
下述命令皆是在bin目录下执行
./zkServer.sh stop
./zkServer.sh status
./zkClient.sh -server 192.168.126.168:2181
创建一个zookeepercluster文件夹,然后复制三份zookeeper,如下
修改三个zookeeper的zoo.cfg文件,如下:
其中
注意:server.标识:后面的标识是代表不同zookeeper文件,故集群时需要在不同zookeeper的data中创建myid文件,如下:
快捷方法:
在zookeepercluster路径下
echo 1 >> zookeeper01/data/myid
echo 2 >> zookeeper02/data/myid
echo 3 >> zookeeper03/data/myid
1、2、3就对应我截图里面的标识,还有就是如果没有对应的myid,会自动创建myid
此时,一个zookeeper集群就配置好了。
但是这样子需要一个个zookeeper启动,再一个个zookeeper是不是很麻烦。为了不那么麻烦,我们可以把这些命令写成sh文件
vim startall.sh
再将这几个命令写进去
输入:wq保存
同理,我们也可以写一个shutdown.sh文件停止zookeeper运行
但是这样子的话,这个sh文件还不能执行,那就用liunx命令给其添加权限
chomd 777 startall.sh
chomd 777 shutdown.sh
可以使用任意一个客户端连接
./zkClient -server 192.168.126.128:2181
ls /path
使用 ls 命令查看 zookeeper 中的内容。在 ZooKeeper 控制台客户端中,没有默认列表功 能,必须指定要列表资源的位置
create [-e] [-s] /path [data]
加-e表示是临时节点,-s表示需要进行顺便编号,/path表示要创建的节点,data表示该节点的值,以上带[]的都表示可选参数
get [-s] /path
-s 表示是否查看详细信息
set /path [data]
delete /path
添加pom依赖
org.apache.zookeeper
zookeeper
3.6.0
public class ZnodeDemo implements Watcher {
public static void main(String[] args) throws InterruptedException, KeeperException, IOException {
ZooKeeper zooKeeper = new ZooKeeper("192.168.126.128:2181,192.168.126.128:2182,192.168.126.128:2183",150000,new ZnodeDemo());
//创建Znode
String path = zooKeeper.create("/lanh/try","ni".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
System.out.println(path);
//获取指定节点的数据
byte[] data = zooKeeper.getData("/lanh/try0000000002",new ZnodeDemo(),new Stat());
System.out.println(new String(data));
//获取指定节点中所有子节点中的数据
List<String> list = zooKeeper.getChildren("/lanh",new ZnodeDemo());
for (String s:list){
System.out.println(new String(zooKeeper.getData("/lanh/"+s,new ZnodeDemo(),new Stat())));
}
//设置节点值,-1表示所有版本
Stat stat = zooKeeper.setData("/lanh/try0000000002","get it a try".getBytes(),-1);
System.out.println(stat);
//删除节点值
zooKeeper.delete("/lanh/try0000000001",-1);
}
@Override
public void process(WatchedEvent watchedEvent) {
if(watchedEvent.getState()==Event.KeeperState.SyncConnected){
System.out.println("连接成功");
}
}
}
org.apache.zookeeper
zookeeper
3.6.0
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface UsersService extends Remote {
String findUsers(String str) throws RemoteException;
}
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* @Author Lanh
**/
public class UsersServiceImpl extends UnicastRemoteObject implements UsersService {
public UsersServiceImpl() throws RemoteException {
}
public String findUsers(String str) throws RemoteException {
return "Hello zookeeper "+str;
}
}
import org.apache.zookeeper.*;
import java.io.IOException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
/**
* @Author Lanh
**/
public class ServerDemo implements Watcher {
public static void main(String[] args) throws IOException, AlreadyBoundException, InterruptedException, KeeperException {
UsersService usersService = new UsersServiceImpl();
LocateRegistry.createRegistry(8888);
String url = "rmi://localhost:8888/user";
Naming.bind(url,usersService);
//将url信息放到Znode中
ZooKeeper zooKeeper = new ZooKeeper("192.168.126.128:2181,192.168.126.128:2182,192.168.126.128:2183",150000,new ServerDemo());
zooKeeper.delete("/lanh/service",-1);
zooKeeper.create("/lanh/service",url.getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
System.out.println("服务发布成功");
}
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState()==Event.KeeperState.SyncConnected){
System.out.println("连接成功");
}
}
}
也要有对应的接口
package com.lanh.service;
public interface UsersService{
String findUsers(String str);
}
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
/**
* @Author Lanh
**/
public class ClientDemo implements Watcher {
public static void main(String[] args) throws IOException, NotBoundException, InterruptedException, KeeperException {
ZooKeeper zooKeeper = new ZooKeeper("192.168.126.128:2181,192.168.126.128:2182,192.168.126.128:2183",150000,new ClientDemo());
byte[] bytes = zooKeeper.getData("/lanh/service",new ClientDemo(),null);
String url = new String(bytes);
UsersService usersService = (UsersService) Naming.lookup(url);
String result = usersService.findUsers("Lanh");
System.out.println(result);
}
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState()==Event.KeeperState.SyncConnected){
System.out.println("连接成功");
}
}
}
至此结束,也欢迎大家来讨论