- 提问:Spring Boot + Spring Cloud 和 Spring Boot + Dubbo + ZooKeeper有什么区别?
Spring Boot + Spring Cloud:组件多,功能完备;
Spring Boot + Dubbo + ZooKeeper:组件少,非能非完备;
Dubbo在2019年还算RPC通信框架,还不算是微服务架构解决方案;
而Spring Cloud算HTTP通信,已经是微服务架构解决方案了;
——————————————————
- 提问:微服务架构(分布式系统开发)最常遇到什么问题?
四大问题:
1.客户端如何访问这么多服务?
使用API网关;
2.服务和服务之间如何通信?
3.这么多服务,如何管理?
服务治理:我希望知道哪台服务器挂了我就知道:服务发现;
————————————————————————————————————
ZooKeeper (默认端口 2181)
启动/登录 ZooKeeper
cd /usr/local/zookeeper-3.4.8/bin
./zkServer.sh start
启动客户端:
./zkCli.sh
————————————————————————————————————
ZooKeeper 安装 本地模式
本地模式仅仅为了测试,如果是企业中使用,则需要分布式安装,页面搜索:
——————————————————
————————————————————————————————————
配置文件 zoo.cfg
配置文件为:zoo.cfg
路径在:/usr/local/zookeeper-3.4.8/conf/zoo.cfg
# The number of milliseconds of each tick
tickTime=2000 (毫秒)
基本事件单元(心跳)时间间隔
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
ZK 客户端初始化连接时,最多可忍受几个心跳时间间隔
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
# dataDir=/tmp/zookeeper
dataDir=/usr/local/zookeeper-3.4.8/dataDir
dataLogDir=/usr/local/zookeeper-3.4.8/dataLogDir
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
tickTime=2000
(毫秒)
基本事件单元,服务器之间或客户端之间维持心跳的时间间隔initLimit=10
ZK 客户端初始化连接时,最多可忍受几个心跳时间间隔
当已超过 10 个心跳时间:
即(ticktime)后 ZK 服务器还未收到客户端的返回
表明客户端连接失败,总时间长:1021000 = 20ssyncLimit
:
表示 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是:5*2000 = 10s
————————————————————————————————————
ZK 内部原理
——————————————————
ZK 选举机制(重点)
如何选出集群中的Leader?
集群中只有一个Leader,其他都是Follower;
(1).半数机制:
集群中半数以上的机器存活,集群可用,所以ZK适合安装【奇数台】服务器;
(2).ZK虽然在配置文件中未指定Master和Slave,但ZK工作时,存在一个节点为Leader,其他为Follower,Leader是通过内部的选举机制临时产生的;
(3).
——————————————————
节点类型
——————————————————
Stat 结构体
——————————————————
监听器原理(重点)
——————————————————
写数据流程
——————————————————
————————————————————————————————————
zkCli.sh 一个简易客户端
通过zkCli.sh
连接远程远程服务器:
zkCli.sh -timeout 0 -r -server ip:port
不填后面的参数,默认连接:localhost:2181
Linux下运行的是.sh
结尾的文件;
ZooKeeper的节点格式(类似Linux下的文件夹):
/ 父节点 / 子节点 / 子节点/...
——————————————————
启动zkCli.sh
./zkCli.sh
返回:
。。。
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
——————————————————
Znode的属性介绍
Znode就是ZooKeeper中的节点,对于程序员来说,对zk的操作主要就是对znode的操作;
Zxid
:事物ID;每个节点的改变都将产生一个唯一的Zxid:ZooKeeper Transaction id;由于Zxid的递增性质:如果zxid1小于zxid2, 那么zxid1肯定先于zxid2发生. 创建任意节点, 或者更新任意节点的数据, 或者删除任意节点, 都会导致ZK状态发生改变, 从而导致zxid的值增加。
get /路径
以及 stat /路径
时会返回如下参数列表:
其中有三个Zxid:cZxid、mZxid、pZxid;
cZxid
= 【Znode创建时的Zxid】
ctime
= 【Znode创建时间】
mZxid
=【Znode修改时的Zxid】
mtime
=【Znode最后一次更新的时间】
pZxid
=【子节点 最后一次修改时的Zxid】
cversion
=【Children子节点的版本号】当Znode的子节点有变化时,cversion 增加1
dataVersion
=【数据版本】
aclVersion
=【ACL权限版本】
ephemeralOwner
=【临时节点的Zxid】(若当前非临时节点,该字段值为0)
dataLength
=【数据内容的长度】
numChildren
=【子节点数量】
——————————————————
zkCli的操作
输入.zkCli.sh h
返回【帮助信息】:
stat path [watch]
set path data [version] 修改参数
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl 创建子节点
addauth scheme auth
quit 退出ZooKeeper
getAcl path
close 关闭当前连接
connect host:port
——————————————————
close
和qiut
的区别:
输入close前:
[zk: localhost:2181(CONNECTED) 3]
输入close后:
[zk: localhost:2181(CLOSED) 4]
注意:close连接后,所有临时节点都会被销毁;
quit:退出ZooKeeper;
——————————————————
create [-s] [-e] path data acl
创建子节点
-s
创建顺序节点;
-e
创建临时节点;
path
表示路径(路径必须加上斜杠,不然报错IllegalArgumentException)
data
表示数据;
acl
权限控制;
若不指定,则表示持久节点;
比如:create -s /class class
(路径为/class 数据为class)
[zk: localhost:2181(CONNECTED) 0] create -s /class class
Created /class0000000002 返回节点路径
[zk: localhost:2181(CONNECTED) 1] create -s /class1 class1
Created /class10000000003 返回节点路径
——————————————————
ls path [watch]
查看子节点
ls /
——————————————————
- (1).获取节点的子节点;
[zk: localhost:2181(CONNECTED) 2] ls /
[dubbo, class0000000002, zookeeper, class10000000003]
——————————————————
- (2).
get 路径 [watch]
获取节点的数据;
返回节点Value + 节点状态(stat
)
[zk: localhost:2181(CONNECTED) 8] get /class0000000002
class
cZxid = 0x6a
ctime = Sun Aug 04 22:58:24 CST 2019
mZxid = 0x6a
mtime = Sun Aug 04 22:58:24 CST 2019
pZxid = 0x6a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
——————————————————
- (3).
stat 路径
查看节点状态;(注意是:stat,而非state!!!)
ZK中每一次创建一个节点都是一个事物,这个时候ZK就会帮我们记录事物ID;
[zk: localhost:2181(CONNECTED) 5] stat /class10000000003
cZxid = 0x6b
ctime = Mon Aug 05 00:13:34 CST 2019
mZxid = 0x6b
mtime = Mon Aug 05 00:13:34 CST 2019
pZxid = 0x6b
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
——————————————————
- (4).
ls2 path [watch]
获取节点的子节点,以及 当前节点的状态;
我们先在class0000000002
下创建一个临时子节点yau
,赋值yau_value
:
[zk: localhost:2181(CONNECTED) 9] create -e /class0000000002/yau yau_value
Created /class0000000002/yau
[zk: localhost:2181(CONNECTED) 12] ls2 /class0000000002
[yau]
cZxid = 0x6a
ctime = Sun Aug 04 22:58:24 CST 2019
mZxid = 0x6a
mtime = Sun Aug 04 22:58:24 CST 2019
pZxid = 0x6c
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
n