软件架构演变+zookeeper--->安装配置+数据模型+常用命令+与java交互

一、软件架构演进

软件架构的发展经历了由单体架构、垂直架构、SOA架构到微服务架构的演进过程,

下面我们分别了解一下这几个架构。

可参考阿里淘宝的 14 次架构演进之路

软件架构演进概览:

image-20210616193754993

1. 单体架构

image-20210616194119788
特点:all in one
① 所有功能集中在一个项目中
② 所有功能都要打成war包部署到服务器
③ 通过集群(session共享集群,如使用redis缓存存储session数据)来提高服务器的性能

优点:①.项目架构简单,前期开发的成本低,周期短,小型企业首选.
缺点:①全部的功能都集中在一个项目中完成,对于大型项目来说,开发难度高,不容易开发及扩展和维护

2. 垂直架构

image-20210616194417124

架构说明:按照业务进行切割,形成小的单体项目。

特点:
    ①.以单体架构为单位进行系统的划分,划分成一个个系统.
    ②.项目与项目之间独立开发,开发效率高.
    ③.项目是以接口调用为主(早期主要使用webservice)
    
优点:
    ①.项目架构简单,前期开发的成本低,周期短,小型企业首选.
    ②.垂直架构进行mvc分层设计,针对分层做相应的处理做到集群(10~1000)
    ③.不同的项目采用不同的技术实现. 
缺点:
    ①.全部的功能都集中在一个项目中完成,对于大型项目来说,开发难度高,不容易开发及扩展和维护.
    ②.集群扩展有瓶颈
    ②.项目与项目之间存在数据冗余,耦合度高.
    ②.项目是以接口调用为主,存在数据同步问题.

3. SOA架构

image-20210616194718951
架构说明:将重复功能或模块抽取成组件的形式,对外提供服务,在项目与服务之间使用ESB(企业服务总线)的形式作为通信的桥梁。

特点:
    ①.基于soa服务思想进行功能的抽取(重复代码问题解决),以服务为中心来管理项目
    ②.各个系统之间要进行调用,所以出现ESB来管理项目(可以使用各种技术实现:webservice,rpc等)
    ③.ESB是作为系统与系统之间连接的桥梁,进行统一管理.

优点:
    ①.重复代码进行了抽取,提高了开发效率,提高了系统的可维护性.
    ②.可以针对某个系统进行扩展,做集群更容易.
    ③.采用ESB来管理服务组件,有利于降低企业开发项目难度 

缺点:
    ①.系统与服务的界限模糊的,不利于设计.
    ②.ESB是作为系统与系统之间桥梁,没有统一标准,种类很多,不利于维护!

4. 微服务架构

image-20210616195323239 image-20210616195217990
架构说明:
将系统服务层完全独立出来,抽取为一个一个的微服务。
抽取的粒度更细,遵循单一原则。
采用轻量级框架协议传输。

架构优点:
服务拆分粒度更细,有利于提高开发效率。 
可以针对不同服务制定对应的优化方案。
适用于互联网时代,产品迭代周期更短。

架构缺点:
粒度太细导致服务太多,维护成本高。 
分布式系统开发的技术成本高,对团队的挑战大。

5. Serverless架构

image-20210616195841135

减少运维,降低部署难度。

目前微服务架构开发Serverless模式的有腾讯的tsf:https://cloud.tencent.com/product/tsf

二、zookeeper分布式协调服务

1. 服务注册中心引入

问题:一旦采用分布式架构,服务都部署在不同的机器上,如何实现服务的通信呢?服务和服务之间如何进行调用的?

解决方案:
需要使用到服务注册中心了(zookeeper可以实现服务注册中心)。
 采用服务中心,可以发现服务,进行服务治理。

无服务中心,服务之间调用

image-20210616200506888

使用服务注册中心管理服务

image-20210616200602863

2. zookeeper介绍

【1】概念

https://zookeeper.apache.org/

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。是Google的Chubby开源实现,是Hadoop和Hbase的重要组件。是一款在分布式系统中用于程序协调的软件
提供的功能包括:配置维护、域名服务、分布式同步、组服务等
其由JAVA编写,支持JAVA 和C两种语言的客户端。

【2】应用场景

配置管理: 分布式集群环境下配置文件共享

image-20210324091227584

分布式锁: 分布式锁实现原理

image-20210616201906677

服务注册中心:

image-20210616201849896

3. zookeeper安装启动停止

下载地址: https://zookeeper.apache.org/releases.html

【1】window
1.确保jdk环境变量配置正确
2.将apache-zookeeper-3.5.8-bin.tar.gz压缩文件进行解压
==注意: 不要安装在有中文和空格的目录下==

解压后目录结构:

image-20210616202141725

3.在安装目录下新建一个data文件夹

image-20210616202232526

4.进入conf文件夹并将zoo_samle.cfg文件复制一份重命名为zoo.cfg

5.编辑并修改zoo.cfg文件内容中dataDir目录地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IHoX7FaM-1624429525215)(C:/Users/16096/Desktop/java127/Zookeeper/img/18.png)]

配置说明:

# zookeeper时间配置中的基本单位 (毫秒)
tickTime=2000
# 允许follower初始化连接到leader最大时长,它表示tickTime时间倍数 即:initLimit*tickTime
initLimit=10
# 允许follower与leader数据同步最大时长,它表示tickTime时间倍数 
syncLimit=5
#zookeper 数据存储目录
dataDir=/tmp/zookeeper
#对客户端提供的端口号
clientPort=2181
#单个客户端与zookeeper最大并发连接数
#maxClientCnxns=60
# 保存的数据快照数量,之外的将会被清除
#autopurge.snapRetainCount=3
#自动触发清除任务时间间隔,小时为单位。默认为0,表示不自动清除。
#autopurge.purgeInterval=1

6.启动服务端 ,找到bin目录下zkServer.cmd,双击运行。

注意:

1.此版本zookeeper启动会默认占用8080端口,如果你当前8080端口被占用了,那么启动的时候会闪退,cmd窗口会自动关闭,此时可以在zoo.cfg配置文件里面最后一行添加admin.serverPort=8123,然后再双击zkServer.cmd运行就ok了。

2.dataDir路径配置的一定不要包含中文,并且路径使用’\‘不要使用’/’。

7.客户端访问,在bin目录下双击zkCli.cmd

image-20210616202830754

【2】linux

这里以centos7为例,确保虚拟中安装了jdk8及以上版本

1、下载安装包,上传到 /opt 目录下,解压缩文件

tar -zxvf apache-zookeeper-3.5.8-bin.tar.gz

2、解压后的文件夹移动到 /usr/local 目录下 并重新命名

mv apache-zookeeper-3.5.8-bin /usr/local/zookeeper

3、进入zookeeper目录,创建数据存放目录

cd /usr/local/zookeeper/
mkdir data

4、进入conf目录,将文件zoo_sample.cfg备案一份,文件名为zoo.cfg

cd conf
cp zoo_sample.cfg zoo.cfg

5、修改zoo.cfg配置文件,修改dataDir属性为自己的目录地址:

vi zoo.cfg

启动zookeeper服务端

# 先切换到zookeeper的bin目录
cd /usr/local/zookeeper/bin/
# 执行脚本
./zkServer.sh start

启动zookeeper客户端

# 同样在bin目录下执行
./zkCli.sh

注:

  1. 执行完如果出现WatchedEvent state:SyncConnected type:None path:null。一直卡主住这里可以敲回车即可。

  2. zookeeper默认创建了一个名称为"zookeeper"的znode节点。

停止服务

./zkServer.sh stop

4. zookeeper数据模型

【1】节点介绍

Zookeeper是一个树形目录服务, 数据模型和Linux的文件系统目录树很类似, 用一个层次化的结构存放数据。这里面的每一个节点都被称之为: ZNode(节点), 每一个节点上都会保存自己的数据和节点信息.节点可以有子节点, 同时也可以将少量数据存放在该节点上(1MB)。

image-20210616204435677

image-20210615100829981

zookeeper存储的数据节点 都是以/ 开头 以树状结构进行存储数据!

并且zookeeper对所在的节点和数据 自带监控功能,可以随时监听到数据节点和存储数据的变化。

【2】 节点分类

Zookeeper的节点分为四大类

Persistent [pəˈsɪstənt] : 持久化节点【默认】 创建的节点永久保存
Ephemeral [ɪˈfemərəl] :临时节点 【-e】      创建的节点为临时的,当客户端重启时节点消失
Persistent_Sequential :持久化顺序节点 【-s】 创建的节点持久且有序
Ephemeral_Sequential [sɪˈkwenʃl] 临时顺序节点 【-es】 创建的节点临时且有序

-e: 临时
-s:  持久顺序
-es: 临时顺序

操作Zookeeper的多种方式

image-20210616204953324

5、zookeeper常用命令

通过命令可以操作Zookeeper上的各个节点

# 查看帮助
help 

# create 命令  注:当服务器重启时,所有的临时节点都会消失
create /节点路径			     # 【持久节点】创建空节点
create /节点路径 值 		        # 【持久节点】创建节点,并赋值
create -e /节点路径			     # 【临时节点】创建空节点
create -e /节点路径 值		    # 【临时节点】创建节点,并赋值
create -s /节点路径			     # 【持久顺序节点】创建空节点
create -s /节点路径	值		    # 【持久顺序节点】创建节点,并赋值
create -es /节点路径			 # 【临时顺序节点】创建空节点
create -es /节点路径	值		# 【临时顺序节点】创建节点,并赋值
例如:
create app1_cj
create app2_cj 200
create -e app3_cj 300

# set 命令
set /节点路径 value		// 给指定的节点设置值
set -s /节点路径 value	// 设置完值后查看节点状态
set -v version /节点路径 value // 设置当前节点的值
说明:
version:这个版本值 
值为当前版本号: 在当前版本号的基础上+1
值为-1: 在当前版本号的基础上+1 
使用这两个命令可查看当前版本
ls -s  /节点路径
set -s /节点路径 value  
例如:
set -v 0 app1_cj 100  # 那么 app1_cj的dataVersion版本就变为了 0+1

# ls 命令
ls /节点路径	// 查看目标节点下所有的子节点
ls -s /节点路径  // 查看节点详细信息
ls -w /节点路径		// 一次性监控节点状态(监控节点的删除)
ls -R /节点路径		// 递归罗列所有子节点
-------------------------------------------
cZxid = 0x24  //创建节点的事物ID
ctime = Mon Aug 10 16:45:17 CST 2020 //创建时间
mZxid = 0x26 //修改节点的事物ID
mtime = Mon Aug 10 16:46:39 CST 2020 //修改时间
pZxid = 0x24 //子节点变更的事物ID
cversion = 0 //这表示对此znode的子节点进行的更改次数(不包括子节点)
dataVersion = 1 // 数据版本,变更次数
aclVersion = 1 //权限版本,变更次数
ephemeralOwner = 0x0 //临时节点所属会话ID
dataLength = 3 //数据长度
numChildren = 0 //子节点数(不包括子子节点)
-------------------------------------------

# get命令
get /节点名       # 获取指定节点上的值
get -s /节点路径  # 获取值的同时查看节点状态
get -w /节点路径  # 一次性监控当前节点数据的变化

# 其他
stat /节点路径   # 查看节点属性
delete /节点路径	# 删除单个节点
deleteall /节点路径  # 删除带有子节点的节点
close   # 输入命令后会一直卡着,可以敲一下回车键回到客户端命令模式。
connect # 连接命令,如close完了以后想重新建立连接可以输入此命令
quit    # 退出当前客户端

三、Java客户端操作Zookeeper(了解)

已经了解通过zookeeper自带的zkCli客户端来操作zookeeper节点,那么我们怎么使用我们的java程序来操作我们的zookeeper呢。

java操作Zookeeper的方式有多种: (了解)

​ Apache Zookeeper提供的名称为Zookeeper类作为java客户端操作

​ 第三方提供的ZkClient作为java客户端操作Zookeeper

​ Apache Zookeeper提供的Curator框架

1. Zookeeper类操作zookeeper节点

Zookeeper客户端API ,核心类:org.apache.zookeeper.ZooKeeper创建与服务端的连接

构造函数参数说明如下:

参数名称类型说明
connectStringString连接串,包括ip+端口 ,集群模式下用逗号隔开 192.168.148.139:2181,192.168.148.140:2181
sessionTimeout**int **会话超时时间,该值不能超过服务端所设置的 minSessionTimeout 和maxSessionTimeout
watcherWatcher会话监听器,服务端事件将会触发该监听
sessionId**long **自定义会话ID
sessionPasswdbyte[]会话密码
canBeReadOnly**boolean **该连接是否为只读的
hostProviderHostProvider服务端地址提供者,指示客户端如何选择某个服务来调用,默认采用StaticHostProvider实现

pom依赖:Zookeeper客户端的pom依赖

<dependencies>
	<dependency>
		<groupId>org.apache.zookeeper</groupId>
		<artifactId>zookeeper</artifactId>
		<version>3.5.8</version>
	</dependency>
</dependencies>

创建 ZookeeperDemo类 演示 创建 PERSISTENT 节点:

1.创建maven项目,导入客户端maven依赖
2.创建zookeeper连接对象
3.通过zookeeper对象发送命令
4.关闭连接
package com.ahcfl.zookeeper;

import org.apache.zookeeper.*;
import java.util.Scanner;

public class ZookeeperDemo {
    // Zookeeper创建连接的方式是异步的.
    // 需要让main方法等待,我们使用了等待键盘录入
    public static void main(String[] args) throws Exception{
        //1.创建zookeeper对象,用于连接Zookeeper服务器
        // 参数1: 服务器地址:端口
        // 参数2: 会话连接超时时间
        // 参数3: 监控zookeeper对象的连接状态
        ZooKeeper zooKeeper = new ZooKeeper("127.0.0.1:2181", 1000,
                new Watcher() {
                    public void process(WatchedEvent event) {
                        if(event.getState()==Event.KeeperState.SyncConnected){
                            //   链接成功    线程放行
                            System.out.println("=======创建链接完毕======"+event.getState());
                        }
                    }
                }
        );
        System.in.read();//  主线程阻塞 :等待输入
        //2.判断/tps节点是否存在,不存在则创建
        // 如果节点不存在 返回null
        if(zooKeeper.exists("/tps",false) == null){
            // 当 /tps 节点不存在是则创建节点,并设置值
            // 参数1: 节点路径
            // 参数2: 节点数据
            // 参数3: Access Control: 访问节点的权限控制
                    //  OPEN_ACL_UNSAFE :完全开放
                    //  CREATOR_ALL_ACL :给创建该znode连接所有权限
                    //  READ_ACL_UNSAFE :所有的客户端都可读
            // 参数4: 节点类型
            zooKeeper.create("/tps",
                    "hello zookeeper".getBytes(),
                    ZooDefs.Ids.OPEN_ACL_UNSAFE,
                    CreateMode.PERSISTENT);
            System.out.println("/tps 节点创建完成-- ");
        }
        zooKeeper.close();//  关闭链接
    }
}

可以 ls /查看 get /tps获取值

【1】创建节点
ZooKeeper zooKeeper;

@Before
public void  before(){
    //1.zookeeper连接服务器
    try {
        zooKeeper  = new ZooKeeper("127.0.0.1:2181", 1000,
                new Watcher() {
                    public void process(WatchedEvent event) {
                        if(event.getState()==Event.KeeperState.SyncConnected){
                            //   链接成功    线程放行
                            System.out.println("=======创建链接完毕======"+event.getState());
                        }

                    }
                }
        );
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * 创建持久节点
 */
@Test
public void test0() throws Exception {
    if(zooKeeper.exists("/tps-p1",false)==null){
        // 创建节点
        String result = zooKeeper.create(
            "/tps-p1",
            "持久节点信息".getBytes("utf-8"),
            ZooDefs.Ids.OPEN_ACL_UNSAFE,
            CreateMode.PERSISTENT
        );
        System.out.println("/tps-p1 创建成功: "+result);
    }
}

/**
 * 创建持久有序节点
 */
@Test
public  void  test1(){
    try {
        if(zooKeeper.exists("/tps-p1",false) == null){
            //  返回值 就是节点的路径
            String path = zooKeeper.create("/tps-p1", "hello pesistent order".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
            System.out.println("/tps-p1 节点创建完成-- "+path);
            byte[] data = zooKeeper.getData(path,null, null);
            System.out.println("/tps-e 持久有序节点数据 -- "+new String(data));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

// 同上:
// CreateMode.EPHEMERAL 创建临时节点
// CreateMode.EPHEMERAL_SEQUENTIAL 创建临时有序节点
    
@After
public  void  after(){
    try {
        zooKeeper.close();//  关闭链接
    } catch (Exception e) {
        e.printStackTrace();
    }
}
【2】更新节点

注意参数3 :

version 版本一致才可以更新节点数据: 每次更新 版本号自动+1

如果我们在调用api 传递version=-1 那么版本号不参与更新!不会自动+1

@Test  //  更新节点数据
public  void  test4(){
    try {
        // 参数1: 节点路径/名称
        // 参数2: 设置的节点数据
        // 参数3: 节点版本
        //      节点的当前版本  或  -1
        zooKeeper.setData("/tps-p/node","xixi".getBytes(),-1);
        System.out.println("设置成功...");
    } catch (Exception e) {
        e.printStackTrace();
    }
}
【3】删除节点
@Test  //  删除节点
public  void  test5(){
    try {
        zooKeeper.delete("/tps-p/node",-1);
        System.out.println("删除成功...");
    } catch (Exception e) {
        e.printStackTrace();
    }
}
【4】获取节点
@Test  //  获取节点内容数据
public  void  test6(){
    try {
        // 创建点击状态对象,用于存放查询的节点状态信息
        Stat state = new Stat();
        byte[] data = zooKeeper.getData("/tps-p", false, state);
        System.out.println("获取数据:"+new String(data));
        System.out.println("获取数据版本号:"+state.getVersion());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
【5】获取子节点数据

在 /tps-p 节点下创建两个节点 p1和p2 数据内容分别是 : nihao p1 和 nihao p2

@Test  //  获子取节点内容数据
public  void  test7(){
    try {
        // 存放节点信息
        Stat parent_state = new Stat();
        // 获取所有子节点名称
        List<String> children = zooKeeper.getChildren("/tps-p", false,parent_state);
        for (String child : children) {
            Stat son_state = new Stat(); // 子节点的状态
            byte[] data = zooKeeper.getData("/tps-p/" + child, false, son_state);
            System.out.println("子节点路径/名称:/tps-p/"+child);
            System.out.println("子节点获取数据:"+new String(data));
            System.out.println("获取数据版本号:"+son_state.getVersion());
            System.out.println("+++++++++++++++++++++++++");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
【6】监听节点数据变化

监听节点

执行下面代码: 进入阻塞监听状态,在客户端窗口 设置节点数据进行测试

@Test  //  监听节点数据变化
public  void  test8(){
    try {
        Stat state = new Stat();
        // 参数1: 节点路径/名称
        // 参数2: 编写监听对象 对节点数据进行监听
        zooKeeper.getData("/tps-p", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println(event);
                //  当节点数据变化  该方法会自动执行
                System.out.println("节点数据变化一次"+event.getState());
            }
        },state);
        System.in.read(); //  当前线程阻塞 一直监听
    } catch (Exception e) {
        e.printStackTrace();
    }

}

监听子节点数据变化(了解)

@Test  //  监听子节点以及子节点数据变化
public  void  test9(){
    try {
        Stat state = new Stat();
        // 获取所有子节点名称
        List<String> children = zooKeeper.getChildren("/tps-p", false, state);

        for (String child : children) {
            zooKeeper.getData("/tps-p/" + child, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    String childPath = event.getPath();
                    try {
                        byte[] data = zooKeeper.getData( childPath, null, state);
                        System.out.println("子节点:" + childPath + " 节点数据变化了。。。。" + new String(data));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, state);

        }
        System.out.println("'-----我在等待更新----------");
        System.in.read(); //  当前线程阻塞 一直监听
    } catch (Exception e) {
        e.printStackTrace();
    }

}

2. 第三方ZKClient操作Zookeeper(了解)

zkClient 是在zookeeper客户端基础之上封装的,使用上更加友好

主要变化如下:

  • 可以设置持久监听,或删除某个监听
  • 可以插入JAVA对象,自动进行序列化和反序列化
  • 简化了基本的增删改查操作。
【1】zkClient创建节点

添加maven依赖:

  <dependencies>        <dependency>            <groupId>com.101tec</groupId>            <artifactId>zkclient</artifactId>            <version>0.10</version>        </dependency>    </dependencies>

测试

package com.ahcfl.zk;

import org.I0Itec.zkclient.ZkClient;

public class ZkClient1 {
    public static void main(String[] args) {
        //1.连接服务器
        ZkClient zkClient = new ZkClient("127.0.0.1:2181");
        if(zkClient.exists("/zkclient") == false){
            zkClient.createPersistent("/zkclient","hello zkclient");
        }
        //读取znode数据
        String data = zkClient.readData("/zkclient");
        System.out.println("data:" + data);
    }
}
【2】zkClient 存储对象数据

实体类序列化

package com.ahcfl.pojo;

import java.io.Serializable;

@Data // 导入lombok依赖
public class User implements Serializable {
    private  Long  id;
    private  String name;
}

测试

package com.ahcfl.zk;

import com.itheima.pojo.User;
import org.I0Itec.zkclient.ZkClient;

public class ZkClient2 {
    public static void main(String[] args) {
        //1.连接服务器
        ZkClient zkClient = new ZkClient("127.0.0.1:2181");
        // 2. 创建节点 赋值
        if(zkClient.exists("/zkclient1") == false){
            User user = new User();
            user.setId(1L);
            user.setName("李四");
            zkClient.createPersistent("/zkclient1",user);
        }
        //3. 读取znode数据
        User data = zkClient.readData("/zkclient1");
        System.out.println("data:" + data);
    }
}
【3】监听节点数据

字符串序列化

package com.ahcfl.pojo;

import org.I0Itec.zkclient.exception.ZkMarshallingError;
import org.I0Itec.zkclient.serialize.ZkSerializer;

import java.io.UnsupportedEncodingException;

/**
 * 解决 控制台监听序列化问题
 */
public class StringValueSerializer implements ZkSerializer {

    private String charset = "UTF-8";

    public StringValueSerializer(){}

    public StringValueSerializer(String charset){
        this.charset = charset;
    }
    public byte[] serialize(Object data) throws ZkMarshallingError {
        try{
            byte[] bytes = String.valueOf(data).getBytes(charset);
            return bytes;
        }catch (UnsupportedEncodingException e){
            throw new ZkMarshallingError("Wrong Charset:" + charset);
        }
    }

    public Object deserialize(byte[] bytes) throws ZkMarshallingError {
        String result = null;
        try {
            result = new String(bytes,charset);
        } catch (UnsupportedEncodingException e) {
            throw new ZkMarshallingError("Wrong Charset:" + charset);
        }
        return result;
    }
}

对已经创建的节点进行监听

package com.ahcfl.zk;

import com.ahcfl.pojo.StringValueSerializer;
import com.ahcfl.pojo.User;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import java.io.IOException;

public class ZkClient3 {
    public static void main(String[] args) throws IOException {
        //1.连接服务器
        ZkClient zkClient = new ZkClient("127.0.0.1:2181");
        // TODO:设置序列化工具类,用于将存放和取出的数据进行序列化操作
        zkClient.setZkSerializer(new StringValueSerializer());

        //监听数据变化
        zkClient.subscribeDataChanges("/zk", new IZkDataListener() {
            // 处理数据的改变
            public void handleDataChange(String dataPath, Object data) throws Exception {
                System.out.println("被监听的节点路径: " + dataPath);
                System.out.println("被监听的节点数据: " + data);
            }
            //  监听节点是否被删除
            public void handleDataDeleted(String dataPath) throws Exception {
                System.out.println("监听到节点删除了....");
                System.out.println("dataPath: " + dataPath);
            }
        });
        System.out.println("我正在监听--------------");
        System.in.read();
        zkClient.close();
    }
}
【4】监听子节点数据

准备 : 在zk节点下:创建两个子节点,分别赋值。

package com.ahcfl.zk;

import com.ahcfl.pojo.StringValueSerializer;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;

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

public class ZkClient4 {
    public static void main(String[] args) throws IOException {
        //1.连接服务器
        ZkClient zkClient = new ZkClient("127.0.0.1:2181");
        zkClient.setZkSerializer(new StringValueSerializer());

        //监听子节点变化
        List<String> children = zkClient.subscribeChildChanges("/zk", (parentPath, currentChilds) ->{
            System.out.println("父节点路径 : " + parentPath);
            System.out.println("当前子节点 : " + currentChilds);
        });

        //监听子节点数据变化
        for (String child : children) {
            System.out.println("-------");
            zkClient.subscribeDataChanges("/zk/"+child, new IZkDataListener() {
                public void handleDataChange(String dataPath, Object data) throws Exception {
                    System.out.println("目标子节点路径::" + dataPath);
                    System.out.println("目标子节点更新数据 :" + data);
                }
                //  处理子节点数据监听
                public void handleDataDeleted(String dataPath) throws Exception {
                    System.out.println("handleDataDeleted-----");
                    System.out.println("dataPath:" + dataPath);
                }
            });
        }
        System.out.println("我正在监听--------------");
        System.in.read();//  线程阻塞
        zkClient.close();
    }
}
【5】特殊字符处理

如果zookeeper 创建节点需要使用特殊字符拼接:特殊字符需要转义编码

特殊字符 =》十六进制

package com.ahcfl.zk;

import org.I0Itec.zkclient.ZkClient;

public class ZkClient5 {
    public static void main(String[] args) {
        //1.连接服务器
        ZkClient zkClient = new ZkClient("127.0.0.1:2181");
        // 判断节点是否存在
        // 节点路径: /http://127.0.0.1:8080/findAll
        if(zkClient.exists("/http%3A%2F%2F127.0.0.1%3A8080%2FfindAll") == false){
            // 创建持久化节点
            zkClient.createPersistent("/http%3A%2F%2F127.0.0.1%3A8080%2FfindAll","hello zkclient 李四");
            // 调用zkClient的createXxx相关方法完成不同类节点的创建
        }
        //读取znode数据
        String data = zkClient.readData("/http%3A%2F%2F127.0.0.1%3A8080%2FfindAll");
        System.out.println("data:" + data);
    }
}
image-20210616215000808

总结

Zookeeper:
		ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务
Zookeeper作用:
		配置管理
    分布式锁
    服务注册中心
     		
Zookeeper数据单元
    Zookeeper存放数据时,是以树形结构存放的
    在树形结构上存放有很多的节点(Znode)
    节点: 保存数据的位置
				节点路径(节点名称)
        节点数据
        节点信息
    节点分类:
				持久化节点:
        临时节点: -e
        持久顺序节点: -s
        临时顺序节点: -es
操作Zookeeper:
	  安装: windows和Linux使用的是同一个压缩包,直接解压即可
    配置数据存放的位置:
				创建data
        编写zoo.cfg核心配置文件
          	在配置文件中配置数据存放的路径 \
        Zookeeper启动时内部会占用8080端口,我们可以在zoo.cfg中进行修改
          	admin.serverPort=8123
		Zookeeper的端口为: 2181
    Zookeeper启动服务器:
				window版本: 双击 zkServer.cmd
    Zookeeper启动客户端:
				window版本: 双击 zkClient.cmd
		zkCli: Zookeeper提供的客户端
      	以命令的方式操作 ★
    javaAPI:
				ZookeeperAPI:
						Apache提供的
        zkClient: 第三方提供的java代码操作Zookeeper的工具
        		循环监控
        curator: 
						Apache提供的curator框架
--------------------
Zookeeper相关命令:
	help : 帮助
  create:
			创建持久节点
          create /节点路径
          create /节点路径 value
      创建临时节点
          create -e /节点路径
          create -e /节点路径 value
      创建持久有序节点
          create -s /节点路径 
          create -s /节点路径 value
      创建临时有序节点
          create -es /节点路径 
          create -es /节点路径 value
    ls:
			ls /节点路径	// 查看目标节点下所有的子节点
      ls -s /节点路径  // 查看节点详细信息
      ls -w /节点路径		// 一次性监控节点状态(监控节点的删除)
      ls -R /节点路径		// 递归罗列所有子节点
   	get:
			get /节点路径  // 获取指定节点的值
      get -s /节点路径  // 获取指定节点的详情
      get -w /节点路径 // 对节点进行一次监控,监控修改
    set:
			set /节点路径 value // 设置节点的值
      set -s /节点路径 value // 设置指定节点的值,并展示详情 
      set -v 版本号 /节点路径 值 // 指定版本进行设置
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值