一、Zookeeper特性与节点说明

323 阅读11分钟

一、分布式应用程序注册中心之zookeeper


知识点:

  1. 什么是微服务的注册中心
  2. 分布式应用知识CAP理论知识
  3. 分布式系统CAP原理常见面试题和注册中心的选择

1. 什么是微服务的注册中心

注册中心:是微服务架构中的“通讯录”,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到注册中心,当一个服务需要调用其它服务时,就会到注册中心里去找服务的地址,然后进行调用。核心是通过服务注册表管理服务,通过心跳机制动态维护服务

服务提供者provider: 服务启动的时候会向注册中心上报自己的网络信息

服务消费者consumer: 服务启动的时候会向注册中心上报自己的网络信息,拉取服务提供者provider的相关网络信息

为什么要用注册中心:微服务应用和机器越来越多,调用方需要知道接口的网络地址,如果靠配置文件的方式去控制网络地址,对于动态新增机器,维护带来很大问题

2. 分布式应用知识CAP理论知识

CAP定理:指的是在一个分布式系统中,Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),三者不可同时获得。

一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(所有节点在同一时间的数据完全一致,越多节点,数据同步越耗时)

可用性(A):负载过大后,集群整体是否还能响应客户端的读写请求。(服务一直可用,而且是正常响应时间)

分区容错性(P):就是高可用性,一个节点崩了,并不影响其它的节点(100个节点,挂了几个,不影响服务,越多机器越好)

CAP理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容错性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡

3. 分布式系统CAP原理常见面试题和注册中心的选择

CA 满足的情况下,P不能满足的原因:数据同步(C)需要时间,也要正常的时间内响应(A),那么机器数量就要少,所以P就不满足

CP 满足的情况下,A不能满足的原因:数据同步(C)需要时间,机器数量多(P),但是同步数据需要时间,所以不能再正常时间内响应,所以A就不满足

AP 满足的情况下,C不能满足的原因:机器数量多(P),正常的时间内响应(A),那么数据就不能及时同步到其他节点,所以C不满足

注册中心选择:

Zookeeper:CP设计,保证了一致性,集群搭建的时候,某个节点失效,则会进行选举新的leader,或者半数以上节点不可用,则无法提供服务,因此可用性没法满足

Eureka:AP原则,无主从节点,一个节点挂了,自动切换其他节点可以使用,去中心化

结论:分布式系统中P,肯定要满足,所以只能在CA中二选一;没有最好的选择,最好的选择是根据业务场景来进行架构设计,如果要求一致性,则选择zookeeper,如金融行业,如果要去可用性,则Eureka,如电商系统

二、zookeeper概要、背景及作用


知识点:

  1. zookeeper是什么
  2. zookeeper产生背景
  3. zookeeper概要
  4. zookeeper数据模型
  5. zookeeper session机制
  6. zookeeper watcher机制

1. zookeeper是什么

zookeeper是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。

上面的解释有点抽象,简单来说zookeeper=文件系统+监听通知机制。

2. zookeeper产生背景

项目从单体到分布式转变之后,将会产生多个节点之间协同的问题。如:

  1. 每天的定时任务由谁哪个节点来执行?
  2. RPC调用时的服务发现?
  3. 如何保证并发请求的幂等
  4. ....

这些问题可以统一归纳为多节点协调问题,如果靠节点自身进行协调这是非常不可靠的,性能上也不可取。必须由一个独立的服务做协调工作,它必须可靠,而且保证性能。

3. zookeeper概要

ZooKeeper是用于分布式应用程序的协调服务。它公开了一组简单的API,分布式应用程序可以基于这些API用于同步节点状态、配置、服务注册等信息。其由JAVA编写,支持JAVA 和C两种语言的客户端。

图片

4. zookeeper数据模型

zookeeper数据模型类似于linux下的文件目录

  • 每一个节点都叫做zNode,可以有子节点,也可以有数据
  • 每个节点都能设置相应的权限控制用户的访问
  • 每个节点存储的数据不宜过大
  • 每个节点都带有一个版本号,数据变更时,版本号也会变更(乐观锁)
  • 节点分永久节点跟临时节点

zookeeper中数据的基本单元叫节点,节点之下可包含子节点,最后以树级方式程现。每个节点拥有唯一的路径path。客户端基于PATH上传节点数据,zookeeper收到后会实时通知对该路径进行监听的客户端。

图片

5. zookeeper session机制

用于客户端与服务端之间的连接,可设置超时时间,通过心跳包的机制(客户端向服务端ping包请求)进行检查,session过期后,该session创建的所有临时节点都会被抛弃

6. zookeeper watcher机制

客户端注册监听它所关心的目录节点,当目录节点发生变化(数据改变、删除、子目录节点发生增加、删除)时,zookeeper会通知客户端

对节点的watcher操作:

针对每一个节点的操作,都可以有一个监控者,当节点发送变化时,就会触发watcher事件,zk中的监听事件是一次性的,触发后立即销毁,所有有监控者的节点的变更操作都能触发watcher事件

对子节点的watcher操作:

监控父节点,当父节点对应的子节点发生变更时,父节点上的watcher事件会触发,ls或ls2指令的增删会触发watcher事件,修改则不会,如果子节点再去新增子节点,则不会触发watcher时间,即触发watcher事件一定是直系子节点

二、部署与常规配置


知识点:

  1. 版本说明
  2. 常规配置文件说明
  3. 客户端命令

zookeeper基于JAVA开发,下载后只要有对应JVM环境即可运行。其默认的端口号是2181,运行前得保证其不冲突。

1. 版本说明:

2019年5月20日发行的3.5.5是3.5分支的第一个稳定版本。此版本被认为是3.4稳定分支的后续版本,可以用于生产。基于3.4它包含以下新功能

  • 动态重新配置
  • 本地会议
  • 新节点类型:容器,TTL
  • 原子广播协议的SSL支持
  • 删除观察者的能力
  • 多线程提交处理器
  • 升级到Netty 4.1
  • Maven构建

另请注意:建议的最低JDK版本为1.8

文件说明:

  • apache-zookeeper-xxx-tar.gz 代表源代码
  • apache-zookeeper-xxx-bin.tar.gz 运行版本

下载地址:zookeeper.apache.org/releases.ht…

具体部署流程:

# 下载
$ wget https://archive.apache.org/dist/zookeeper/zookeeper-3.5.5/apache-zookeeper-3.5.5-bin.tar.gz
# 解压
$ tar -zxvf $ apache-zookeeper-3.5.5-bin.tar.gz -C /usr/local/
$ cd /usr/local/
# 创建软链接
$ ln -s apache-zookeeper-3.5.5-bin/ zk
$ cd zk/
$ cd conf/
# 拷贝默认配置
$ cp zoo_sample.cfg zoo.cfg
$ ../bin/
# 删除window命令
$ rm -rf *.cmd
# 启动
$ ./zkServer.sh start
$ ./zkCli.sh 

添加用户并授权

$ useradd zookeeper
$ cd /usr/local/
$ chown -R zookeeper:zookeeper /usr/local/zk/
$ cd zk/bin/
$ ./zkServer.sh start
$ ./zkServer.sh status
$ ./zkServer.sh stop

2. 常规配置文件说明:

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

3. 客户端命令:

# 获取帮助信息
$ ./bin/zkCli.sh h

基本命令列表

# close:关闭当前会话
$ close
# quit:退出客户端
$ quit
# connect host:port:重新连接指定Zookeeper服务
$ connect 127.0.0.1:2181

# create [-s] [-e] [-c] [-t ttl] path [data] [acl]:创建节点
$ create /qingzi "糖糖"
# delete [-v version] path:删除节点,(不能存在子节点)
$ delete /cyan/qingzi
# deleteall path:删除路径及所有子节点
$ deleteall /cyan
# set [-s] [-v version] path data:设置值
$ set /cyan "巡阴人"
# get [-s] [-w] path:查看节点数据,-s包含节点状态, -w添加监听 
$ get -s /cyan

# stat [-w] path:查看节点状态,-w添加监听
$ stat /cyan
# ls [-s] [-w] [-R] path:列出子节点,-s状态,-R递归查看所有子节点,-w 添加监听
$ ls -R /
$ ls -w /temp
# ls2 path [watch]:列出子节点以及当前节点的状态
$ ls2 /cyan
# printwatches on|off:是否打印监听事件
$ printwatches off
# history:查看执行的历史记录
$ history
# redo cmdno:重复执行命令,cmdno为history中命令编号
$ redo 4

# setAcl [-s] [-v version] [-R] path acl:为节点设置ACL权限
$ setAcl /cyan world:anyone:cdrwa
# getAcl [-s] path
$ getAcl /cyan

node数据的增删改查

# 列出子节点 
$ ls /
# 创建节点
$ create /cyan 
# 查看节点
$ get /cyan
# 设置节点数据
$ set /cyan "巡阴人"
# 创建子节点 
$ create /cyan/qingzi "xuannv"
# 删除节点
$ delete /cyan/qingzi
# 删除所有节点,包括子节点
$ deleteall /cyan

三、Zookeeper节点介绍


知识点:

  1. 节点类型
  2. 节点的监听(watch)
  3. 节点属性说明(stat)
  4. 权限设置(acl)

1. 节点类型

zookeeper中的节点叫znode,存储结构上跟文件系统类似,能够自由的增加和删除节点,不同之处在于znode没有目录的概念,不能执行类似cd之类的命令,但znode是可以存储数据的。znode结构包含如下:

  • path:唯一路径
  • childNode:子节点
  • stat:状态属性
  • type:节点类型
类型 描述
PERSISTENT 持久节点
PERSISTENT_SEQUENTIAL 持久序号节点
EPHEMERAL 临时节点(不可在拥有子节点)
EPHEMERAL_SEQUENTIAL 临时序号节点(不可在拥有子节点)
  1. PERSISTENT(持久节点)

客户端与zookeeper断开连接后,该节点依旧存在,也是默认创建的节点类型

$ create /test
  1. PERSISTENT_SEQUENTIAL(持久序号节点)

客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号。非常适合用于分布式锁、分布式选举等场景。创建时添加 -s 参数即可。

# 创建序号节点
$ create -s /test
# 返回创建的实际路径
$ created /test0000000001
create -s /test
# 返回创建的实际路径2
$ created /test0000000002
  1. EPHEMERAL(临时节点)

客户端与zookeeper断开连接后,该节点被删除。适用于心跳,服务发现等场景。创建时添加参数-e 即可。

# 创建临时节点, 断开会话,在连接将会自动删除
$ create -e /temp
$ close
$ connect 127.0.0.1:2181
  1. EPHEMERAL_SEQUENTIAL(临时序号节点)

客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。创建时添加 -e -s

$ create -e -s /temp

2. 节点的监听:

客户添加 -w 参数可实时监听节点与子节点的变化,并且实时收到通知。非常适用保障分布式情况下的数据一至性。其使用方式如下:

命令 描述
ls -w path 监听子节点的变化(增,删)
get -w path 监听节点数据的变化
stat -w path 监听节点属性的变化
printwatches on|off 触发监听后,是否打印监听事件(默认on)
$ create /temp "temp"
# 监听子节点的变化(增、删)
$ ls -w /temp
$ create -s -e /temp/app1

3. 节点属性

# 查看节点属性
$ stat /cyan

其属性说明如下表:

# 创建节点的事物ID
cZxid = 0xd
# 创建时间
ctime = Fri Sep 27 06:48:13 CST 2019
# 修改节点的事物ID
mZxid = 0xe
# 最后修改时间
mtime = Fri Sep 27 06:48:46 CST 2019
# 子节点变更的事物ID(新增与删除)
pZxid = 0xd
# 这表示对此znode的子节点进行的更改次数(新增与删除)
cversion = 0
# 数据版本,变更次数
dataVersion = 1
# 权限版本,变更次数
aclVersion = 0
# 临时节点所属会话ID
ephemeralOwner = 0x0
# 数据长度
dataLength = 2
# 子节点数(不包括子子节点)
numChildren = 0

4. 权限设置(acl)

ACL全称为Access Control List(访问控制列表),用于控制资源的访问权限。ZooKeeper使用ACL来控制对其znode的防问。基于scheme:id:permission的方式进行权限控制。scheme表示授权模式、id模式对应值、permission即具体的增删改权限位。

scheme:认证模型

方案 描述
world 开放模式,world表示全世界都可以访问(这是默认设置)
ip ip模式,限定客户端IP防问
auth 用户密码认证模式,只有在会话中添加了认证才可以防问
digest 与auth类似,区别在于auth用明文密码,而digest 用sha-1+base64加密后的密码。在实际使用中digest 更常见。

permission权限位

权限位 权限 描述
c CREATE 可以创建子节点
d DELETE 可以删除子节点(仅下一级节点)
r READ 可以读取节点数据及显示子节点列表
w WRITE 可以设置节点数据
a ADMIN 可以设置节点访问控制列表权限

acl 相关命令

命令 使用方式 描述
getAcl getAcl 读取ACL权限
setAcl setAcl 设置ACL权限
addauth addauth 添加认证用户

world权限示例:

语法: setAcl world:anyone:<权限位>

注:world模式中anyone是唯一的值,表示所有人

  1. 查看默认节点权限:
# 创建一个节点
$ create -e /testAcl
# 查看节点权限,返回的默认权限('world,'anyone: cdrwa)表示 ,所有人拥有所有权限。
$ getAcl /testAcl
  1. 修改默认权限为 读写
# 设置为rw权限
$ setAcl /testAcl world:anyone:rw
$ get /testAcl
# 无法正常创建子节点,返回没有权限的异常
Authentication is not valid : /testAcl/t
$ create -e /testAcl/t "hi"

IP权限示例:

语法:setAcl ip:<ip地址|地址段>:<权限位>

auth模式示例:

语法:

  1. setAcl auth:<用户名>:<密码>:<权限位>
  2. addauth digest <用户名>:<密码>
# 设置auth权限
$ setAcl /cyan auth:cyan:cyan:cdrwa
# 显示权限是无效的
$ Acl is not valid : /cyan
# 给当前会话添加权限帐户
$ addauth digest cyan:cyan
# 设置auth权限
$ setAcl /cyan auth:cyan:cyan:cdrwa
# 查看节点
$ getAcl /cyan

digest 权限示例:

语法:

  1. setAcl digest :<用户名>:<密钥>:<权限位>
  2. addauth digest <用户名>:<密码>

注1:密钥 通过sha1与base64组合加密码生成,可通过以下命令生成

echo -n <用户名>:<密码> | openssl dgst -binary -sha1 | openssl base64

注2:为节点设置digest权限后,访问前必须执行addauth,当前会话才可以防问。

  1. 设置digest 权限
# 先sha1加密,然后base64加密
$ echo -n cyan:123456 | openssl dgst -binary -sha1 | openssl base64
# 返回密钥
$ +jOMa+Q8mSc8dCCohMc+Il3zE+c=
# 设置digest权限
$ setAcl /cyan/cyan004 digest:cyan:+jOMa+Q8mSc8dCCohMc+Il3zE+c=:ra
  1. 查看节点将显示没有权限
# 查看节点
get getAcl /cyan/cyan004
# 显示没有权限访问
$ Authentication is not valid : /cyan/cyan004
  1. 给当前会话添加认证后在次查看
# 给当前会话添加权限帐户
$ addauth digest cyan:123456
# 再次查看
$ getAcl /cyan/cyan004
# 获得返回结果
$ 'digest,'cyan:+jOMa+Q8mSc8dCCohMc+Il3zE+c=
: ra

ACL的特殊说明:权限仅对当前节点有效,不会让子节点继承。如限制了IP防问A节点,但不妨碍该IP防问A的子节点 /A/B。