• zookeeper 的介绍以及c api的使用


    一、zookeeper 的安装与配置:

    1.zookeeper安装

    下载:https://zookeeper.apache.org/  建议下载zookeeper 3.4.6稳定版的, 3.5版本的在搭建集群时,会出现服务启动失败的错误。

    安装: 解压 即可

    安装C 语言 api:

    进入./zookeeper/src/c目录

    ./configure

    make

    make install

    2.集群配置

    Zookeeper 的配置文件在 conf 目录下,这个目录下有 zoo_sample.cfg 和 log4j.properties,需要将 zoo_sample.cfg 改名为 zoo.cfg,因为 Zookeeper 在启动时会找这个文件作为默认配置文件。下面详细介绍一下,这个配置文件中各个配置项的意义。

     tickTime=2000

     dataDir= /home/zoo/data

     clientPort=2181

    • tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
    • dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
    • clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。

    当这些配置项配置好后,你现在就可以启动 Zookeeper 了,启动后要检查 Zookeeper 是否已经在服务,可以通过 netstat – ano 命令查看是否有你配置的 clientPort 端口号在监听服务。

    集群模式

    Zookeeper 不仅可以单机提供服务,同时也支持多机组成集群来提供服务。实际上 Zookeeper 还支持另外一种伪集群的方式,也就是可以在一台物理机上运行多个 Zookeeper 实例,下面将介绍集群模式的安装和配置。

    Zookeeper 的集群模式的安装和配置也不是很复杂,所要做的就是增加几个配置项。集群模式除了上面的三个配置项还要增加下面几个配置项:

     initLimit=5

     syncLimit=2

     server.1=192.168.211.1:2888:3888

     server.2=192.168.211.2:2888:3888

    • initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
    • syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
    • server.myid=ip:port1:port2:其中 myid 是一个数字,表示这个是第几号服务器;ip是这个服务器的 ip 地址;port1表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;port2表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 ip 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。

    除了修改 zoo.cfg 配置文件,集群模式下还要配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面就有一个数据就是 A 的值,Zookeeper 启动时会读取这个文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是那个 server。

    二、Zookeeper的使用:

    1.服务端的启动:

    进入/bin目录,使用./zkServer.sh start 启动zookeeper服务。 使用./zkServer.sh stop 停止服务。./zkServer.sh status 查看服务状态 (leader or follower).

    2.客户端命令的使用:

    进入/bin目录下,使用 ./zkCli.sh –server host:port 登陆服务,例如

    ./zkCli.sh  -server 192.168.1.91:2181,键入任意字符出现以下help命令。

    [zk: localhost:2181(CONNECTED) 1] help
    ZooKeeper -server host:port cmd args
            connect host:port
            get path [watch]
            ls path [watch]
            set path data [version]
            delquota [-n|-b] path
            quit 
            printwatches on|off
            create [-s] [-e] path data acl
            stat path [watch]
            close 
            ls2 path [watch]
            history 
            listquota path
            setAcl path acl
            getAcl path
            sync path
            redo cmdno
            addauth scheme auth
            delete path [version]
            setquota -n|-b val path

    1. create [-s] [-e] path data acl
      其中”-s”表示创建一个顺序自动编号的节点,”-e”表示创建一个临时节点.默认为持久性节点

    例如:创建一个持久性节点和临时节点

    [zk: localhost:2181(CONNECTED) 7] create /test null

    Created /test

    [zk: localhost:2181(CONNECTED) 8] create -e /test0 null

    Created /test0

    当会话退出,临时节点将会自动删除,并且临时节点无子节点。

    关于ACL的设置和使用在下一节单独介绍。

    2.get path [watch]和set path data [version]

    get是获取Znode的数据及相关属性,而set是修改此Znode的数据.

    3.ls path [watch]

    查看Znode的子节点

    4.stat path [watch]

    查看Znode的属性

    5.delete path [version]

    删除Znode,前提若有子节点,先删除其子节点

    6.addauth scheme auth

    认证授权,若某个节点需要认证后才能查看,就需要此命令,具体见下节。

    3.ACL 的使用

     传统的文件系统中,ACL分为两个维度,一个是属组,一个是权限,子目录/文件默认继承父目录的ACL。而在Zookeeper中,node的ACL是没有继承关系的,是独立控制的.

    多集群共用zookeeper又涉及一个权限隔离的问题。zookeeper本身提供了ACL机制,表示为scheme:id:permissions,第一个字段表示采用哪一种机制,第二个id表示用户,permissions表示相关权限,如只读,读写,管理等。

    scheme: scheme对应于采用哪种方案来进行权限管理,zookeeper实现了一个pluggable的ACL方案,可以通过扩展scheme,来扩展ACL的机制。zookeeper-3.4.4缺省支持下面几种scheme:

    ž   world: 它下面只有一个id, 叫anyone, world:anyone代表任何人,zookeeper中对所有人有权限的结点就是属于world:anyone的

    ž   auth: 它不需要id, 只要是通过authentication的user都有权限(zookeeper支持通过kerberos (http://www.cnblogs.com/jankie/archive/2011/08/22/2149285.html)来进行authencation, 也支持username/password形式的authentication)

    ž   digest: 它对应的id为username:BASE64(SHA1(password)),它需要先通过username:password形式的authentication

    ž   ip: 它对应的id为客户机的IP地址,设置的时候可以设置一个ip段,比如ip:192.168.1.0/16, 表示匹配前16个bit的IP段

    ž   super: 在这种scheme情况下,对应的id拥有超级权限,可以做任何事情(cdrwa)

      另外,zookeeper-3.4.4的代码中还提供了对sasl的支持,不过缺省是没有开启的,需要配置才能启用,具体怎么配置在下文中介绍。
           * sasl: sasl的对应的id,是一个通过sasl authentication用户的id,zookeeper-3.4.4中的sasl authentication是通过kerberos来实现的,也就是说用户只有通过了kerberos认证,才能访问它有权限的node.(关于sasl 参考:http://www.wxdl.cn/cloud/zookeeper-sasl.html)

    id: id与scheme是紧密相关的,具体的情况在上面介绍scheme的过程都已介绍.

     

    permission: zookeeper目前支持下面一些权限:

    权限

    描述

    备注

    CREATE

    有创建子节点的权限

     

    READ

    有读取节点数据和子节点列表的权限

     

    WRITE

    有修改节点数据的权限

    无创建和删除子节点的权限

    DELETE

    有删除子节点的权限

     

    ADMIN

    有设置节点权限的权限

     

    客户端示例:

    1. create [-s] [-e] path data acl
      create /acl  test world:anyone:rwd

    Created  /test

    1. create -s /test/test null digest:test:V28q/NynI4JI3Rk54h0r8O5kMug=:rwcda

    Created /test/test0000000000

    1. getAcl  /acl  查看路径的acl信息
    2. setAcl /test digest:test:V28q/NynI4JI3Rk54h0r8O5kMug=:r
    3. setAcl /test auth:username:password:crdwa
    4. addauth /<node-name> digest <username>:<password>

    ACL的原理:

    ZooKeeper 的权限管理通过Server、Client 两端协调完成:

    (1) Server

    一个ZooKeeper 的节点存储两部分内容:数据状态,状态中包含ACL 信息。创建一个znode 会产生一个ACL 列表,列表中每个ACL 包括:

     权限perms

     验证模式scheme

     具体内容expression:Ids

    例如,当scheme="digest" 时, Ids 为用户名密码, 即"root :J0sTy9BCUKubtK1y8pkbL7qoxSw"。ZooKeeper 提供了如下几种验证模式:

    Digest: Client 端由用户名和密码验证,譬如user:pwd

    Host: Client 端由主机名验证,譬如localhost

    Ip:Client 端由IP 地址验证,譬如172.2.0.0/24

    World :固定用户为anyone,为所有Client 端开放权限

    (2) 客户端

    Client 通过调用addAuthInfo()(java, c为zoo_add_auth)函数设置当前会话的Author信息。Server 收到Client 发送的操作请求除exists、getAcl 之外,需要进行ACL 验证:对该请求携带的Author 明文信息加密,并与目标节点的ACL 信息进行比较,如果匹配则具有相应的权限,否则请求被Server 拒绝。

    三、zookeeper原理机制

    1.文件系统

    Zookeeper维护一个类似文件系统的数据结构:

     

     

    每个子目录项如 NameService 都被称作为 znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。

    有四种类型的znode:

    1、PERSISTENT-持久化目录节点

    客户端与zookeeper断开连接后,该节点依旧存在

    2、 PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点

    客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号

    3、EPHEMERAL-临时目录节点

    客户端与zookeeper断开连接后,该节点被删除

    4、EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点

    客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号

    2.通知机制

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

    Zookeeper 的watch函数时一次性触发的,即一 个watch事件将会在数据发生变更时发送给客户端。例如,如果客户端执行操作getData(“/znode1″, true),而后 /znode1 发生变更或是删除了,客户端都会得到一个  /znode1 的watch事件。如果  /znode1 再次发生变更,则在客户端没有设置新的watch的情况下,是不会再给这个客户端发送watch事件的。

    这就是说,一个事件会发送向客户端,但可能在在操作成功的返回值到达发起变动的客户端之前,这个事件还没有送达watch的客户端。Watch是异步发送 的。但ZooKeeper保证了一个顺序:一个客户端在收到watch事件之前,一定不会看到它设置过watch的值的变动。网络时延和其他因素可能会导 致不同的客户端看到watch和更新返回值的时间不同。但关键点是,每个客户端所看到的每件事都是有顺序的。

    四、使用场景

    1.配置同步:

    1. 搭建zookeeper集群,在集群服务器上创建永久节点如:Authorization
    2. 需要更新缓存的客户机器,连接至集群,并通过zookeeper watch机制对Authorization节点设置watch。
    3. 当数据库认证信息发生变化时,对 Authorization 节点数据进行更新,从而触发客户机的watch 函数,在watch函数中进行更新缓存的操作。

    注意事项:

    1. watch 时一次性触发的,因此在watch函数触发后,需要重新注册,从而实现永久监听。
    2. 由于网络原因,或者更新操作过于频繁时,在客户机处理更新操作,没有注册新的watch间隙,数据库的认证信息发生变化时,这时会出现客户端缓存和数据库数据不一致的错误,因此,在watch函数结束后,通过再次获取Authorization的相关信息(程序中使用的是mzxid)与之前的进行比较,若不一致,需要再次进行更新缓存操作。
    3. zookeeper session 失效问题 http://blog.csdn.net/kobejayandy/article/details/26289273当客户端收到SESSIONEXPIRED状态信息后,由于之前设置的watch将失效,因此,进行了关闭之前的连接,重新开始连接,并设置watch函数的操作。

    2.集群管理

    使用zookeeper可以进行集群管理,主要针对两点

    1. 是否有机器的加入或退出

    解决这个问题,可以在约定一个父目录,gropmember,然后再父目录下面,每个机器创建临时节点,并且监听父目录的子节点变化消息,一旦有机器退出集群,对应的子节点也将被删除,其它机器将受到通知。同样,当加入新的机器时,其它机器也将受到通知。

    1. Master的选举

    Master的选举与上面的原理大致一致,所有机器创建临时子节点并按顺序编号,每次选择编号最小的子节点对应的机器作为master即可。

    另外:

    zookeeper 

    zoo_get(zhandle_t *zh, const char *path, int watch, char *buffer,
    int* buffer_len, struct Stat *stat);

    1.在传递参数时,buffer_len 的值是buffer缓冲的大小,当zoo_get成功返回后,buffer_len将被至为对应node节点数据的长度

    2.如何确定buffer的大小? 可以设置一个大约值,然后当zoo_get 返回后,从stat结构体中获取node数据长度,与返回的buffer_len 进行比较,若是不相符,说明缓冲区小了,这时可以拿到正确的长度,再次get即可。

    stat结构体:

    struct Stat {
        int64_t czxid;
        int64_t mzxid;
        int64_t ctime;
        int64_t mtime;
        int32_t version;
        int32_t cversion;
        int32_t aversion;
        int64_t ephemeralOwner;
        int32_t dataLength;
        int32_t numChildren;
        int64_t pzxid;
    };

    ~~~~~
  • 相关阅读:
    2019.6.30 Spring注解 bean后置处理器和属性赋值
    2019.6.29 Spring注解-Bean的注册
    2019.6.28 Spring注解
    boost基础环境搭建
    动态规划入门一:钢条切割问题
    《剑指offer》读书笔记
    字符串的全排列
    西山居递归面试题
    常见的数据结构
    832. Flipping an Image
  • 原文地址:https://www.cnblogs.com/missmzt/p/4892719.html
Copyright © 2020-2023  润新知