本文比较系统的梳理了ZooKeeper的常用知识点,包括文件系统、监听通知机制、单机环境搭建、集群环境搭建、常用操作命令、Java API调用和作为注册中心服务等内容,读完本文,相信能有助于我们对ZooKeeper的概念和用法有一个整体的认识。 ZooKeeper是阿帕奇官网的一个分布式服务框架,用来解决分布式应用中经常出现的一些数据管理问题,比如统一命名服务、状态同步服务、集群管理和分布式应用配置管理等。总的来说, ZooKeeper底层是一套树形存储结构,类似于Unix文件系统路径,也是从根节点开始,这些节点都称之为 ZooKeeper采用了观察者设计模式,客户端会向其关心的目录节点注册,一旦目录节点发生改变(比如数据的更新或删除、子目录节点的增加或删除),ZK服务就会通知客户端。 我们这里都是在Linux系统中搭建环境 JDK安装请参考一文搞定Linux常见用法中第八部分 1、上传安装包 2、解压 4、创建数据缓存目录 使用 停止服务使用 在bin目录下,执行 ZooKeeper 集群中的角色主要有三类:领导者(Leaner)、跟随者(Follower)和观察者(ObServer),后两者也叫学习者(Learner) zk集群最小安装需要3个节点,我们这里搭建伪集群(伪集群简单理解就是在一个Linux环境中创建多个zk服务,实际生产环境中我们肯定使用真实集群) 然后再分别复制 4、提供应用唯一标识 5、增加集群配置 方式一: 对两个脚本授权: 在任意一个zk节点的bin目录下,执行 ls命令查看节点,格式: path不能少,否则无法执行(这点与linux不一样) create命令创建节点,格式: 持久化有序号节点: 临时的无序号节点: 临时的有序号解决: get命令获取节点数据,格式: 获取详细信息: 详细信息说明 set命令往无数据节点写入数据或修改节点中的数据,格式: 修改节点中的数据 delete删除节点命令,格式: 这里要注意引入的版本,因为我安装的3.6.0的zk,所有引入的也是这个版本的依赖 新建一个 启动mian方法之前,要先开启3zk服务的端口防火墙,否则连不上,命令如下 测试,控制台打印 查看zk服务中的节点, 1、查询指定节点数据 在main方法中调用 效果如下,获得了hello值 2、查询某个节点下所有子节点数据 效果如下,获得了多个节点的值 创建 效果如下,值已被更新 创建 在本例中,我们将使用 ZooKeeper 作为注册中心,实现客户端与服务端之间的RPC调用。 创建一个 创建一个 启动 查看zk集群中的节点,可见节点和数据已经创建成功 启动 至此,说明客户端与服务端之间已经可以通过zk注册中心进行正常RPC调用了。 读到了这里,那我们对于ZooKeeper常见用法应该已经有整体性的认识了~
介绍
目录
一、文件系统与监听通知机制
ZK=文件系统 + 监听通知机制
1、文件系统
znode
,可以用来保存数据(默认存储大小为1MB)。 而这些znode节点也分为四种类型
节点类型
节点描述
PERSISTENT
持久化目录节点,当客户端与 zookeeper 断开连接后,该节点依旧存在
PERSISTENT_SEQUENTIAL
持久化顺序编号目录节点,当客户端与 zookeeper 断开连接后,该节点依旧存在,只是 Zookeeper 给该节点名称进行顺序编号
EPHEMERAL
临时目录节点,当客户端与 zookeeper 断开连接后,该节点被删除
EPHEMERAL_SEQUENTIAL
临时顺序编号目录节点,当客户端与 zookeeper 断开连接后,该节点被删除,只是 Zookeeper 给该节点名称进行顺 序编号
2、监听通知机制
二、单机环境搭建
1、安装JDK
2、安装ZooKeeper
使用rz
命令,将从zk官网下载的压缩包上传至temp目录(这里使用的3.6版本)[root@localhost temp]# rz [root@localhost temp]# ll -rw-r--r--. 1 root root 12392394 3月 31 06:49 apache-zookeeper-3.6.0-bin.tar.gz
1)解压:使用命令tar -zxvf apache-zookeeper-3.6.0-bin.tar.gz -C /usr/local/
,将zookeeper解压到/usr/local/
目录下
2)重命名:mv apache-zookeeper-3.6.0-bin/ zookeeper
3、配置文件处理
ZooKeeper 启动时默认的去 conf 目录下读取zoo.cfg
配置文件,但是这个文件其实不存在,只有一个zoo_sample.cfg参考文件,所以我们先要使用 cp zoo_sample.cfg zoo.cfg
复制一份实际配置-rw-r--r--. 1 1000 mysql 535 2月 25 14:36 configuration.xsl -rw-r--r--. 1 1000 mysql 3435 2月 25 14:36 log4j.properties -rw-r--r--. 1 root root 1148 6月 7 02:19 zoo.cfg -rw-r--r--. 1 1000 mysql 1148 2月 25 14:36 zoo_sample.cfg
为了方便缓存数据管理,我们在zookeeper目录下执行mkdir data
,创建data文件夹
并且将zoo.cfg
中缓存数据目录修改为dataDir=/usr/local/zookeeper/data
5、启动服务
进入到bin
目录下,执行./zkServer.sh start
命令[root@localhost bin]# ./zkServer.sh start ZooKeeper JMX enabled by default Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg Starting zookeeper ... STARTED
./zkServer.sh status
可查看服务状态,默认端口为2181
,Mode:standalone
表示为单机模式[root@localhost bin]# ./zkServer.sh status ZooKeeper JMX enabled by default Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg Client port found: 2181. Client address: localhost. Mode: standalone
./zkServer.sh stop
3、客户端连接ZooKeeper
./zkCli.sh -server ip:port
命令,ip和port分布为需要连接的zk服务的地址和端口。如果只是连接本机zk,且使用的默认端口2181,则使用./zkCli.sh
即可。连接成功后会进入到客户端模式,Crtl + C
可退出省略.... WATCHER:: WatchedEvent state:SyncConnected type:None path:null [zk: 192.168.xx.xxx:2181(CONNECTED) 0]
三、集群环境搭建
1、角色概念
角色类型
角色描述
领导者(Leaner)
领导者负责进行投票的发起和决议,更新系统状态
跟随者(Follower)
跟随者负责接收客户端请求并返回结果,在选举过程中参与投票
观察者(ObServer)
观察者负责接收客户端连接,并将写请求转发给领导者节点。它不参与投票,只同步领导者的状态。其作用是为扩展系统,提高读的速度
2、集群搭建
1、新建目录
在/usr/local
目录下mkdir zookeepercluster
创建一个目录,方便管理3个zk服务
2、创建3个zk服务
按照之前单机版的安装方式,在zookeepercluster目录下分别创建zookeeper01、zookeeper02、zookeeper03
解压:tar -zxvf apache-zookeeper-3.6.0-bin.tar.gz -C /usr/local/zookeepercluster/
重命名:mv apache-zookeeper-3.6.0-bin/ zookeeper01
复制:cp -r zookeeper01/ zookeeper02
、cp -r zookeeper01/ zookeeper03
[root@localhost zookeepercluster]# ll drwxr-xr-x. 8 root root 157 6月 7 04:19 zookeeper01 drwxr-xr-x. 8 root root 157 6月 7 04:19 zookeeper02 drwxr-xr-x. 8 root root 157 6月 7 04:19 zookeeper03
zoo.cfg
和创建data目录
3、dataDir配置修改
改为指定路径,如zookeeper01dataDir=/usr/local/zookeepercluster/zookeeper01/data
在 zk 集群中需要为每个节点创建一个唯一标识(自然数),就是在我们之前创建的data/目录中创建一个myid 文件
,并写入一个1或2的自然数(只要数字不同就行),那我们在zookeepercluster目录下执行如下命令,分别为3个节点创建1、2、3三个唯一标识[root@localhost zookeepercluster]# echo 1 >> zookeeper01/data/myid [root@localhost zookeepercluster]# echo 2 >> zookeeper02/data/myid [root@localhost zookeepercluster]# echo 3 >> zookeeper03/data/myid
zk集群除了本身客户端监听端口外,还需要使用投票端口和选举端口,我们这里如下分配
客户端监听端口
分别为:2181、2182、2183
投票端口
分别为:2184、2185、2186
选举端口
分别为:2187、2188、2189
然后在每个zk的zoo.cfg中修改对应clientPort
,再加上如下配置即可(ip要改)server.1=ip:2184:2187 server.2=ip:2185:2188 server.3=ip:2186:2189
server.
后面的数字指myid3、服务启停
每个节点执行./zkServer.sh start
即可
方式二:
创建startall.sh
和stopall.sh
启停脚本,内容分别如下zookeeper01/bin/zkServer.sh start zookeeper02/bin/zkServer.sh start zookeeper03/bin/zkServer.sh start
zookeeper01/bin/zkServer.sh stop zookeeper02/bin/zkServer.sh stop zookeeper03/bin/zkServer.sh stop
chmod 777 st*
(777 表示文件可读可写可执行)
启动服务(记得先停掉之前单机版2181端口服务,避免端口冲突)[root@localhost zookeepercluster]# ./startall.sh ZooKeeper JMX enabled by default Using config: /usr/local/zookeepercluster/zookeeper01/bin/../conf/zoo.cfg Starting zookeeper ... STARTED ZooKeeper JMX enabled by default Using config: /usr/local/zookeepercluster/zookeeper02/bin/../conf/zoo.cfg Starting zookeeper ... STARTED ZooKeeper JMX enabled by default Using config: /usr/local/zookeepercluster/zookeeper03/bin/../conf/zoo.cfg Starting zookeeper ... STARTED
4、客户端连接
./zkCli.sh -server ip:port
命令即可四、常用操作命令
1、ls命令
ls /path
查看根节点[zk: 192.168.xx.xxx:2181(CONNECTED) 0] ls / [zookeeper]
[zk: 192.168.xx.xxx:2181(CONNECTED) 1] ls ls [-s] [-w] [-R] path
2、create命令
create [-e] [-s] /path [data]
,-e
表示临时节点,-s
表示带顺序,/path
表示路径,data
表示写入节点的数据。
持久化无序号节点:create /path data
(退出客户端后数据仍然存在)[zk: 192.168.xx.xxx:2181(CONNECTED) 3] create /testnodeA helloA Created /testnodeA [zk: 192.168.xx.xxx:2181(CONNECTED) 4] ls / [testnodeA, zookeeper]
create -s /path data
[zk: 192.168.xx.xxx:2181(CONNECTED) 5] create -s /testnodeB helloB Created /testnodeB0000000002 [zk: 192.168.xx.xxx:2181(CONNECTED) 6] ls / [testnodeA, testnodeB0000000002, zookeeper]
create -e /path data
(退出客户端后数据会自动删除【有延时】)[zk: 192.168.xx.xxx:2181(CONNECTED) 7] create -e /tempnodeA helloA Created /tempnodeA [zk: 192.168.xx.xxx:2181(CONNECTED) 8] ls / [tempnodeA, testnodeA, testnodeB0000000002, zookeeper]
create -e -s /path data
[zk: 192.168.xx.xxx:2181(CONNECTED) 2] create -e -s /tempnode helloB Created /tempnode0000000004 [zk: 192.168.xx.xxx:2181(CONNECTED) 3] ls / [tempnode0000000004, testnodeA, testnodeB0000000002, zookeeper]
3、get命令
get [-s] /path
,-s
表示获取详细信息
获取数据:get /path
[zk: 192.168.xx.xxx:2181(CONNECTED) 4] get /testnodeA helloA
get -s /path
[zk: 192.168.xx.xxx:2181(CONNECTED) 5] get -s /testnodeA helloA cZxid = 0x200000008 ctime = Sun Jun 07 07:48:56 GMT 2020 mZxid = 0x200000008 mtime = Sun Jun 07 07:48:56 GMT 2020 pZxid = 0x200000008 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 6 numChildren = 0
名称
描述
helloA
数据本身
cZxid
创建时 zxid(znode 每次改变时递增的事务 id)
ctime
创建时间
mZxid
最近一次更近的 zxid
mtime
最新更新时间
pZxid
子节点的 zxid,如果没有子节点,则就是本身节点的值
cversion
子节点更新次数
dataversion
节点数据更新次数
aclVersion
节点 ACL(授权信息)的更新次数
ephemeralOwner
如果该节点为 ephemeral 节点(临时,生命周期与session一样),ephemeralOwner 值表示与该节点绑定的sessionid。 如果该节点不是 ephemeral 节点,ephemeralOwner值为0
4、set命令
set /path [data]
往无数据节点写入数据[zk: 192.168.xx.xxx:2181(CONNECTED) 7] create /testnodeB Created /testnodeB [zk: 192.168.xx.xxx:2181(CONNECTED) 8] get /testnodeB null [zk: 192.168.xx.xxx:2181(CONNECTED) 9] set /testnodeB haha [zk: 192.168.xx.xxx:2181(CONNECTED) 10] get /testnodeB haha
[zk: 192.168.xx.xxx:2181(CONNECTED) 11] set /testnodeB heihei [zk: 192.168.xx.xxx:2181(CONNECTED) 12] get /testnodeB heihei
5、delete命令
delete /path
[zk: 192.168.xx.xxx:2181(CONNECTED) 13] delete /testnodeB [zk: 192.168.xx.xxx:2181(CONNECTED) 14] ls / [tempnode0000000004, testnodeA, testnodeB0000000002, zookeeper]
五、Java API调用ZooKeeper(实现节点增删改查)
1、引入pom依赖
<!-- 引入zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.0</version> </dependency>
2、创建节点
TestZK
测试类,这里主要有三个步骤
第一,实现Watcher 接口事件通知回调方法
第二,创建ZooKeeper 连接对象,里面需要3个参数,connectString是zk服务连接串(集群逗号隔开),sessionTimeout 是连接超时时间
第三,编写创建节点的createNode()方法,第一个参数为节点名称,第二为写入节点的数据,第四个指定节点类型(这里是持久化顺序编号节点)package com.example.demo.utils; import org.apache.zookeeper.*; /** * zookeeper节点增删改成操作 */ public class TestZK implements Watcher { /** * 事件通知回调方法 * @param watchedEvent */ @Override public void process(WatchedEvent watchedEvent) { if(watchedEvent.getState() == Event.KeeperState.SyncConnected){ System.out.println("connection success"); } } public static void main(String[] args) throws Exception{ //1.创建连接对象 String connectString = "192.168.xx.xxx:2181,192.168.xx.xxx:2182,192.168.xx.xxx:2183"; //服务连接串,集群逗号隔开 int sessionTimeout = 150000;//连接超时时间 (毫秒) ZooKeeper zooKeeper = new ZooKeeper(connectString, sessionTimeout, new TestZK()); //2.创建一个znode节点 createNode( zooKeeper); } /** * 创建一个znode节点 * 在根节点下创建一个 javaTest 节点,写入数据 hello * @param zooKeeper */ public static void createNode(ZooKeeper zooKeeper) throws Exception{ String path = zooKeeper.create("/javaTest","hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); System.out.println(path); } }
[root@localhost zookeepercluster]# firewall-cmd --zone=public --add-port=2181-2183/tcp --permanent success [root@localhost zookeepercluster]# firewall-cmd --reload success
connection success
,并输出新建的节点路径/javaTest0000000008
connection success 19:50:33.632 [main-SendThread(192.168.xx.128:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10000dc55e20006, packet:: clientPath:null serverPath:null finished:false header:: 1,1 replyHeader:: 1,8589934623,0 request:: '/javaTest,#68656c6c6f,v{s{31,s{'world,'anyone}}},2 response:: '/javaTest0000000008 /javaTest0000000008
javaTest0000000008
已创建成功[zk: 192.168.xx.xxx:2181(CONNECTED) 5] ls / [javaTest0000000008, testnodeA, testnodeB0000000002, zookeeper]
3、查询节点
创建getOneNode()
方法,查询javaTest0000000008
节点的数据/** * 查询指定节点数据 * @param zooKeeper * @throws Exception */ public static void getOneNode(ZooKeeper zooKeeper) throws Exception{ byte[] data= zooKeeper.getData("/javaTest0000000008",new TestZK(),new Stat()); System.out.println(new String(data)); }
getOneNode(zooKeeper);
connection success 20:02:13.384 [main-SendThread(192.168.xx.128:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20000dc561e0001, packet:: clientPath:null serverPath:null finished:false header:: 1,4 replyHeader:: 1,8589934625,0 request:: '/javaTest0000000008,T response:: #68656c6c6f,s{8589934623,8589934623,1591530633906,1591530633906,0,0,0,0,5,0,8589934623} hello
创建getNodeList()
方法,查询根节点下所有子节点中的数据/** * 查询某个节点下所有子节点数据 * @param zooKeeper * @throws Exception */ public static void getNodeList(ZooKeeper zooKeeper) throws Exception{ List<String> list = zooKeeper.getChildren("/",new TestZK()); for(String path :list){ byte[] data= zooKeeper.getData("/"+path,new TestZK(),null); System.out.println(new String(data)); } }
connection success 20:04:40.692 [main-SendThread(192.168.xx.128:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10000dc55e20007, packet:: clientPath:null serverPath:null finished:false header:: 1,8 replyHeader:: 1,8589934627,0 request:: '/,T response:: v{'zookeeper,'testnodeA,'testnodeB0000000002,'javaTest0000000008} 20:04:40.711 [main-SendThread(192.168.xx.128:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10000dc55e20007, packet:: clientPath:null serverPath:null finished:false header:: 2,4 replyHeader:: 2,8589934627,0 request:: '/zookeeper,T response:: ,s{0,0,0,0,0,-2,0,0,0,2,0} 20:04:40.717 [main-SendThread(192.168.xx.128:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10000dc55e20007, packet:: clientPath:null serverPath:null finished:false header:: 3,4 replyHeader:: 3,8589934627,0 request:: '/testnodeA,T response:: #68656c6c6f41,s{8589934600,8589934600,1591516136816,1591516136816,0,0,0,0,6,0,8589934600} helloA 20:04:40.722 [main-SendThread(192.168.xx.128:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10000dc55e20007, packet:: clientPath:null serverPath:null finished:false header:: 4,4 replyHeader:: 4,8589934627,0 request:: '/testnodeB0000000002,T response:: #68656c6c6f42,s{8589934601,8589934601,1591516195796,1591516195796,0,0,0,0,6,0,8589934601} helloB 20:04:40.727 [main-SendThread(192.168.xx.128:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10000dc55e20007, packet:: clientPath:null serverPath:null finished:false header:: 5,4 replyHeader:: 5,8589934627,0 request:: '/javaTest0000000008,T response:: #68656c6c6f,s{8589934623,8589934623,1591530633906,1591530633906,0,0,0,0,5,0,8589934623} hello
4、修改节点
setNode()
方法,将/javaTest0000000008
节点中的值更新为update hello
/** * 设置node中的值 * @param zooKeeper * @throws Exception */ public static void setNode(ZooKeeper zooKeeper) throws Exception{ Stat stat = zooKeeper.setData("/javaTest0000000008","update hello".getBytes(),-1); System.out.println(stat); }
[zk: 192.168.xx.128:2181(CONNECTED) 7] get /javaTest0000000008 update hello
5、删除节点
deleteNode()
方法,删除/javaTest0000000008
节点/** * 删除节点 * @param zooKeeper * @throws Exception */ public static void deleteNode(ZooKeeper zooKeeper) throws Exception{ zooKeeper.delete("/javaTest0000000008",-1); }
6、完整代码
package com.example.demo.utils; import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.util.List; /** * zookeeper节点增删改成操作 * pdfox */ public class TestZK implements Watcher { /** * 事件通知回调方法 * @param watchedEvent */ @Override public void process(WatchedEvent watchedEvent) { if(watchedEvent.getState() == Event.KeeperState.SyncConnected){ System.out.println("connection success"); } } public static void main(String[] args) throws Exception{ //1.创建连接对象 String connectString = "192.168.xx.128:2181,192.168.xx.128:2182,192.168.xx.128:2183"; //服务连接串,集群逗号隔开 int sessionTimeout = 150000;//连接超时时间 (毫秒) ZooKeeper zooKeeper = new ZooKeeper(connectString, sessionTimeout, new TestZK()); //2.创建一个znode节点 createNode( zooKeeper); //3.查询指定节点数据 // getOneNode(zooKeeper); //4.查询某个节点下所有子节点数据 // getNodeList(zooKeeper); //5.设置node中的值 // setNode(zooKeeper); //6.删除节点 // deleteNode(zooKeeper); } /** * 创建一个znode节点 * 在根节点下创建一个 javaTest 节点,写入数据 hello * @param zooKeeper */ public static void createNode(ZooKeeper zooKeeper) throws Exception{ String path = zooKeeper.create("/javaTest","hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); System.out.println(path); } /** * 查询指定节点数据 * @param zooKeeper * @throws Exception */ public static void getOneNode(ZooKeeper zooKeeper) throws Exception{ byte[] data= zooKeeper.getData("/javaTest0000000008",new TestZK(),new Stat()); System.out.println(new String(data)); } /** * 查询某个节点下所有子节点数据 * @param zooKeeper * @throws Exception */ public static void getNodeList(ZooKeeper zooKeeper) throws Exception{ List<String> list = zooKeeper.getChildren("/",new TestZK()); for(String path :list){ byte[] data= zooKeeper.getData("/"+path,new TestZK(),null); System.out.println(new String(data)); } } /** * 设置node中的值 * @param zooKeeper * @throws Exception */ public static void setNode(ZooKeeper zooKeeper) throws Exception{ Stat stat = zooKeeper.setData("/javaTest0000000008","update hello".getBytes(),-1); System.out.println(stat); } /** * 删除节点 * @param zooKeeper * @throws Exception */ public static void deleteNode(ZooKeeper zooKeeper) throws Exception{ zooKeeper.delete("/javaTest0000000008",-1); } }
六、ZooKeeper实现注册中心服务(实例)
1、示例说明
2、创建服务端
zkserver
的maven项目作为服务端,它将提供一个getFromZkserver()
查询接口,并且将接口发布到zk注册中心。(这里也要先引入zk的pom依赖)
ITestService
接口package service; import java.rmi.Remote; import java.rmi.RemoteException; /** * Remote表示定义了此接口为远程调用接口 */ public interface ITestService extends Remote { /** * 模拟一个测试查询方法,给zkclient调用 * @param s * @return * @throws RemoteException */ String getFromZkserver(String s) throws RemoteException; }
TestServiceImpl
实现类package service.impl; import service.ITestService; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class TestServiceImpl extends UnicastRemoteObject implements ITestService { public TestServiceImpl() throws RemoteException { } public String getFromZkserver(String s) throws RemoteException { return "response from zkserver : request[" + s +"]"; } }
ServerApp
主入口import org.apache.zookeeper.*; import service.ITestService; import service.impl.TestServiceImpl; import java.rmi.Naming; import java.rmi.registry.LocateRegistry; /** * 服务端主入口 */ public class ServerApp implements Watcher { /** * 事件通知回调方法 * @param watchedEvent */ public void process(WatchedEvent watchedEvent) { if(watchedEvent.getState() == Event.KeeperState.SyncConnected){ System.out.println("connection success !"); } } /** * 主方法 * @param args * @throws Exception */ public static void main(String[] args) throws Exception{ ITestService service = new TestServiceImpl(); //1.通过LocateRegistry在本机上创建Registry LocateRegistry.createRegistry(8866); String url ="rmi://localhost:8866/getMsg"; //2。使用Naming 绑定需要远程调用的方法。RMI(Remote Method Invocation) 远程方法调用 Naming.bind(url,service); //3.创建连接对象 ZooKeeper zooKeeper = new ZooKeeper("192.168.xx.128:2181,192.168.xx.128:2182,192.168.xx.128:2183" ,150000,new ServerApp()); //4.将url信息放到zookeeper的节点中 zooKeeper.create("/zkregister/testService",url.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("服务发布至zk注册中心成功"); } }
3、创建客户端
zkclient
的maven项目作为客户端,它也定义了一个名为getFromZkserver()
的查询接口,将从zk注册中心查询zkserver
发布的接口实现。
ITestService
接口package service; public interface ITestService { String getFromZkserver(String s); }
ClientApp
主入口import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import service.ITestService; import java.rmi.Naming; /** * 客户端主入口 */ public class ClientApp implements Watcher { /** * 事件通知回调方法 * @param watchedEvent */ public void process(WatchedEvent watchedEvent) { if(watchedEvent.getState() == Event.KeeperState.SyncConnected){ System.out.println("connection success !"); } } /** * 主方法 * @param args * @throws Exception */ public static void main(String[] args) throws Exception { //1.创建连接对象 ZooKeeper zooKeeper = new ZooKeeper("192.168.xx.128:2181,192.168.xx.128:2182,192.168.xx.128:2183",150000,new ClientApp()); //2.通过指定节点获取zkserver中接口提供的url信息 byte[] bytes = zooKeeper.getData("/zkregister/testService",new ClientApp(),null); String url = new String(bytes); //3.通过url找到zkserver中的远程调用对象 ITestService usersService = (ITestService) Naming.lookup(url); //4.调用对象的方法 String result = usersService.getFromZkserver("client request hello"); System.out.println(result); } }
4、调用验证
zkserver
,接口服务成功发布到zk注册中心connection success ! 服务发布至zk注册中心成功
[zk: 192.168.xx.128:2181(CONNECTED) 14] get /zkregister/testService rmi://localhost:8866/getMsg
zkclient
,调用zkserver
中getFromZkserver()
接口成功connection success ! response from zkserver : request[client request hello];
结语
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算