zookeeper是用来存放配置信息的,量比较小,所以zookeeper不是用来存放大量的数据信息的。
1、下载地址
https://zookeeper.apache.org/
2、linux系统安装zookeeper
a、安装zookeeper之前需要先安装好jdk
b、安装zookeeper
cd /usr/local
mkdir zookeeper
cd zookeeper/
rz 打开传输窗口,传输zookeeper安装包到linux系统
tar -zxvf zookeeper-3.4.10.tar.gz 解压
ls 查看
3、修改配置文件
a、将/usr/local/zookeeper/zookeeper-3.4.10/conf路径下的zoo_sample.cfg改名为zoo.cfg
mv zoo_sample.cfg zoo.cfg
b、在/usr/local/zookeeper/zookeeper-3.4.10路径下创建 data/zkData目录
mkdir -p data/zkData
c、修改步骤a中的zoo.cfg文件,将dataDir设置为步骤b中新建的目录路径dataDir=/usr/local/zookeeper/zookeeper-3.4.10/data/zkData
这是快照的保存位置
4、操作zookeeper
a、启动zookeeper
进入/usr/local/zookeeper/zookeeper-3.4.10/bin,查看有哪些内容
执行启动命令:
./zkServer.sh start
或者在上一层目录执行bin/zkServer.sh start
b、查看是否启动成功
jps 或者ps -ef | grep zookeeper
c、查看状态
bin/zkServer.sh status
d、启动客户端
bin/zkCli.sh
e、退出客户端
quit
f、停止服务端
bin/zkServer.sh stop
说明:客户端可以连接服务端,对服务端进行操作
------zookeeper的分布式安装部署----------
1、linux系统安装zookeeper
a、安装zookeeper之前需要先安装好jdk
b、安装zookeeper
cd /usr/local
mkdir zookeeper
cd zookeeper/
rz 打开传输窗口,传输zookeeper安装包到linux系统
tar -zxvf zookeeper-3.4.10.tar.gz 解压
ls 查看
2、修改配置文件
a、将/usr/local/zookeeper/zookeeper-3.4.10/conf路径下的zoo_sample.cfg改名为zoo.cfg
mv zoo_sample.cfg zoo.cfg
b、在/usr/local/zookeeper/zookeeper-3.4.10路径下创建 data/zkData目录
mkdir -p data/zkData
c、修改步骤a中的zoo.cfg文件,将dataDir设置为步骤b中新建的目录路径dataDir=/usr/local/zookeeper/zookeeper-3.4.10/data/zkData
这是快照的保存位置
d、配置zookeeper集群的服务器节点
server.1=centos:2888:3888
server.2=centos2:2888:3888
server.3=centos3:2888:3888
其中centos、centos2、centos3分别为3台zookeeper服务器节点的hostname名称
3、在zoo.cfg中配置的dataDir对应的目录下新建myid文件,如果当前机器是server.2,则myid文件中的内容为2;如果当前机器是server.3,则myid文件中的内容为3。
touch myid
vim myid
4、在配置文件中添加ip地址与主机名称的映射关系
vim /etc/hosts
192.168.225.132 centos
192.168.225.133 centos2
192.168.225.134 centos3
5、分别启动zookeeper
cd /usr/local/zookeeper/zookeeper-3.4.10/bin
./zkServer.sh start
6、查看zookeeper服务器节点状态
./zkServer.sh status
7、关闭防火墙
查看通过以上步骤启动后,查看zookeeper状态,会提示It is probably not runnig,原因可能有两点:
1)需要几台server服务器都启动以后才能查看状态
2)可能是防火墙没有关闭,导致连接不上
查看防火墙状态:firewall-cmd --state
关闭防火墙:systemctl stop firewalld.service
如果zookeeper集群搭建成功后,应该是一个leader,两个follower,状态应该如下图:
----------客户端命令操作zookeeper集群-------
1、启动客户端
./zkCli.sh
2、help命令查看在客户端上可以操作的命令
help
3、查看当前znode服务器节点中所包含的内容
ls /
ls2 /
4、主要创建短暂节点时,只有创建短暂节点的客户端退出连接时,才会删除该短暂节点,如果是a客户端创建的短暂节点,只要a不退出,即使b客户端退出连接,也不会删除该短暂节点。
5、创建节点必须一层一层的创建,否则会提示Node does not exist
6、监听节点变化
get /nihao watch
注意:只能监控一次,及数据第一次改变时,可以监听到,如果再改变就监听不到了
7、删除节点
rm 节点名 只能删除没有子节点的节点
rmr 节点名 级联删除当前节点及其子节点
8、查看节点状态
stat /xiyou
与get的区别就在于,get会获取节点数据,而stat不获取数据
9、创建临时节点
create -s /servers/server ceshi
以上命令执行结果,就是在/servers路径下创建新的节点,由于我们给定的几点名称是
server,而我们要创建的有序节点,所以创建出来的节点就是server0000000004,而ceshi
是该节点存放的值
10、创建短暂节点,一般用于注册服务时使用
create -e /servers/server2 haha
-----------java API操作zookeeper集群-----------
watch实现监听的作用,当符合条件时,会调用该接口中的process方法,所以process方法中可以处理真正的业务逻辑
案例:
动态感知服务器的上下线:
首先要明白:无论是server端还是client端,都应该理解为是zookeeper的client端,server做为client连接到zookeeper,上线时创建对应的临时节点,下线时临时节点自动删除。
1、服务器端启动时,向zookeeper中取注册信息(zookeeper中创建的是对应的临时节点)
2、客户端启动时,就去getChildren,获取到当前在线服务器列表,并且注册监听
3、在zookeeper上注册的某一个server服务端节点下线时,zookeeper上该节点对会被自动删除(由于添加的是临时节点);同时由于步骤2中客户端注册了Watch事件,所以当某个server节点下线时,客户端可以在Watch接口的process中做一些业务逻辑上的处理
小总结:zookeeper是集群的,可以理解为独立于应用系统之外的,而应用的服务端server和客户端client,都是要做为zookeeper的客户端clien去连接zookeeper的, 新增一个server,则在zookeeper新建一个临时的对应路径,而server下线,该路径被删除,而client端监听watch到server的上线下,可以做一些业务逻辑上的处理。
具体代码如下:
AppServer.java代码如下:
package zkCase;
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
public class AppServer {
//1、连接到zookeeper
public String connectString = "192.168.225.132:2181,192.168.225.133:2181,192.168.225.134:2181";
private int sessionTimeout = 2000;
private ZooKeeper zkClient = null;
//前提是zookeeper上提前创建了/servers路径
private String parentNode = "/servers";
public void getConnection() throws IOException{
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher(){
public void process(WatchedEvent event) {
System.out.println(event.getType()+"--"+event.getPath());
}
});
}
//2、注册AppServer信息
public void regist(String hostname) throws KeeperException, InterruptedException{
//创建短暂的有序的连接,短暂是因为Appserver下线时节点信息被删除,有序可以保证每个节点名称不重复
zkClient.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(hostname + "is online");
}
//3、具体的业务逻辑
public void business() throws InterruptedException{
System.out.println("处理具体业务逻辑");
//睡眠这么久是为了保证程序不执行完,AppServer不会因为自动退出而导致注册的信息被自动删除
Thread.sleep(Long.MAX_VALUE);
}
public static void main(String[] args)throws Exception {
AppServer server = new AppServer();
server.getConnection();
server.regist(args[0]);
server.business();
}
}
AppClient.java代码如下:
package zkCase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
public class AppClient {
//1、连接到zookeeper
public String connectString = "192.168.225.132:2181,192.168.225.133:2181,192.168.225.134:2181";
private int sessionTimeout = 2000;
private ZooKeeper zkClient = null;
//前提是zookeeper上提前创建了/servers路径
private String parentNode = "/servers";
public void getConnection() throws IOException{
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher(){
public void process(WatchedEvent event){
System.out.println(event.getType()+"--"+event.getPath());
try {
//保证第二次调用时依然能够监听
getServers();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
//2、监听节点变化
public void getServers() throws KeeperException, InterruptedException{
List<String> list = zkClient.getChildren(parentNode, true);
List<String> hostnames = new ArrayList<String>();
for(String str:list){
byte[] data = zkClient.getData(parentNode+"/"+str, false, null);
hostnames.add(new String(data));
}
System.out.println(hostnames);
}
//3、处理具体的业务逻辑
public void business() throws InterruptedException{
System.out.println("处理具体的业务逻辑");
//此处长睡眠,是为了保证在见天到节点变化之前,程序没有结束
Thread.sleep(Long.MAX_VALUE);
}
//4.在获取连接中实现Watch的process方法,重新调用getServers()方法以保证可以再次监听
public static void main(String[] args)throws Exception {
AppClient client = new AppClient();
client.getConnection();
client.getServers();
client.business();
}
}