ZooKeeper介绍
简介说明
官网解释 “ZooKeeper是一个分布式,开源的分布式应用程序协调服务,Google的Chubby一个开源的实现;它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作” 。
借鉴网上的一个说法就是:ZooKeeper是一种为分布式应用所设计的高可用(集群)、高性能(分布式锁)且一致的开源协调服务,它提供了一项基本服务:分布式锁服务。由于ZooKeeper的开源特性,后来我们的开发者在分布式锁的基础上,摸索了出了其他的使用方法:配置维护、组服务、分布式消息队列、分布式通知/协调等。目前主要的注册中心有zookeeper、eureka、consul、etcd等开源框架实现,也有一个互联网公司自研的,如美团的MNS。
借用zookeeper开源框架接口,我们可以从抽象角度去理解注册中心(但并不是为注册而设计的zk),他为我们提供了如下几种接口:
- void registry(URL url) 向注册中心注册服务
- void unregistry(URL url) 向注册中心接注册服务
- void available(URL url) 将服务设置为可用,供客户端调用
- void unavailable(URL url) 禁用服务,客户端无法发现该服务
- Collection<URL> getRegisteredServiceUrls() 获取已经注册的服务集合
- void subscribe(URl url, NotifyListener listener) 订阅服务,并添加监听器
- void unsubscribe(URL url, NotifyListener listener) 取消订阅
- List<URL> discover(URL url) 发现服务列表
由上面介绍可知,不管是注册还是发现,或是调用,都是基于url参数传递的,而这个url就是是传输协议上一个URL类的实例化参数,它包括了像协议名称、域名、端口、路径、协议参数等信息。总之,zookeeper可以简单理解为一个存储介质,给服务提供者和消费者共同连接,而这个存储介质上面的信息,就是上面谈到的URL。
以下,附上zookeeper在系统中的调用图:
数据模型
注册信息
通常,我们使用zookeeper客户端去查询一个zookeeoer服务时,会看到他的一些URL信息和节点信息:
从上面的注册流程可知,但我们去查询某个服务节点信息是:ls /edsp/4030/providers,我们可以知道4030接口所包含的ServiceUrl的信息:协议(http)、ip(10.22.60.6)、port(29021)、serviceId(4030)、appid(CBS)、codec(http)、filters(ServerEventFilter)、group(800)、pid(1488)、serializer(string)、version(1.0)
这里有一点点可以注意:EDSP平台注册节点与Dubbo类似,都是:/框架标识/接口名/配置节点 ,zk默认的配置节点有:providers、consumers、configurations、routers,如果是dubbo注册的服务,注册节点将是:/dubbo/cn.sunline.ltts.busi.lttran.trans.intf.dp4030/providers
(1)providers节点由服务端(provider)创建,也就是服务端创建,以供服务消费者获得节点中的信息,从而确定服务提供者真正的网络拓扑位置,以及得知如何调用。且如上述/edsp/4030/providers所展示的信息键值对,其中的value就包含了RPC调用中所需要的全部信息!
(2)consumers节点是客户端(consumer)注册的,方便对调用进行统计,管理。
(3)routers节点是客户端(consumer)创建,保存了一些路由规则信息,便于调用时进行路由服务。
(4)configurations节点是服务端(provider)创建,便于监听订阅admin的对provider的修改。
节点模型
ZooKeeper的数据模型,在结构上和标准的文件目录很相似,都是树形的层次结构,每个子目录项如NameServer都被称之为ZNode,它是节点在所在路径的唯一标识。
(1)引用方式
Znode通过路径引用,路径必须是绝对的,以斜杠开头。
(2)znode结构
zookeeper命名空间内的znode,兼具文件和目录两种特点。就是说每个znode有自己的描述信息(数据、元信息、ACl、时间戳),也可作为一个路径标识。总的来讲,分为3部分:
- stat 此为状态信息,秒数znode的版本、权限信息
- data znode关联的数据
- children znode下的子节点
(3)数据访问
每次数据访问都是原子性的,每个znode都存在一个ACL(访问控制列表),保存着用户对该节点操作的权限,可在创建节点时设置。
(4)节点类型
zookeeper节点大致上可分为临时节点和永久节点,由创建时指定。
- 临时节点:顾名思义,节点创建出来是有时间限制的,存在于节点会话(Session)的一个生命周期内,会话结束即删除,也可手动删除,绑定在一个特定的客户端内,对所有客户端可见,不能拥有子节点。
- 永久节点:通常使用的节点,没有生命周期,创建即表示永久,除非客户端指定节点删除,就算zk服务断掉重启,节点也将存在
(5)监听器
每个znode都有监听器的概念,客户端创建时可创建watch,当zkServer节点状态发生改变时(znode增、删、改)触发watch,并发送到zk客户端,可进行响应的动作。平台RPC就是在创建节点时,建立对节点的监听,进行一些监控并处理。
(6)节点属性
以上讲了,每个znode都有文件和目录得属性,所以一下列出文件属性下的数据属性
安装
安装模式
ZooKeeper的安装分为单机模式、集群模式、伪集群模式
- 单机模式:zookeeper服务搭建在一台机器上,存在一个zk服务实例,所有访问都到这一台机器上面
- 集群模式:zookeeper平行的搭在多台服务器上,存在多个zk服务实例,他们之间建立通讯关系(和主从关系),所有访问可指向这多台机器,zk服务内部自动优化处理
- 伪集群模式:zookeeper服务搭建在一台机器上,存在多个zk服务实例,他们之间建立通讯关系(和主从关系),所有访问可指向这多台机器,zk服务内部自动优化处理,实现单机上模拟集群模式
搭建zookeeper需要根据具体的环境来选择,不然有些操作会变的无意义。海外核心系统是集中式的,所有业务交易都是采用的同步调用,这也默认了zookeeper选用单机安装会比较好。集群模式安装和伪集群安装比较类似,网上可以搜到很多简易安装步骤,这里就不介绍了。
安装步骤
zookeeper是可以跨平台的,所以你可以安装在Windows、Linux、Mac操作系统上面,并且他们的安装步骤一致。
安装JDK
安装zookeeper之前,确认JDK已经安装,并且设置到环境变量中。如果未设置,请提前安装JDK并设置环境变量,步骤省略。
java -version #在当前的用户空间/DOS/命令行下验证JDK |
下载zookeeper
百度上搜索"zookeeper安装包"都有大量的教程,也可访问此URL:http://zookeeper.apache.org/releases.html 前往下载最新zookeeper安装包!然后上传到服务器,或者放在本地合适的位置!
配置与运行
假设下载的包为:ZooKeeper-3.4.6.tar.gz 服务器安装路径:/home/zookeeper/ 包路径:/home/zookeeper/ZooKeeper-3.4.6.tar.gz
1、解压和配置日志、数据目录:
& cd /home/zookeeper/ & tar -xzvf ZooKeeper-3.4.6. tar .gz & mv ZooKeeper-3.4.6 zookeeper_dev & mkdir data logs & mkdir data /zookeeper_dev logs /zookeeper_dev & cd zookeeper_dev |
2、修改配置文件
& cd /home/zookeeper/zookeeper_dev/conf & cp zoo_sample.cfg zoo.cfg & vi zoo.cfg |
以下为修改的zoo.cfg的内容:
# The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit=10 # 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= /home/zookeeper/data/zookeeper_dev ## 此处必须配置 dataLogDir= /home/zookeeper/logs/zookeeper_dev # the port at which the clients will connect clientPort=2181 ## 默认端口2181 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # # 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 |
3、运行zookeeper服务
当以上配置都修改完毕,就可以到/bin目录下,启动zookeeper了!
& netstat -at| grep 2181 #查看zookeeper端口 & netstat -nat #查看端口信息 & cd /home/zookeeper/zookeeper_dev/bin & . /zkServer .sh start #启动服务 & jps #查看启动的java服务名称 & . /zkServer .sh stop #关闭服务 |
4、查看zookeeper服务
当确认zookeeper服务已经启动,则可以使用zk客户端去查看服务
& cd /home/zookeeper/zookeeper_dev/bin & . /zkCli .sh #启动客户端 或者使用: ./zkCli.sh -server 127.0.0.1:2181 格式: ./bash -server ip:port & ls /edsp/4030/providers #查看4030服务提供者的信息 & ctrl + z #进行客户端退出 |
zookeeper操作
当zookeeper服务启动起来了,并且你也登录到zk客户端了,此时你可以查询服务提供者、消费者、配置信息、路由信息等。
以下列出几个zk原生的操作:
使用以上命令可以去创建节点、删除节点、获取子节点、获取数据、同步数据,但是需要注意:如果是服务器上的zookeeper,禁止此类操作!!!!
首先看看zk客户端给我们的操作
(1) 创建节点 /parent/children 数据为"children1"
& cd /home/zookeeper/zookeeper_dev/bin & . /zkCli .sh -server 127.0.0.1:2181 格式: . /bash -server ip:port [zk: localhost:2181(CONNECTED) 1]create /parent "parent" #创建父节点 [zk: localhost:2181(CONNECTED) 1]create /parent/children "children1" #创建子节点 [zk: localhost:2181(CONNECTED) 1]create -e /parent/temp "temp" #创建临时节点,当前客户端退出自动删除 [zk: localhost:2181(CONNECTED) 1]create -s /parent/sequence "ss" #节点:/parent/sequence0000000001 [zk: localhost:2181(CONNECTED) 1]create -s /parent/sequence "ss" #节点:/parent/sequence0000000002 #创建顺序节点,节点附上序列号,自动递增,可多次执行 |
(2) 查看节点,查看节点数据
& cd /home/zookeeper/zookeeper_dev/bin & . /zkCli .sh -server 127.0.0.1:2181 格式: . /bash -server ip:port [zk: localhost:2181(CONNECTED) 1] ls /parent #查看父目录节点 [zk: localhost:2181(CONNECTED) 1]get /parent #获得父节点信息,返回数据 [zk: localhost:2181(CONNECTED) 1] ls /parent/children #查看子节点目录 [zk: localhost:2181(CONNECTED) 1]get /parent/children #获得子节点信息,返回数据 [zk: localhost:2181(CONNECTED) 1]stat /parent/children #获得子节点信息,不返回数据 |
(3)删除节点
& cd /home/zookeeper/zookeeper_dev/bin & . /zkCli .sh -server 127.0.0.1:2181 格式: . /bash -server ip:port [zk: localhost:2181(CONNECTED) 1]rmr /parent #删除目录,可递归删除 [zk: localhost:2181(CONNECTED) 1]delete /parent/children #删除节点,不可递归删除 |
安全控制
zookeeper提供ACL(访问控制列表),对每个znode的操作进行权限控制。具体的讲就是:针对一个znode,限制哪些用户的哪种权限。
这里哪些用户,指的是用户的认证方式,这里有4中认证方式:
- world:默认方式,相当于全世界都能访问
- auth:代表已经认证通过的用户(cli中可以通过addauth digest user:pwd 来添加当前上下文中的授权用户)(语法:addauth digest username:password)
- digest:即用户名:密码这种方式认证,这也是业务系统中最常用的(语法:digest:username:BASE64(SHA1(password)):cdrwa)
- ip:使用Ip地址认证(语法:ip:192.168.1.100:cdrwa)
这里哪种权限,指的是znode的操作权限,有以下5种操作cdrwa:
- CREATE(r):创建子节点的权限
- DELETE(d):删除节点的权限
- READ(r):读取节点数据的权限
- WRITE(w):修改节点数据的权限
- ADMIN(a):设置子节点权限的权限
基于以上操作,我们可以对创建的节点,或者创建节点时,设置授权信息。那么后续的所有操作,都需要加上授权信息才能进行操作。
& cd /home/zookeeper/zookeeper_dev/bin & . /zkCli .sh #启动客户端 或者使用: ./zkCli.sh -server 127.0.0.1:2181 格式: ./bash -server ip:port [zk: localhost:2181(CONNECTED) 1]create /node "node" #创建node节点 [zk: localhost:2181(CONNECTED) 1]setAcl /node digest:dingmk:7zmm3QUaLqQVBWHTEPohlXLPT3w=:cdrwa #设置Acl,对/node节点,给dingmk用户赋予cdrwa权限 [zk: localhost:2181(CONNECTED) 1]getAcl /node #获得/node节点的权限信息 [zk: localhost:2181(CONNECTED) 1]create /node/node1 "node1" #创建/node/node1节点,没有授权,所以失败! [zk: localhost:2181(CONNECTED) 1]addauth digest dingmk:123456 #增加用户的权限 [zk: localhost:2181(CONNECTED) 1]create /node/node1 "node1" #创建/node/node1节点,成功! |
设置权限信息时,有一个加密的过程,需要我们手动去将密码加密,表达形式为:digest:username:BASE64(SHA1(password)),使用的是做了SHA1和Base64加密后的密码,将dingmk:123456 => dingmk:7zmm3QUaLqQVBWHTEPohlXLPT3w=,这可以借助zookeeper一个工具类操作:
& cd /home/zookeeper/zookeeper_dev/lib & java -Djava.ext. dirs = /home/zookeeper/zookeeper_dev/lib - cp /home/zookeeper/zookeeper_dev/zookeeper-3 .4.6.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider dingmk:123456 dingmk:123456->dingmk:7zmm3QUaLqQVBWHTEPohlXLPT3w= |
windows下加密过程,如下:
参考文章: