软件架构演变+zookeeper--->安装配置+数据模型+常用命令+与java交互
Posted ahcfl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件架构演变+zookeeper--->安装配置+数据模型+常用命令+与java交互相关的知识,希望对你有一定的参考价值。
一、软件架构演进
软件架构的发展经历了由单体架构、垂直架构、SOA架构到微服务架构的演进过程,
下面我们分别了解一下这几个架构。
可参考:阿里淘宝的 14 次架构演进之路
软件架构演进概览:
1. 单体架构
特点:all in one
① 所有功能集中在一个项目中
② 所有功能都要打成war包部署到服务器
③ 通过集群(session共享集群,如使用redis缓存存储session数据)来提高服务器的性能
优点:①.项目架构简单,前期开发的成本低,周期短,小型企业首选.
缺点:①全部的功能都集中在一个项目中完成,对于大型项目来说,开发难度高,不容易开发及扩展和维护
2. 垂直架构
架构说明:按照业务进行切割,形成小的单体项目。
特点:
①.以单体架构为单位进行系统的划分,划分成一个个系统.
②.项目与项目之间独立开发,开发效率高.
③.项目是以接口调用为主(早期主要使用webservice)
优点:
①.项目架构简单,前期开发的成本低,周期短,小型企业首选.
②.垂直架构进行mvc分层设计,针对分层做相应的处理做到集群(10~1000)
③.不同的项目采用不同的技术实现.
缺点:
①.全部的功能都集中在一个项目中完成,对于大型项目来说,开发难度高,不容易开发及扩展和维护.
②.集群扩展有瓶颈
②.项目与项目之间存在数据冗余,耦合度高.
②.项目是以接口调用为主,存在数据同步问题.
3. SOA架构
架构说明:将重复功能或模块抽取成组件的形式,对外提供服务,在项目与服务之间使用ESB(企业服务总线)的形式作为通信的桥梁。
特点:
①.基于soa服务思想进行功能的抽取(重复代码问题解决),以服务为中心来管理项目
②.各个系统之间要进行调用,所以出现ESB来管理项目(可以使用各种技术实现:webservice,rpc等)
③.ESB是作为系统与系统之间连接的桥梁,进行统一管理.
优点:
①.重复代码进行了抽取,提高了开发效率,提高了系统的可维护性.
②.可以针对某个系统进行扩展,做集群更容易.
③.采用ESB来管理服务组件,有利于降低企业开发项目难度
缺点:
①.系统与服务的界限模糊的,不利于设计.
②.ESB是作为系统与系统之间桥梁,没有统一标准,种类很多,不利于维护!
4. 微服务架构
架构说明:
将系统服务层完全独立出来,抽取为一个一个的微服务。
抽取的粒度更细,遵循单一原则。
采用轻量级框架协议传输。
架构优点:
服务拆分粒度更细,有利于提高开发效率。
可以针对不同服务制定对应的优化方案。
适用于互联网时代,产品迭代周期更短。
架构缺点:
粒度太细导致服务太多,维护成本高。
分布式系统开发的技术成本高,对团队的挑战大。
5. Serverless架构
减少运维,降低部署难度。
目前微服务架构开发Serverless模式的有腾讯的tsf:https://cloud.tencent.com/product/tsf
二、zookeeper分布式协调服务
1. 服务注册中心引入
问题:一旦采用分布式架构,服务都部署在不同的机器上,如何实现服务的通信呢?服务和服务之间如何进行调用的?
解决方案:
需要使用到服务注册中心了(zookeeper可以实现服务注册中心)。
采用服务中心,可以发现服务,进行服务治理。
无服务中心,服务之间调用
使用服务注册中心管理服务
2. zookeeper介绍
【1】概念
https://zookeeper.apache.org/
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。是Google的Chubby开源实现,是Hadoop和Hbase的重要组件。是一款在分布式系统中用于程序协调的软件。
提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
其由JAVA编写,支持JAVA 和C两种语言的客户端。
【2】应用场景
配置管理: 分布式集群环境下配置文件共享
分布式锁: 分布式锁实现原理
服务注册中心:
3. zookeeper安装启动停止
下载地址: https://zookeeper.apache.org/releases.html
【1】window
1.确保jdk环境变量配置正确
2.将apache-zookeeper-3.5.8-bin.tar.gz压缩文件进行解压
==注意: 不要安装在有中文和空格的目录下==
解压后目录结构:
3.在安装目录下新建一个data文件夹
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
【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
注:
-
执行完如果出现WatchedEvent state:SyncConnected type:None path:null。一直卡主住这里可以敲回车即可。
-
zookeeper默认创建了一个名称为"zookeeper"的znode节点。
停止服务
./zkServer.sh stop
4. zookeeper数据模型
【1】节点介绍
Zookeeper是一个树形目录服务, 数据模型和Linux的文件系统目录树很类似, 用一个层次化的结构存放数据。这里面的每一个节点都被称之为: ZNode(节点), 每一个节点上都会保存自己的数据和节点信息.节点可以有子节点, 同时也可以将少量数据存放在该节点上(1MB)。
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的多种方式
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创建与服务端的连接
构造函数参数说明如下:
参数名称 | 类型 | 说明 |
---|---|---|
connectString | String | 连接串,包括ip+端口 ,集群模式下用逗号隔开 192.168.148.139:2181,192.168.148.140:2181 |
sessionTimeout | **int ** | 会话超时时间,该值不能超过服务端所设置的 minSessionTimeout 和maxSessionTimeout |
watcher | Watcher | 会话监听器,服务端事件将会触发该监听 |
sessionId | **long ** | 自定义会话ID |
sessionPasswd | byte[] | 会话密码 |
canBeReadOnly | **boolean ** | 该连接是否为只读的 |
hostProvider | HostProvider | 服务端地址提供者,指示客户端如何选择某个服务来调用,默认采用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(架构师必备软件:安装Dubbo注册中心(Zookeeper-3.4.6)
自从看了大牛级大数据架构师整理的ZooKeeper安装配置!瞬间会!