Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目。Zookeeper工作机制如下:
提供的服务包括:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡 等。
官网
▲ 拷贝Zookeeper安装包到Linux系统下
解压:tar -zxvf 压缩包名 目录 (解压到指定目录,不加目录默认当前目录)
▲ 将/opt/zookeeper-3.4.10/conf这个路径下的zoo_sample.cfg修改为zoo.cfg;
mv zoo_sample.cfg zoo.cfg
▲ 打开zoo.cfg文件,修改dataDir路径:
▲ 启动Zookeeper
bin/zkServer.sh start
▲ 查看进程是否启动
jps
▲ 查看状态:
bin/zkServer.sh status
▲ 启动客户端:
bin/zkCli.sh
▲ 退出客户端:
quit
▲ 停止Zookeeper
bin/zkServer.sh stop
在一台机器上模拟3个 zk server的集群安装
前提:解压后zookeeper后,新建三个zkData,然后在conf中将zoo_sample.cfg改名,复制三份zoo配置文件
在 zkData 文件夹下创建myid文件,内容分别为id值1,2,3
server.1=192.168.44.129:2887:3887
server.2=192.168.44.129:2888:3888
server.3=192.168.44.129:2889:3889
配置参数解读:server.A=B:C:D。
▲ 分别启动Zookeeper
# 启动服务端
bin/zkServer.sh start conf/zoo1.cfg
# 启动对应服务端的客户端
bin/zkCli.sh -server localhost:2182
▲ 查看状态
( 根据之前的投票规则:正常情况下应该是 zookeeper-2 是 leader,1,3为follower )
bin/zkServer.sh status conf/zoo1.cfg
bin/zkCli.sh
bin/zkCli.sh -server localhost:2182 #指定某台server的客户端
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>RELEASEversion>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.8.2version>
dependency>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.4.10version>
dependency>
dependencies>
需要在项目的src/main/resources目录下,新建一个文件命名为“log4j.properties”,在文件中填入。
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
// 创建ZooKeeper客户端,客户端连接服务端
public static void init() throws IOException {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
}
});
}
public static void main(String[] args) throws Exception {
init();
}
如果是远程连接操作的虚拟机中的zk,一定要记得:
关闭 linux 环境中的防火墙!
关闭 linux 环境中的防火墙!
关闭 linux 环境中的防火墙!
// 创建子节点
public static void create() throws Exception {
// 参数1:要创建的节点的路径
String path = "/testCreate";
// 参数2:节点数据
byte[] data = "ht".getBytes();
// 参数3:节点权限
List<ACL> acls = Ids.OPEN_ACL_UNSAFE;
// 参数4:节点的类型
CreateMode createMode = CreateMode.PERSISTENT;
String nodeCreated = zkClient.create(path, data, acls, createMode);
System.out.println(nodeCreated);
}
public static void main(String[] args) throws Exception {
init();
create();
}
获取节点
public static void getDataAndWatch() throws KeeperException, InterruptedException {
List<String> children = zkClient.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
// 延时阻塞
Thread.sleep(Long.MAX_VALUE);
}
// 创建ZooKeeper客户端,客户端连接服务端
public static void init() throws IOException {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
// 监听
@Override
public void process(WatchedEvent watchedEvent) {
List<String> children = null;
System.out.println("---------start---------");
try {
children = zkClient.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("---------end---------");
}
});
}
public static void main(String[] args) throws Exception {
init();
// create();
getDataAndWatch();
}
// 判断节点是否存在
public static void isExist() throws KeeperException, InterruptedException {
Stat exists = zkClient.exists("/sanguo", false);
System.out.println(exists==null ? "not exist" : "exist");
}
public static void main(String[] args) throws Exception {
init();
// create();
// getDataAndWatch();
isExist();
}
某分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线。
create /servers "servers"
public class DistributeServer {
private String connectString = "192.168.44.129:2181,192.168.44.129:2182,192.168.44.129:2183";
private int sessionTimeout = 10000;
private ZooKeeper zk = null;
private String parentNode = "/servers";
private static String hostname = "ht";
public static void main(String[] args) throws Exception {
DistributeServer server = new DistributeServer();
// 服务端获取和zk的连接
server.getConnect();
// 注册服务器
server.registServer(hostname);
// 业务逻辑
server.businesss(hostname);
}
// 注册服务器
public void registServer(String hostname) throws Exception{
String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(hostname +" is online "+ create);
}
// 业务逻辑代码
private void businesss(String hostname) throws InterruptedException {
System.out.println(hostname+" is working ...");
// 延时阻塞
Thread.sleep(Long.MAX_VALUE);
}
// 创建到zookeeper的客户端连接
private void getConnect() throws IOException {
zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
}
});
}
}
public class DistributeClient {
private String connectString = "192.168.44.129:2181,192.168.44.129:2182,192.168.44.129:2183";
private int sessionTimeout = 10000;
private ZooKeeper zk = null;
private String parentNode = "/servers";
public static void main(String[] args) throws Exception {
DistributeClient client = new DistributeClient();
// 1获取zk连接
client.getConnect();
// 2获取servers的子节点信息,从中获取服务器信息列表
client.getServerList();
// 3业务进程启动
client.business();
}
// 3业务进程启动
private void business() throws InterruptedException {
System.out.println("client is working ...");
Thread.sleep(Long.MAX_VALUE);
}
private void getServerList() throws KeeperException, InterruptedException {
// 1获取服务器子节点信息,并且对父节点进行监听
List<String> children = zk.getChildren(parentNode, true);
// 2存储服务器信息列表
ArrayList<String> servers = new ArrayList<>();
// 3遍历所有节点,获取节点中的主机名称信息
for (String child : children) {
// byte[] data = zk.getData(parentNode + "/" + child, false, null);
//
// servers.add(new String(data));
servers.add(child);
}
// 4 打印服务器列表的信息
System.out.println(servers);
}
// 创建客户端和zookeeper的连接
private void getConnect() throws IOException {
zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
// 再次启动监听
try {
getServerList();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}