Zookeeper
Zookeeper命令操作
Zookeeper服务端命令
- 启动Zookeeper服务:./zkServer.sh start
- 查看Zookeeper服务状态:./zkServer.sh status
- 停止Zookeeper服务:./zkServer.sh stop
- 重启Zookeeper服务:./zkServer.sh restart
Zookeeper客户端命令
- 连接:./zkCli.sh -server localhost:2181 (./zkCli.sh)
- 查看命令:help
- 查看节点:ls /节点名
- 创建持久节点:create /节点名 数据
- 创建临时节点:create -e /节点名(关闭客户端后临时节点将消失)
- 创建顺序节点:create -s /节点名(自动加编号)
- 创建临时顺序节点:create -es /节点名
- 查看节点数据:get /节点名
- 修改节点数据:set /节点名 数据
- 删除节点:delete /节点名(非递归删除,删除时需要节点数据为空)
- 删除节点数据:delete /节点名/数据
- 递归删除:deleteall /节点名
Zookeeper JavaAPI操作
Curator 介绍
-
Curator是ApacheZookeeper的Java客户端
-
常见的Zookeeper Java API:
- 原生Java API
- ZkClient
- Curator
-
Curator项目的目标是简化ZooKeeper客户端的使用
建立连接
-
导入依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.Curator</groupId> <artifactId>Curator-mk</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <!--curator--> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.0.0</version> </dependency> <!--日志--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
-
导入log4j.properties文件
-
编写测试类
public class CuratorTest { private CuratorFramework client; /** * 建立连接 */ @Test //@Before public void testConnect(){ /* * * @param connectString 连接字符串。zk server 地址和端口 "192.168.23.129:2181" * @param sessionTimeoutMs 会话超时时间 单位ms * @param connectionTimeoutMs 连接超时时间 单位ms * @param retryPolicy 重试策略 */ //重试策略 RetryPolicy retryPolicy=new ExponentialBackoffRetry(3000,3 ); //第一种方式 // CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.23.129:2181", // 60 * 1000, // 15 * 1000, // retryPolicy); //第二种方式 client = CuratorFrameworkFactory.builder() .connectString("192.168.23.129:2181") .sessionTimeoutMs(60 * 1000) .connectionTimeoutMs(15 * 1000) .retryPolicy(retryPolicy) .namespace("curator") .build(); //开启连接 client.start(); } }
创建节点
/**
* 创建节点:create 持久 临时 顺序 数据
* 1. 基本创建 :create().forPath("")
* 2. 创建节点 带有数据:create().forPath("",data)
* 3. 设置节点的类型:create().withMode().forPath("",data)
* 4. 创建多级节点 /app1/p1 :create().creatingParentsIfNeeded().forPath("",data)
*/
/**
* 基本创建
* @throws Exception
*/
@Test
public void testCreate1() throws Exception {
//如果创建节点,没有指定数据,则默认将当前客户端的ip作为数据存储
String s = client.create().forPath("/app12");
System.out.println(s);
}
/**
* 创建带有数据的节点
* @throws Exception
*/
@Test
public void testCreate2() throws Exception {
String app2 = client.create().forPath("/app2", "wangnima".getBytes());
System.out.println(app2);
}
/**
* 设置节点类型
* 节点类型默认为持久化
* @throws Exception
*/
@Test
public void testCreate3() throws Exception {
String path = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3");
System.out.println(path);
}
/**
* 创建多级节点 /app4/p1
* creatingParentsIfNeeded():如果父节点不存在,则创建父节点
* @throws Exception
*/
@Test
public void testCreate4() throws Exception {
String path = client.create().creatingParentsIfNeeded().forPath("/app4/p1");
System.out.println(path);
}
查询节点
/**
* 查询节点:
* 1. 查询数据:get: getData().forPath()
* 2. 查询子节点: ls: getChildren().forPath()
* 3. 查询节点状态信息:ls -s:getData().storingStatIn(状态对象).forPath()
*/
@Test
public void testGet1() throws Exception {
//查询数据:get 当节点没数据时会报错
byte[] data = client.getData().forPath("/app2");
System.out.println(new String(data));
}
@Test
public void testGet2() throws Exception {
//查询子节点
List<String> list = client.getChildren().forPath("/");
System.out.println(list);
}
@Test
public void testGet3() throws Exception {
//历史遗留问题,其实就是一个JavaBean
Stat status = new Stat();
//3. 查询节点状态信息:ls -s
client.getData().storingStatIn(status).forPath("/app2");
System.out.println(status);
}
修改节点
/**
* 修改数据
* 1. 基本修改数据:setData().forPath()
* 2. 根据版本修改: setData().withVersion().forPath()
* * version 是通过查询出来的。目的就是为了让其他客户端或者线程不干扰。
*
* @throws Exception
*/
@Test
public void testSet() throws Exception {
//修改节点数据为:王大锤
client.setData().forPath("/app2","王大锤".getBytes());
System.out.println("修改成功");
}
@Test
public void testSetForVersion() throws Exception {
Stat status = new Stat();
//3. 查询节点状态信息:ls -s
client.getData().storingStatIn(status).forPath("/app2");
int version = status.getVersion();//查询出来的
System.out.println(version);
client.setData().withVersion(version).forPath("/app2", "胖虎".getBytes());
}
删除节点
/**
* 删除节点: delete deleteall
* 1. 删除单个节点:delete().forPath("/app1");
* 2. 删除带有子节点的节点:delete().deletingChildrenIfNeeded().forPath("/app1");
* 3. 必须成功的删除:为了防止网络抖动。本质就是重试。 client.delete().guaranteed().forPath("/app2");
* 4. 回调:inBackground
* @throws Exception
*/
@Test
public void testDelete() throws Exception {
// 1. 删除单个节点
client.delete().forPath("/app1");
}
@Test
public void testDelete2() throws Exception {
//2. 删除带有子节点的节点
client.delete().deletingChildrenIfNeeded().forPath("/app4");
}
@Test
public void testDelete3() throws Exception {
//3. 必须成功的删除
client.delete().guaranteed().forPath("/app2");
}
@Test
public void testDelete4() throws Exception {
//4. 回调
client.delete().guaranteed().inBackground(new BackgroundCallback(){
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("删除");
System.out.println(event);
}
}).forPath("/app1");
}
Watch事件监听
- Zookeeper 允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,Zookeeper服务端会将事件通知到感兴趣的客户端上去,该机制是Zookeeper实现分布式协调服务的重要特性。
- Zookeeper中引入Watcher机制来实现了分布/订阅功能,能够让多个订阅同时监听某一个对象,当一个对象自身状态变化时,会通知所有订阅者。
- Zookeeper原生支持通过注册Watcher来进行事件监听,但是其使用并不是特别方便需要开发人员自己反复注册Watcher,比较繁琐。
- Curator引入了Cache来实现对Zookeeper服务端事件的监听。
- Zookeeper提供了三种Watcher:
- NodeCache:只是监听某一个特定的节点
- PathChildrenCache:监控一个ZNode的子节点
- TreeCache:可以监控整个树上的所有节点,类似于PathChildrenCache和NodeCache的组合
Watch监听-NodeCache
![wang](C:\Users\Administrator\Desktop\wang.png)![wang](C:\Users\Administrator\Desktop\wang.png)public class CuratorWatcherTest {
private CuratorFramework client;
/**
* 建立连接
*/
@Before
public void testConnect(){
/*
*
* @param connectString 连接字符串。zk server 地址和端口 "192.168.23.129:2181"
* @param sessionTimeoutMs 会话超时时间 单位ms
* @param connectionTimeoutMs 连接超时时间 单位ms
* @param retryPolicy 重试策略
*/
//重试策略
RetryPolicy retryPolicy=new ExponentialBackoffRetry(3000,3 );
//第一种方式
// CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.23.129:2181",
// 60 * 1000,
// 15 * 1000,
// retryPolicy);
//第二种方式
client = CuratorFrameworkFactory.builder()
.connectString("192.168.23.129:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retryPolicy)
.namespace("curator")
.build();
//开启连接
client.start();
}
@After
public void close(){
if (client != null){
client.close();
}
}
/**
* NodeCache:给指定一个节点注册监听器
*/
@Test
public void testNodeCache() throws Exception {
//1.创建NodeCache对象
NodeCache nodeCache = new NodeCache(client,"/app1");
//2.注册监听
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("节点已变化");
//获取修改节点后的数据
byte[] data = nodeCache.getCurrentData().getData();
System.out.println(new String(data));
}
});
//3.开启监听,如果设置为true,则开启监听,加载缓冲数据
nodeCache.start(true);
while (true){
}
}
}
Watch监听-PathChildrenCache
/**
* 监听自己的儿子
* @throws Exception
*/
@Test
public void testPathChildrenCache() throws Exception {
//1.创建NodeCache对象
PathChildrenCache pathChildrenCache = new PathChildrenCache(client,"/curator",true);
//2.注册监听
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
//监听子节点的数据变更,并且拿到变更后的数据
//1.监听类型
PathChildrenCacheEvent.Type type = event.getType();
//2.判断类型是否是update
if (type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
byte[] data = event.getData().getData();
System.out.println(new String(data));
System.out.println("儿子们变坏了");
}
}
});
//3.开启监听
pathChildrenCache.start();
while (true){
}
}
Watche监听-TreeCache
/**
* 监听自己和儿子们
*/
@Test
public void testTreeCache() throws Exception {
//1. 创建监听器
TreeCache treeCache = new TreeCache(client,"/app2");
//2. 注册监听
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
System.out.println("节点变化了");
System.out.println(event);
}
});
//3. 开启
treeCache.start();
while (true){
}
}