zookeeper02(zookeeper常用命令、使用java API操作Zookeeper、zookeeper实战)

zookeeper02

本文代码:https://pan.baidu.com/s/1GftxVT7HIH9oMO0zBmEO6A
提取码:7brm

一、zookeeper常用命令

[1] ls命令
ls /path

使用 ls 命令查看 zookeeper 中的内容。在 ZooKeeper 控制台客户端中,没有默认列表功能(即直接 ls–>回车 的命令是错误的),必须指定要列表资源的位置。 如: ls / 或者 ls /path
在这里插入图片描述

[2] create命令
create [-e] [-s] /path [data]

使用 create 命令创建一个新的 Znode。
create [-e] [-s] path data - 创建节点,如:

  • create /test 123 创建一个/test 节点,节点携带数据信息 123。
  • create -e /test 123 创建一个临时节点/test,携带数据为 123,临时节点只在当前会话生命周期中有效,会话结束节点自动删除。(需要一些时间删除,大概10秒左右)
  • create -s /test 123 创建一个顺序节点/test,携带数据 123,创建的顺序节点由 ZooKeeper 自动为节点增加后缀信息,如-/test00000001 等。-e 和-s 参数可以联合使用。
    在这里插入图片描述
    在这里插入图片描述
[3] get 命令
#获取节点例的[详细]内容
get [-s] /path

在这里插入图片描述

  • oldlu:存放的数据
  • cZxid:创建时 zxid(znode 每次改变时递增的事务 id)
  • ctime:创建时间戳
  • mZxid:最近一次更近的 zxid
  • mtime:最近一次更新的时间戳
  • pZxid:子节点的 zxid
  • cversion:子节点更新次数
  • dataversion:节点数据更新次数
  • aclVersion:节点 ACL(授权信息)的更新次数
  • ephemeralOwner:如果该节点为 ephemeral 节点(临时,生命周期与 session 一样), ephemeralOwner 值表示与该节点绑定的 session id. 如果该节点不是ephemeral 节点, ephemeralOwner 值为 0
  • dataLength:节点数据字节数
  • numChildren:子节点数量
[4]set 命令

set /path data
修改添加 Znode 中的值
(1)修改节点中的值
在这里插入图片描述
(2)添加节点中的值
在这里插入图片描述

[5] delete命令

delete /path 删除节点
在这里插入图片描述

二、使用 Java API 操作 Zookeeper

本文代码:https://pan.baidu.com/s/1GftxVT7HIH9oMO0zBmEO6A

提取码:7brm

[1] 创建 Znode

创建maven项目,不需要用到需骨架
在这里插入图片描述
修改 POM 文件添加依赖
该依赖为基于 Java 语言连接 Zookeeper 的客户端工具。版本选择和安装的zookeeper版本一致

<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.6.0</version>
</dependency>

创建 Znode 并添加数据

package com.qt;

import org.apache.zookeeper.*;

import java.io.IOException;

/**
 * 操作Zookeeper的Znode
 */
public class ZnodeDemo implements Watcher {
    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        ZooKeeper zooKeeper= new ZooKeeper("120.25.255.18:2181",150000,new ZnodeDemo());
        //创建一个Znode("路径",byte[存放数据],权限,节点类型)
        String path = zooKeeper.create("/szxy/qiaotong","oldJoe".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
        System.out.println(path);
    }

    /**
     * 事件通知会掉方法
     * @param event
     */
    @Override
    public void process(WatchedEvent event) {//在连接成功后会返回一个event事件
        //获取连接事件
        if (event.getState() == Event.KeeperState.SyncConnected){//若事件的state值为连接序列值
            System.out.println("连接成功");
        }
    }
}

程序执行完成后结果。(时间有点长)
在这里插入图片描述
进入zookeeper查看创建的节点
在这里插入图片描述

[2]获取 Znode 中的数据

1 获取指定节点中的数据
getData(节点路径,实现了Watcher接口的事件通知方法,Stat())

		byte[] data = zooKeeper.getData("/szxy/qiaotong0000000000", new ZnodeDemo(), new Stat());
        System.out.println(new String(data));

2 获取所有子节点中的数据
getChildren(路径,实现Watcher接口的事件通知方法)

		//获取指定节点中所有节点的路径
        List<String> list = zooKeeper.getChildren("/", new ZnodeDemo());
        System.out.println(list.toString());
        for (String path:list) {
            byte[] data1 = zooKeeper.getData("/"+path, new ZnodeDemo(), null);
            System.out.println(new String(data1));
        }
[3]设置节点中的值
		//setData("节点路径","要设置的内容",要修改的节点版本号,若不正确则设置失败,-1表示所有版本)
		Stat stat = zooKeeper.setData("/szxy", "abcde".getBytes(), -1);
        System.out.println(stat);
[4]删除节点值
//delete(“节点路径”,被删除节点的版本号,若版本号错误则删除失败,-1表示所有版本号)
zooKeeper.delete("/szxy/qiaotong0000000000",-1);
[5]代码汇总
package com.qt;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.List;

/**
 * 操作Zookeeper的Znode
 * 本类实现了Watcher 接口,因此可以当一些方法的watcher参数
 */
public class ZnodeDemo implements Watcher {
    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        ZooKeeper zooKeeper= new ZooKeeper("120.25.255.18:2181",150000,new ZnodeDemo());
        //创建一个Znode
        /*String path = zooKeeper.create("/szxy/qiaotong","oldJoe".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
        System.out.println(path);*/

        //获取指定节点的数据
        /*byte[] data = zooKeeper.getData("/szxy/qiaotong0000000000", new ZnodeDemo(), new Stat());
        System.out.println(new String(data));*/

        //获取指定节点中所有节点的路径
       /* List<String> list = zooKeeper.getChildren("/", new ZnodeDemo());
        System.out.println(list.toString());
        for (String path:list) {
            byte[] data1 = zooKeeper.getData("/"+path, new ZnodeDemo(), null);
            System.out.println(new String(data1));
        }*/
        //设置节点的值(state为节点的详细信息,设置成功后会把设置好的节点详细信息返回)
       /* Stat stat = zooKeeper.setData("/szxy", "我是帅哥".getBytes(), -1);
        System.out.println(stat);*/
        //删除节点值
        zooKeeper.delete("/szxy/qiaotong0000000000",-1);
    }

    /**
     * 事件通知回调方法
     * @param event
     */
    @Override
    public void process(WatchedEvent event) {//在连接成功后会返回一个event事件
        //获取连接事件
        if (event.getState() == Event.KeeperState.SyncConnected){//若事件的state值为连接序列值
            System.out.println("连接成功");
        }
    }
}

三、zookeeper实战

实战案例介绍:使用 Zookeeper 与 RMI 技术实现一个 RPC 框架。
RPC:RPC(Remote Procedure Call)远程过程调用。

[1] 基于 RMI 实现远程方法调用

1.1RMI 简 介
RMI(Remote Method Invocation) 远程方法调用。
RMI 是从 JDK1.2 推出的功能,它可以实现在一个 Java 应用中可以像调用本地方法一样调用另一个服务器中 Java 应用(JVM)中的内容。
RMI 是 Java 语言的远程调用,无法实现跨语言。
1.2执行流程
在这里插入图片描述
Server端:能够允许外界通过其对象调用其方法的一侧。
Client:要去调用远程目标的对象下方法的一侧。
Registry(注册表):是放置所有服务器对象的命名空间,里面放的是所有对外暴露的对象。 每次服务端创建一个对象时,它都会使用 bind()或 rebind()方法注册该对象。 这些是使用称为绑定名称的唯一名称注册的。
要调用远程对象,客户端需要该对象的引用。即通过服务端绑定的名称从注册表中获取对象(lookup()方法)。
1.3RMI 的 API 介绍
(1)Remote 接口
java.rmi.Remote 定义了此接口为远程调用接口。如果接口被外部调用,需要继承此接口。
(2)RemoteException 类
java.rmi.RemoteException
继承了 Remote 接口的接口,如果方法是允许被远程调用的,需要抛出此异常。
(3)UnicastRemoteObject 类
java.rmi.server.UnicastRemoteObject
此类实现了 Remote 接口和 Serializable 接口。自定义接口实现类除了实现自定义接口还需要继承此类。
(4)LocateRegistry 类
java.rmi.registry.LocateRegistry
可以通过 LocateRegistry 在本机上创建 Registry,通过特定的端口就可以访问这个Registry。
(5)Naming 类
java.rmi.Naming
Naming 定义了发布内容可访问 RMI 名称。也是通过 Naming 获取到指定的远程方法。
Server端通过该类实现将暴露的类绑定到注册表,Client端通过此类访问注册表中暴露的方法。
1.4 创建Server端
(1)创建项目
在这里插入图片描述
(2)创建接口

/*
* 定义允许远程调用该接口,该接口必须继承Remote接口
* 允许被远程调用的方法必须抛出RemoteException异常
* */

public interface DemoService extends Remote {
    String demo(String str) throws RemoteException;
}

(3)创建接口实现的类

/*
* 接口实现类必须要继承UnicastRemoteObject
* 会自动添加构造方法,需要修改为public
* */
public class DemoServiceImpl extends UnicastRemoteObject implements DemoService {
    //把protected改成public
    public DemoServiceImpl() throws RemoteException {
    }

    @Override
    public String demo(String str) throws RemoteException {
        return "Hello RMI"+str;
    }
}

(3)编写主方法

public class DemoServer {
    public static void main(String[] args) throws RemoteException, AlreadyBoundException, MalformedURLException {
        //将对象实例化
        DemoService demoService = new DemoServiceImpl();
        //创建本地注册表
        LocateRegistry.createRegistry(8081);
        //将对象绑定到注册表中("rmi协议://ip地址:端口号/对象名",对象)
        Naming.bind("rmi://localhost:8081/demoService",demoService);
    }
}

1.5创建Client端
(1)创建项目
在这里插入图片描述
(2)复制服务器端接口(客户端在注册表中找到暴露的对象后,需要有具体的类型来修饰该对象)

/*
* 定义允许远程调用该接口,该接口必须继承Remote接口
* 允许被远程调用的方法必须抛出RemoteException异常
* */

public interface DemoService extends Remote {
    String demo(String str) throws RemoteException;
}

(3)创建主方法

public class ClientDemo {
    public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {
        //该URL必须和Server端的URL保持一致,若其他电脑想远程调用该对象,则必须把localhost改为Server端电脑IP地址
        DemoService demoService =(DemoService)Naming.lookup("rmi://localhost:8081/demoService");
        String str = demoService.demo(" hello");
        System.out.println(str);
    }
}

测试结果
在这里插入图片描述
该方式缺点:Client端必须知道Server端的IP地址、端口号、对象名称,否则无法找到注册表中的对象。
解决方法:Server端启动后把URL信息放在Zookeeper的节点中,Client端先从zookeeper中指定的节点获取URL信息,再把获取到的URL放在lookup方法中。

[2]使用zookeeper作为注册中心实现RPC

2.1创建zookeeperserver端
(1)创建项目
在这里插入图片描述
(2)修改pom.xml文件

	<dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.6.0</version>
        </dependency>
    </dependencies>

(3)创建接口

public interface UserService extends Remote {
    String findUsers(String str)throws RemoteException;
}

(4)创建接口实现类

public class UserServiceImpl extends UnicastRemoteObject implements UserService {

    public UserServiceImpl() throws RemoteException {
    }

    @Override
    public String findUsers(String str) throws RemoteException {
        return "Hello zookeeperRMI "+str;
    }
}

(5)编写主方法

public class ServerDemo  implements Watcher {
    public static void main(String[] args) throws IOException, AlreadyBoundException, KeeperException, InterruptedException {
        UserService userService=new UserServiceImpl();
        //创建端口号
        LocateRegistry.createRegistry(8888);
        //创建绑定对象的URL
        String url="rmi://localhost:8888/user";
        //绑定对象到注册表
        Naming.bind(url,userService);
        //将url信息放到zookeeper中
        ZooKeeper zooKeeper=new ZooKeeper("120.25.255.18:2181",150000,new ServerDemo());
        //创建Znode(节点路径,节点内容,权限:全部权限,节点类型:持久化节点)
        zooKeeper.create("/szxy/service",url.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("服务发布成功");
    }

    @Override
    public void process(WatchedEvent event) {
        if (event.getState() == Event.KeeperState.SyncConnected){
            System.out.println("连接成功");
        }
    }
}

运行结果
在这里插入图片描述
在这里插入图片描述

2.2创建zookeeperclient端
(1)创建项目
在这里插入图片描述
(2)修改pom.xml依赖

	<dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.6.0</version>
        </dependency>
    </dependencies>

(3)复制zookeeperserver服务端的接口(用于修饰获取到对象的类型)

public interface UserService{
    String findUsers(String str);
}

(4)编写主方法

public class ClientDemo implements Watcher {
    public static void main(String[] args) throws IOException, KeeperException, InterruptedException, NotBoundException {
        //创建Zookeeper对象
        ZooKeeper zooKeeper=new ZooKeeper("120.25.255.18:2181",150000,new ClientDemo());
        //获得Znode节点中的数据
        byte[] data = zooKeeper.getData("/szxy/service", new ClientDemo(), null);
        String url=new String(data);
        //从注册表中寻找对象
        UserService userServer =(UserService)Naming.lookup(url);
        String str = userServer.findUsers("qt");
        System.out.println(str);
    }
    @Override
    public void process(WatchedEvent event) {
        if (event.getState() ==Event.KeeperState.SyncConnected){
            System.out.println("连接成功");
        }
    }
}

运行结果
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值