Chapter 10 运行 ZooKeeper

1、配置 ZooKeeper 服务器

ZooKeeper 服务器在启动时从一个名为 zoo.cfg 的配置文件读取全部选项,多个服务器若是角色类似,同时基本配置信息同样,就能够共享一个文件。
data 目录下的 myid 文件用于区分各个服务器,对每一个服务器来讲,data 目录是惟一的,所以这个目录能够更加方便地保持一些差别化文件。服务器ID 将 myid 文件做为一个索引引入到配置文件中,一个特定的 ZooKeeper 服务器能够知道如何配置本身参数。
配置参数经常经过配置文件的方式进行设置,本节后续部分,经过列表方式列出了这些参数。不少参数也能够经过Java的系统属性传递,其形式一般为zookeeper.propertyName,在启动服务器时,经过-D选项设置这些属性。不过,系统属性所对应的一个特定参数对服务来讲是插入的配置,配置文件中的配置参数优先于系统属性中的配置。

一、基本配置

  • clientPort
    客户端所链接的服务器所监听的TCP端口,默认状况下,服务端会监听在全部的网络链接接口的这个端口上,除非设置了clientPortAddress参数。客户端端口能够设置为任何值,不一样的服务器也能够监听在不一样的端口上。默认端口号为2181。
  • dataDir 和 dataLogDirjava

    • dataDir:用于配置内存数据库保存的模糊快照的目录,若是某个服务器为集群中的一台,id文件也保存在该目录下。dataDir并不须要配置到一个专用存储设备上,快照将会之后台线程的方式写入,且并不会锁定数据库,并且快照的写入方式并非同步方式,直到写完整快照为止。
    • dataLogDir:事务日志对该目录所处的存储设备上的其余活动更加敏感,服务端会尝试进行顺序写入事务日志,觉得服务端在确认一个事务前必须将数据同步到存储中,该设备的其余活动(尤为是快照的写入)可能致使同步时磁盘过于忙碌,从而影响写入的吞吐能力。所以,最佳实践是使用专用的日志存储设备,将dataLogDir的目录配置指向该设备。
  • tickTime
    tick的时长单位为毫秒,tick为ZooKeeper使用的基本的时间度量单位,在9.7节已经介绍过,该值还决定了会话超时的存储器大小。Zookeeper集群中使用的超时时间单位经过tickTime指定,也就说,实际上tickTime设置了超时时间的下限值,由于最小的超时时间为一个tick时间,客户端最小会话超时事件为两个tick时间。
    tickTime的默认值为3000毫秒,更低的tickTime值能够更快地发现超时问题,但也会致使更高的网络流量(心跳消息)和更高CPU使用率(会话存储器的处理)。

二、存储配置

  • preAllocSize
    用于设置预分配的事务日志文件(zookeeper.preAllocSize)的大小值,以KB为单位。
    当写入事务日志文件时,服务端每次会分配preAllocSize值的KB的存储大小,经过这种方式能够分摊文件系统将磁盘分配存储空间和更新元数据的开销,更重要的是,该方式也减小了文件寻址操做的次数。

    默认状况下preAllocSize的值为64MB,缩小该值的一个缘由是事务日志永远不会达到这么大,由于每次快照后都会从新启动一个新的事务日志,若是每次快照之间的日志数量很小,并且每一个事务自己也很小,64MB的默认值显然就太大了。例如,若是咱们每1000个事务进行一次快照,每一个事务的平均大小为100字节,那么100KB的preAllocSize值则更加合适。默认的preAllocSize值的设置适用于默认的snapCount值和平均事务超过512字节的状况。node

  • snapCount
    指定每次快照之间的事务数(zookeeper.snapCount)。
    当Zookeeper服务器重启后须要恢复其状态,恢复时两大时间因素分别是为恢复状态而读取快照的时间以及快照启动后所发生的事务的执行时间。执行快照能够减小读入快照文件后须要应用的事务数量,可是进行快照时也会影响服务器性能,即使是经过后台线程的方式进行写入操做。
    snapCount的默认值为100000,由于进行快照时会影响性能,因此集群中全部服务器最好不要在同一时间进行快照操做,只要仲裁服务器不会一同进行快照,处理时间就不会受影响,所以每次快照中实际的事务数为一个接近snapCount值的随机数。
    注意,若是snapCount数已经达到,但前一个快照正在进行中,新的快照将不会开始,服务器也将继续等到下一个snapCount数量的事务后再开启一个新的快照。
  • autopurge.snapRetainCount
    当进行清理数据操做时,须要保留在快照数量和对应的事务日志文件数量。
    ZooKeeper将会按期对快照和事务日志进行垃圾回收操做,autopurge.snapRetainCount值指定了垃圾回收时须要保留的快照数,显然,并非全部的快照均可以被删除,由于那样就不可能进行服务器的恢复操做。autopurge.snapRetainCount的最小值为3,也是默认值的大小。
  • autopurge.purgeInterval
    对快照和日志进行垃圾回收(清理)操做的时间间隔的小时数。若是设置为一个非0的数字,autopurge.purgeInterval指定了垃圾回收周期的时间间隔,若是设置为0,默认状况下,垃圾回收不会自动执行,而须要经过ZooKeeper发行包中的zkCleanup.sh脚本手动运行。
  • fsync.warningthresholdms
    触发警告的存储同步时间阀值(fsync.warningthresholdms),以毫秒为单位。
    ZooKeeper服务器在应答变化消息前会同步变化状况到存储中。若是同步系统调用消耗了太长时间,系统性能就会受到严重影响,服务器会跟踪同步调用的持续时间,若是超过fsync.warningthresholdms只就会产生一个警告消息。默认状况下,该值为1000毫秒。
  • weight.x=n
    该选项经常以一组参数进行配置,该选项指定组成一个仲裁机构的某个服务器的权重为n,其权重n值指示了该服务器在进行投票时的权重值。在ZooKeeper中一些部件须要投票值,好比群首选举中和原子广播协议中。默认状况下,一个服务器的权重值为1,若是定义的一组服务器没有指定权重,全部服务器的权重值将默认分配为1。
  • traceFile
    持续跟踪ZooKeeper的操做,并将操做记录到跟踪日志中,跟踪日志的文件名为traceFile.year.month.day。除非设置了该选项(requestTraceFile),不然跟踪功能将不会启用。
    该选项用来提供ZooKeeper所进行的操做的详细视图。不过,要想记录这些日志,ZooKeeper服务器必须序列化操做,并将操做写入磁盘,这将争用CPU和磁盘的时间。若是你使用了该选项,请确保不要将跟踪文件放到日志文件的存储设备中。还须要知道,跟踪选项还可能影响系统运行,甚至可能会很难重现跟踪选项关闭时发生的问题。另外还有个有趣的问题,traceFile选项的Java系统属性配置中不含有zookeeper前缀,并且系统属性的名称也与配置选项名称不一样,这一点请当心。

三、网络配置

这些配置参数能够限制服务器和客户端之间的通讯,超时选项也在该节进行讨论:
  • globalOutstandingLimit
    ZooKeeper中待处理请求的最大值(zookeeper.globalOutstandingLimit)。
    ZooKeeper客户端提交请求比ZooKeeper服务端处理请求要快不少,服务端将会对接收到的请求队列化,最终(也许几秒以内)可能致使服务端的内存溢出。为了防止发生这个问题,ZooKeeper服务端中若是待处理请求达到globalOutstandingLimit值就会限制客户端的请求。但globalOutstandingLimit值并非硬限制,由于每一个客户端至少有一个待处理请求,不然会致使客户端超时,所以,当达到globalOutstandingLimit值后,服务端还会继续接收客户端链接中的请求,条件是这个客户端在服务器中没有任何待处理的请求。
    为了肯定某个服务器的全局限制值,咱们只是简单地将该参数值除以服务器的数量,目前尚未更智能的方式去实现全局待处理操做数量的计算,并强制采用该参数所指定的限制值,所以,该限制值为待处理请求的上限值,事实上,服务器之间完美的负载均衡解决方案还没法实现,因此某些服务器运行得稍缓慢一点,或者处于更高的负载中,即便最终没有达到全局限制值也可能被限制住吞吐量。
    该参数的默认值为1000个请求,你可能并不会修改该参数值,但若是你有不少客户端发送大数据包请求可能就须要下降这个参数值,但咱们在实践中还未遇到须要修改这个参数的状况。
  • maxClientCnxns
    容许每一个IP地址的并发socket链接的最大数量。Zookeeper经过流量控制和限制值来避免过载状况的发生。一个链接的创建所使用的资源远远高于正常操做请求所使用的资源。咱们曾看到过某些错误的客户端每秒建立不少ZooKeeper链接,最后致使拒绝服务(DoS),为了解决这个问题,咱们添加了这个选项,经过设置该值,能够在某个IP地址已经有maxClientCnxns个链接时拒绝该IP地址新的链接。该选项的默认值为60个并发链接。
    注意,每一个服务器维护着这个链接的数量,若是有一个5个服务器的集群,而且使用默认的并发链接数60,一个欺诈性的客户端会随机链接到这5个不一样的服务器,正常状况下,该客户端几乎能够从单个IP地址上创建300个链接,以后才会触发某个服务器的限制。
  • clientPortAddress
    限制客户端链接到指定的接收信息的地址上。默认状况下,一个ZooKeeper服务器会监听在全部的网络接口地址上等待客户端的链接。
    有些服务器配置了多个网络接口,其中一个网络接口用于内网通讯,另外一个网络接口用于公网通讯,若是你并不但愿服务器在公网接口接受客户端的链接,只须要设置clientPortAddress选项为内网接口的地址。
  • minSessionTimeout
    最小会话超时时间,单位为毫秒。当客户端创建一个链接后就会请求一个明确的超时值,而客户端实际得到的超时值不会低于minSessionTimeout的值。
    minSessionTimeout的默认值为tickTime值的两倍。配置该参数值太低可能会致使错误的客户端故障检测,配置该参数值太高会延迟客户端故障的检测时间。
  • maxSessionTimeout
    会话的最大超时时间值,单位为毫秒。当客户端创建一个链接后就会请求一个明确的超时值,而客户端实际得到的超时值不会高于maxSessionTimeout的值。
    虽然该参数并不会影响系统的性能,但却能够限制一个客户端消耗系统资源的时间,默认状况下maxSessionTimeout的时间为tickTime的20倍。

四、集群配置

当以一个集群来构建ZooKeeper服务时,须要为每台服务器配置正确的时间和服务器列表信息,以便服务器之间能够互相创建链接并进行故障监测,在ZooKeeper的集群中,这些参数的配置必须一致:
  • initLimit
    对于追随者最初链接到群首时的超时值,单位为tick值的倍数。
    当某个追随者最初与群首创建链接时,它们之间会传输至关多的数据,尤为是追随者落后总体不少时。配置initLimit参数值取决于群首与追随者之间的网络传输速度状况,以及传输的数据量大小,若是ZooKeeper中保存的数据量特别大(即存在大量的znode节点或大数据集)或者网络很是缓慢,就须要增大initLimit值,由于该值取决于环境问题,全部没有默认值。须要为该参数配置适当的值,以即可以传输所指望的最大快照,也许有时你须要屡次传输,你能够配置initLimit值为两倍你所指望的值。若是配置initLimit值太高,那么首次链接到故障的服务器就会消耗更多的时间,同时还会消耗更多的恢复时间,所以最好在你的网络中进行追随者与群首之间的网络基准测试,以你规划所使用的数据量来测试出你所指望的时间。
  • syncLimit
    对于追随者与群首进行sync操做时的超时值,单位为tick值的倍数。
    追随者老是会稍稍落后于群首,可是若是由于服务器负载或网络问题,就会致使追随者落后群首太多,甚至须要放弃该追随者,若是群首与追随者没法进行sync操做,并且超过了syncLimit的tick时间,就会放弃该追随者。与initLimit参数相似,syncLimit也没有默认值,与initLimit不一样的是,syncLimit并不依赖于ZooKeeper中保存的数据量大小,而是依赖于网络的延迟和吞吐量。在高延迟网络环境中,发送数据和接收响应包会耗费更多时间,此时就须要调高syncLimit值。即便在相对低延迟的网络中,若是某些相对较大的事务传输给追随者须要必定的时间,你也须要提升syncLimit值。
  • leaderServes
    配置值为“yes”或“no”标志,指示群首服务器是否为客户端提供服务(zookeeper.leaderServes)。
    担任群首的ZooKeeper服务器须要作不少工做,它须要与全部追随者进行通讯并会执行全部的变动操做,也就意味着群首的负载会比追随者的负载高,若是群首过载,整个系统可能都会受到影响。
    该标志位若是设置为“no”就能够使群首除去服务客户端链接的负担,使群首将全部资源用于处理追随者发送给它的变动操做请求,这样能够提升系统状态变动操做的吞吐能力。换句话说,若是群首不处理任何与其直连的客户端链接,追随者就会有更多的客户端,由于链接到群首的客户端将会分散到追随者上,尤为注意在集群中服务器数量比较少的时候。默认状况下,leaderServes的值为“yes”。
  • server.x=[hostname]:n:n[:observer]
    服务器x的配置参数。
    ZooKeeper服务器须要知道它们如何通讯,配置文件中该形式的配置项就指定了服务器x的配置信息,其中x为服务器的ID值(一个整数)。当一个服务器启动后,就会读取data目录下myid文件中的值,以后服务器就会使用这个值做为查找server.x项,经过该项中的数据配置服务器本身。若是须要链接到另外一个服务器y,就会使用server.y项的配置信息来与这个服务器进行通讯。
    其中hostname为服务器在网络n中的名称,同时后面跟了两个TCP的端口号,第一个端口用于事务的发送,第二个端口用于群首选举,典型的端口号配置为2888:3888。若是最后一个字段标记了observer属性,服务器就会进入观察者模式。
    注意,全部的服务器使用相同的server.x配置信息,这一点很是重要,不然的话,因服务器之间可能没法正确创建链接而致使整个集群没法正常工做。
  • cnxTimeout
    在群首选举打开一个新的链接的超时值(zookeeper.cnxTimeout)。
    ZooKeeper服务器在进行群首选举时互相之间会创建链接,该选项值肯定了一个服务器在进行重试前会等待链接成功创建的时间为多久,9.2节介绍了该超时的用途。默认的超时时间为5秒,该值足够大,也许你并不须要修改。
  • electionAlg
    选举算法的配置选项。
    为了整个配置的完整性,咱们也列入了该选项。该选项用于选择不一样的群首选举算法,但除了默认的配置外,其余算法都已经弃用了,因此并不须要配置这个选项。

五、认证和受权选项

该节中包括认证和受权相关的选型配置。对于Kerberos相关的配置选项信息,请参考6.1.2节:
zookeeper.DigestAuthenticationProvider.superDigest(只适用于Java系统属性)该系统属性指定了“super”用户的密码摘要信息(该功能默认不启用),以super用户认证的客户端会跳过全部ACL检查。该系统属性的值形式为super:encoded_digest。为了生成加密的摘要,能够使用org.apache.zookeeper.server.auth.DigestAuthenticationProvider工具,使用方式以下:
java -cp $ZK_CLASSPATH \ org.apache.zookeeper.server.auth.DigestAuthenticationProvider super:asdf
经过命令行工具生成一个 asdf 密码的加密摘要信息:
super:asdf->super:T+4Qoey4ZZ8Fnni1Yl2GZtbH2W4=
为了在服务器启动中使用该摘要,能够经过如下命令实现:
export SERVER_JVMFLAGS
SERVER_JVMFLAGS=-Dzookeeper.DigestAuthenticationProvicder.superDigest=
    suer:T+4Qoey4ZZ8Fnni1Yl2GZtbH2W4=
./bin/zkServer.sh start
如今经过 zkCli 进行链接:
[zk: localhost:2181(CONNECTED) 0] addauth digest super:asdf
[zk: localhost:2181(CONNECTED) 1]
此时,已经以super用户的身份被认证,如今不会被任何ACL所限制。

【注意:不安全链接】算法

ZooKeeper客户端与服务器之间的链接并未加密,所以不要在不可信的连接中使用super的密码,使用super密码的安全方式是在ZooKeeper服务器本机上使用super密码运行客户端。

六、非安全配置

  • forceSync
    经过“yes”或“no”选项能够控制是否将数据信息同步到存储设备上(zookeeper.forceSync)。
    默认状况下,forceSync配置yes时,事务只有在同步到存储设备后才会被应答,同步系统调用的消耗很大,并且也是事务处理中最大的延迟缘由之一。若是forceSync配置为no,事务会在写入到操做系统后就马上被应答,在将事务写入磁盘以前,这些事务经常缓存于内存之中,配置forceSync为no能够提升性能,但代价是服务器崩溃或停电故障时可恢复性。
  • jute.maxbuffer(仅适用于Java系统属性)
    一个请求或响应的最大值,以字节为单位。该选项只能经过Java的系统属性进行配置,而且选项名称没有zookeeper前缀。
    ZooKeeper中内置了一些健康检查,其中之一就是对可传输的znode节点数据的大小的检查,ZooKeeper被设计用于保存配置数据,配置数据通常由少许的元数据信息(大约几百字节)所组成。默认状况下,一个请求或响应消息若是大于1M字节,就会被系统拒绝,能够使用该属性来修改健康检查值,调小检查值,或者真的确认要调大检查值。

【注意:修改健康检查值】
虽然经过jute.maxbuffer指定的限制值能够进行大块数据的写入操做,但获取一个znode节点的子节点,而同时该节点有不少子节点时就会出现问题。若是一个znode节点含有几十万个子节点,每一个子节点的名字长度平均为10个字符,在试着返回子节点列表时就会命中默认最大缓冲大小检查,此时就会致使链接被重置。数据库

  • skipACL
    跳过全部ACL检查(zookeeper.skipACL)。
    处理ACL检查会有必定的开销,经过该选项能够关闭ACL检查功能,这样作能够提升性能,但也会将数据彻底暴露给任何一个能够链接到服务器的客户端。
  • readonlymode.enabled(仅适用于Java系统属性)
    将该配置设置为true能够启用服务器只读模式功能,客户端能够以只读模式的请求链接服务器并读取信息(多是已过时的信息),即便该服务器在仲裁中因分区问题而被分隔。为了启用只读模式,客户端须要配置canBeReadOnly为true。
    该功能能够使客户端即便在网络分区发生时也能读取(不能写入)ZooKeeper的状态,在这种状况下,被分区而分离的客户端依然能够继续取得进展,并不须要等待分区问题被修复。特别注意,一个与集群中其余服务器失去链接ZooKeeper也许会终止以只读模式提供过时的数据服务。

七、日志

ZooKeeper采用SLF4J库(JAVA简易日志门面)做为日志的抽象层,默认使用Log4J进行实际的日志记录功能。
Log4J的配置文件为log4j.properties,系统会从classpath中加载这个文件,对于Log4J比较失望的是,若是对应路径不存在log4j.properties文件,咱们会看到如下输出信息:
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.serv ...
log4j:WARN Please initialize the log4j system properly.
通常,log4j.properties会保存到classpath中的conf目录下,在ZooKeeper中的log4j.properties文件的主要部分:
zookeeper.root.logger=INFO, CONSOLE ①
zookeeper.console.threshold=INFO
zookeeper.log.dir=.
zookeeper.log.file=zookeeper.log
zookeeper.log.threshold=DEBUG
zookeeper.tracelog.dir=.
zookeeper.tracelog.file=zookeeper_trace.log
log4j.rootLogger=${zookeeper.root.logger} ②
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender ③
log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold} ④
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout ⑤
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] -
...
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender ⑥
log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold} ⑦
log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file}
log4j.appender.ROLLINGFILE.MaxFileSize=10MB
log4j.appender.ROLLINGFILE.MaxBackupIndex=10
log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] -
①第一组配置中,全部配置项均以zookeeper.开头,配置了该文件的默认值,这些配置项其实是系统属性配置,能够经过java命令行指定-D参数来覆盖JVM的配置。第一行的日志配置中,默认配置了日志消息的级别为INFO,即全部低于INFO级别的日志消息都会被丢弃,使用的appender为CONSOLE。你能够指定多个appender,例如,你若是想将日志信息同时输出到CONSOLE和ROLLINGFILE时,能够配置zookeeper.root.logger项为INFO,CONSOLE,ROLLINGFILE。
②rootLogger指定了处理全部日志消息的日志处理器,由于咱们并不须要其余日志处理器。
③该行配置以CONSOLE名称定义了一个类,该类会处理消息的输出。在这里使用的是ConsoleAppender类。
④在appender的定义中也能够过滤消息,该行配置了这个appender会忽略全部低于INFO级别的消息,由于zookeeper.root.logger中定义了全局阀值为INFO。
⑤appender使用的布局类对输出日志在输出前进行格式化操做。咱们经过布局模式定义了输出日志消息外还输出日志级别、时间、线程信息和调用位置等信息。
⑥RollingFileAppender实现了滚动日志文件的输出,而不是不断地输出到一个单个日志文件或控制台。除非ROLLINGFILE被rootLogger引用,不然该appender会被忽略。
⑦定义ROLLINGFILE的输出级别为DEBUG,由于rootLogger过滤了全部低于INFO级别的日志,因此,你若是你想看DEBUG消息,就必须将zookeeper.root.logger项的配置从INFO修改成DEBUG。

八、专用资源

当考虑在服务器上运行ZooKeeper如何配置时,服务器自己的配置也很重要。为了达到所指望的性能,能够考虑使用专用的日志存储设备,就是说日志目录处于专属的硬盘上,没有其余进程使用该硬盘资源,甚至周期性的模糊快照也不会使用该硬盘。

2、配置 ZooKeeper 集群

仲裁(quorum)的概念:该概念深深贯穿于ZooKeeper的设计之中。在复制模式下处理请求时以及选举群首时都与仲裁的概念有关,若是ZooKeeper集群中存在法定人数的服务器已经启动,整个集群就能够继续工做。
观察者(observer):与集群一同工做,接收客户端请求并处理服务器上的状态变动,可是群首并不会等待观察者处理请求的响应包,同时集群在进行群首选举时也不会考虑观察者的通知消息。

一、多数原则

当集群中拥有足够的 ZooKeeper 服务器来处理请求时,称这组服务器的集合为仲裁法定人数。
当配置多个服务器来组成ZooKeeper集群时,咱们默认使用多数原则做为仲裁法定人数。ZooKeeper会自动监测是否运行于复制模式,从配置文件读取时肯定是否拥有多个服务器的配置信息,并默认使用多数原则的仲裁法定人数。

二、法定人数的可配置性

关于法定人数的一个重要属性:
若是一个法定人数解散了,集群中另外一个法定人数造成,这两个法定人数中至少有一个服务器必须交集。
ZooKeeper也容许灵活的法定人数配置,这种特殊方案就是对服务器进行分组配置时,会将服务器分组成不相交的集合并分配服务器的权重,经过这种方案来组成法定人数,须要使多数组中的服务器造成多数投票原则。
例如,有三个组,每一个组中有三个服务器,每一个服务器的权重值为1,在这种状况下,须要四个服务器来组成法定人数:某个组中的两个服务器,另外一组中的两台服务器。
总之,其数学逻辑归结为:若是有G个组,所须要的服务器为一个G组的服务器,知足|G|>|G|/2,同时对于G组中的服务器集合g,还须要集合g中的集合g知足集合g的全部权重值之和W'不小于集合g的权重值之和(如:W>W/2)。
经过如下配置选项能够建立一个组:
group.x=n[:n]
启用法定人数的分层构建方式。x为组的标识符,等号后面的数字对应服务器的标识符,赋值操做符右侧为冒号分隔的服务器标识符的列表。注意,组与组之间不能存在交集,全部组的并集组成了整个ZooKeeper集群,换句话说,集群中的每一个服务器必须在某个组中被列出一次。

【下面的示例说明了9个服务器被分为3组的状况:】apache

group.1=1:2:3
group.2=4:5:6
group.3=7:8:9
这个例子中,每一个服务器的权重都同样,为了构成法定人数,须要两个组及这两个组中各取两个服务器,也就是总共4个服务器。但根据法定人数多数原则,至少须要5个服务器来构成一个法定人数。注意,不能从任何子集造成法定人数的4个服务器,不过,一个组所有服务器加上另外一个组的一个单独的服务器并不能构成法定人数。
当在跨多个数据中心部署ZooKeeper服务时,这种配置方式有不少优势。例如,一个组可能表示运行于不一样数据中心的一组服务器,即便这个数据中心崩溃,ZooKeeper服务也能够继续提供服务。
在跨三个数据中心部署的这种方式能够容忍某个数据中心的故障问题,能够在两个数据中心中每个部署三个服务器,而只在第三个数据中心部署一个服务器,经过这种方式来使用多数原则,这样,若是某个数据中心不可用,其余两个数据中心还能组成法定人数。这种配置方式的优势是这七个服务器中的任何四个都构成一个法定人数,而缺点是一旦某个数据中心不可用,其余数据中心中任何服务器的崩溃都没法容忍。
若是只有两个数据中心可用,能够使用 【权重值】来表示优先权,例如,基于每一个数据中心中的客户端数量来配置权重值。只有两个数据中心时,若是每一个服务器的权重值都同样,就没法容忍任何一个数据中心的失效,可是若是对某个服务器分配了更高的权重值,就能够容忍这两个数据中心中某个数据中心的失效。假设,在每一个数据中心中分配三个服务器,而且将这些服务器均放到同一组中:
group.1=1:2:3:4:5:6
由于全部的服务器默认状况下权重值都同样,所以只要6个服务器中有4个服务器有效时就能够构成法定人数的服务器。固然,这也意味着若是某个数据中心失效,就不能造成法定人数,即便另外一个数据中心的三个服务器均有效。

【为了给服务器分配不一样的权重值,能够经过如下选型进行配置:】数组

weight.x=n
与group选项一块儿配合使用,经过该选项能够为某个服务器造成法定人数时分配一个权重值为n。其值n为服务器投票时的权重,ZooKeeper中群首选举和原子广播协议中均须要投票。默认状况下,服务器的权重值为1,若是配置文件中定义了组的选项,但为指定权重值,全部的服务器均会被分配权重值1。

假设,某个数据中心只要其全部服务器都可用,即便在其余数据中心失效时,这个数据中心也能够提供服务,咱们暂且称该数据中心为D1,此时,能够为D1中的某个服务器分配更高权重值,以即可以更容易与其余服务器组成法定人数。缓存

【假设D1中有服务器一、2和3,经过如下方式为服务器1分配更高的权重值:】安全

weight.1=2
经过以上配置,就有了7个投票,在构成法定人数时,只须要4个投票。若是没有weight.1=2参数,任何服务器都须要与其余三个服务器来构成法定人数,但有了这个参数配置,服务器1与两个服务器就能够构成法定人数。所以,只要D1可用,即便其余数据中心发生故障,服务器一、2和3也能构成法定人数并继续提供服务。

经过以上不一样的法定人数配置的若干示例,看到该配置对部署的影响。提供的分层方案很是灵活,经过不一样的权重值和组的管理能够提供不一样的分层配置。服务器

三、观察者

观察者(observer)为ZooKeeper服务器中不参与投票但保障状态更新顺序的特殊服务器。网络

【配置ZooKeeper集群使用观察者,须要在观察者服务器的配置文件中添加如下行】:

peerType=observer

【同时,还须要在全部服务器的配置文件中添加该服务器的:observer定义。以下】:

server.1:localhost:2181:3181:observer

3、重配置

图10-1的场景,三个服务器(A、B、C)组成了整个集群,服务器C因某些网络拥塞问题稍稍落后于整个集群,所以服务器C刚刚了解事务到<1,3>(其中1为时间戳,3为对应该时间戳的事务标识,但由于服务器A和B的通讯良好,因此服务器C稍稍落后并不会致使整个系统变慢,服务器A和B能够提交事务到<1,6>)。

【图10-1:含有3个服务器的集群将要扩展到5个】
clipboard.png

如今,假设将全部服务中止,添加服务器D和E到集群中,固然这两个新的服务器并不存在任何状态信息,从新配置了服务器A、B、C、D、E成为更大的集群并启动集群恢复服务,由于如今有了五个服务器,至少须要三个服务器组成一个法定人数,而服务器C、D、E足够构成法定人数,所以在图10-2中看到当这些服务器构成法定人数并开始同步时都发生了什么。这个场景能够简单重现,若是服务器A和B的启动慢一些,好比服务器A和B比其余三个服务器的启动晚一些。一旦新的法定人数开始同步,服务器A和B就会与服务器C进行同步,由于法定人数中服务器C的状态为最新状态,法定人数的三个成员服务器会同步到最后的事务<1,3>,而不会同步<1,4>、<1,5>和<1,6>这三个事务,由于服务器A和B并未构成法定人数的成员。

【图10-2:5个服务器的集群的法定人数为3】
clipboard.png

由于已经构成一个活跃的法定人数,这些服务器能够开始提交新的事务,假设有两个事务:<2,1>和<2,2>,如图10-3所示,当服务器A和B启动后链接到服务器C后,服务器C做为群首欢迎其加入到集群之中,并在收到事务<2,1>和<2,2>后当即告知服务器A和B删除事务<1,4>、<1,5>和<1,6>。
图10-3:5个服务器的集群丢失数据
clipboard.png

这个结果很是糟糕,丢失了某些状态信息,并且状态副本与客户端所看到的<1,4>、<1,5>、<1,6>也再也不一致。为了不这个问题,ZooKeeper提供了重配置操做,这意味着运维人员并不须要手工进行重配置操做而致使状态信息的破坏,并且,也不须要中止任何服务。

【重配置】不只能够改变集群成员配置,还能够修改网络参数配
置,由于ZooKeeper中配置信息的变化,须要将重配置参数与静态的配置文件分离,单独保存为一个配置文件并自动更新该文件。dynamicConfigFile参数和连接这两个配置文件。

【使用动态配置以前,回顾一下以前的配置文件:】

tickTime=2000
initLimit=10
syncLimit=5
dataDir=./data
dataLogDir=./txnlog
clientPort=2182
server.1=127.0.0.1:2222:2223
server.2=127.0.0.1:3333:3334
server.3=127.0.0.1:4444:4445

【如今,将配置文件修改成动态配置方式:】

tickTime=2000
initLimit=10
syncLimit=5
dataDir=./data
dataLogDir=./txnlog
dynamicConfigFile=./dyn.cfg

【注意】,甚至从配置文件中删除了clientPort参数配置,在dyn.cfg文件由服务器项的配置组成,同时还多了一些配置,服务器项的配置形式以下:

server.id=host:n:n[:role];[client_address:]client_port

与正常的配置文件同样,列出了每一个服务器的主机名和端口号用于法定人数和群首选举消息。

  • role选项:必须为participant或observer,若是忽略role选项,默认为participant
  • client_port:还指定了client_port(用于客户端链接的服务器端口号),以及该服务器须要绑定的特定网络接口地址,由于从静态配置文件中删除了clientPort参数,因此在这里添加该配置。

【最终的dyn.cfg配置文件以下所示】:

server.1=127.0.0.1:2222:2223:participant;2181
server.2=127.0.0.1:3333:3334:participant;2182
server.3=127.0.0.1:4444:4445:participant;2183

使用重配置以前必须先建立这些文件,一旦这些文件就绪,就能够经过reconfig操做来从新配置一个集群,该操做能够增量或全量(总体)地进行更新操做。

增量的重配置操做将会造成两个列表:

  • 待删除的服务器列表
    待删除的服务器列表仅仅是一个逗号分隔服务器ID列表
  • 待添加的服务器项的列表
    待添加的服务器项列表为逗号分隔的服务器项列表,每一个服务器项的形式为动态配置文件中所定义的形式。例如:
reconfig -remove 2,3 -add \
server.4=127.0.0.1:5555:5556:participant;2184,\
server.5=127.0.0.1:6666:6667:participant;2185

该命令将会删除服务器2和3,添加服务器4和5。该操做成功执行还须要知足某些条件:

  • 首先,与其余ZooKeeper操做同样,原配置中法定人数必须处于活动状态;
  • 其次,新的配置文件中构成的法定人数也必须处于活动状态。

【注意:经过重配置从一个服务器到多个服务器】

当只有一个单独的ZooKeeper服务器,该服务器以独立模式运行,这种状况稍微复杂一些,由于重配置不只改变了法定人数组成的元素,同时还会切换原来的服务器模式从独立模式到仲裁模式,因此,不容许以独立模式运行重配置操做,只有在仲裁模式时才能够使用重配置功能。
ZooKeeper一次容许一个配置的变动操做请求,固然,配置操做会很是快地被处理,并且从新配置也不多发生,因此并发的重配置操做应该不是什么问题。

还能够使用-file参数来指定一个新的成员配置文件来进行一次全量更新。例如:reconfig-file newconf命令会产生如上面命令同样的增量操做结果,newconf文件为:

server.1=127.0.0.1:2222:2223:participant;2181
server.4=127.0.0.1:5555:5556:participant;2184
server.5=127.0.0.1:6666:6667:participant;2185
经过-members参数,后跟服务器项的列表信息,能够代替-file参数进行全量更新配置操做。
最后【-v】,全部形式的reconfig的为从新配置提供了条件,若是经过-v参数提供了配置版本号,reconfig命令会在执行前确认配置文件当前的版本号是否匹配,只有匹配才会成功执行。能够经过读取zookeeper/config节点来获取当前配置的版本号,或经过zkCli工具来调用config获取配置版本号信息。

客户端链接串的管理

客户端也涉及一些相关的配置问题:链接串。
客户端链接串经常表示为逗号分隔的host:port对,其中host为主机名或IP地址,经过主机名能够提供服务器实际IP与所访问的服务器的标识符之间的间接层的对应关系。
例如,运维人员能够替换ZooKeeper服务为另外一个,而不须要改变客户端的配置。
不过,该灵活性有必定限制,运维人员能够改变组成集群的服务器机器,但不能改变客户端所使用的服务器。
例如,如图10-4所示,ZooKeeper能够经过重配置很简单地将集群从三个服务器扩展到五个服务器,但客户端仍然使用三个服务器,而不是五个。

【图10-4:集群从三个到五个服务器时,客户端的重配置】
clipboard.png

另外一种方式能够使ZooKeeper的服务器数量更具弹性,而不须要改变客户端的配置。对主机名很天然地想到能够解析为一个IP地址,但实际上,一个主机名能够解析为多个地址,若是主机名解析为多个IP地址,ZooKeeper就能够链接到其中的任何地址,在图10-4中,假设服务器zk-a、zk-b和zk-c,解析为三个独立的IP地址:10.0.0.一、10.0.0.2和10.0.0.3,如今假设经过DNS配置了一个单独的主机名:zk,解析为这三个IP地址,只须要修改DNS的解析地址数量,以后启动的任何客户端均可以访问这五个服务器,如图10-5所示。

【图10-5:集群从三个到五个服务器时,使用DNS对客户端的重配置】
clipboard.png

在使用主机名解析为多个地址方式时,还有一些注意事项:

  • 首先,全部的服务器必须使用相同的客户端端口号;
  • 其次,主机名解析只有在建立链接时才会发生,因此已经链接的客户端没法知道最新的名称解析,只能对新建立的ZooKeeper客户端生效。
【路径信息】:
客户端的链接还能够包含路径信息,该路径指示了解析路径名称时的根路径,其行为与UNIX系统中的chroot命令类似,并且在ZooKeeper社区中也会常常听到人们以“chroot”来称呼这个功能。
例如,若是客户端的链接串为zk:2222/app/superApp,当客户端链接并执行getData("/a.dat",...)操做时,实际客户端会获得/app/superApp/a.dat节点的数据信息(注意,链接串中指示的路径必须存在,而不会建立链接串中所指示的路径)。

在链接串中添加路径信息的动机在于一个ZooKeeper集群为多个应用程序提供服务,这样不须要要求每一个应用程序添加其路径的前缀信息。每一个应用程序能够相似名称独享似的使用ZooKeeper集群,运维人员能够按他们的指望来划分命名空间。
图10-6的示例展现了不一样的链接串能够为客户端应用程序提供不一样的根入口点。

【图10-6:经过链接串指定ZooKeeper客户端的根节点】
clipboard.png

【注意:链接串的重叠】
当管理客户端链接串时,注意一个客户端的链接串永远不要包含两个不一样的ZooKeeper集群的主机名,这是最快速也是最简单致使脑裂问题的方式。

4、配额管理

ZooKeeper的另外一个可配置项为配额,ZooKeeper初步提供了znode节点数量和节点数据大小的配额管理的支持。能够经过配置来指定某个子树的配额,该子树就会被跟踪,若是该子树超过了配额限制,就会记录一条警告日志,但操做请求仍是能够继续执行。此时,ZooKeeper会检测是否超过了某个配额限制,但不会阻止处理流程。

配额管理的跟踪功能经过/zookeeper子树完成,因此应用程序不能在这个子树中存储本身的数据,这个子树只应该保留给ZooKeeper使用,而 /zookeeper/quota 节点就是ZooKeeper管理配额的节点。为了对应用程序/application/superApp建立一个配额项,须要在application/superApp节点下建立两个子节点zookeeper_limits和zookeeper_stats。

对于znode节点数量的限制称之为count,而对于节点数据大小的限制则为bytes。在zookeeper_limits和zookeeper_stats节点中经过count=n,bytes=m来指定配额,其中n和m均为整数,在zookeeper_limits节点中,n和m表示将会触发警告的级别(若是配置为-1就不会触发警告信息),在zookeeper_stats借点中,n和m分别表示当前子树中的节点数量和子树节点的数据信息的当前大小。

【注意:对元数据的配额跟踪】

对于子树节点数据的字节数配额跟踪功能,并不会包含每一个znode节点的元数据的开销,元数据的大小大约100字节,因此若是每一个节点的数据大小都比较小,跟踪znode节点的数量比跟踪znode数据的大小更加实用。

能够使用zkCli来建立/application/superApp节点,并配置配额限制:

[zk: localhost:2181(CONNECTED) 2] create /application ""
Created /application
[zk: localhost:2181(CONNECTED) 3] create /application/superApp super
Created /application/superApp
[zk: localhost:2181(CONNECTED) 4] setquota -b 10 /application/superApp
Comment: the parts are option -b val 10 path /application/superApp
[zk: localhost:2181(CONNECTED) 5] listquota /application/superApp
absolute path is /zookeeper/quota/application/superApp/zookeeper_limits
Output quota for /application/superApp count=-1,bytes=10
Output stat for /application/superApp count=1,bytes=5
建立了/application/superApp节点,且该节点的数据为5个字节(一个单词“super”),以后为/application/superApp节点设置了配额限制为10个字节,当列出/application/superApp节点配置限制是,发现数据大小的配额还有5个字节的余量,而并未对这个子树设置znode节点数量的配额限制,由于配额中count的值为-1。

若是发送命令get/zookeeper/quota/application/superApp/zookeeper_stats,能够直接访问该节点数据,而不须要使用zkCli工具,事实上,能够经过建立或删除这些节点来建立或删除配额配置。若是运行如下命令:

create /application/superApp/lotsOfData ThisIsALotOfData
就会在日志中看到以下信息:
Quota exceeded: /application/superApp bytes=21 limit=10

5、多租赁配置

配额,提供了配置选项中的某些限制措施,而ACL策略更值得咱们考虑如何使用ZooKeeper来服务于多租赁(multitenancy)状况。知足多租赁的一些使人信服的缘由以下:

  • 为了提供可靠的服务器,ZooKeeper服务器须要运行于专用的硬件设备之上,跨多个应用程序共享这些硬件设备更容易符合资本投资的指望。
  • 发现,在大多数状况下,ZooKeeper的流量很是具备突发性:配置或状态的变化的突发操做会致使大量的负载,从而致使服务长时间的不可用。若是是没有什么关联的应用程序的突发操做,将这些应用程序共享这个服务器更能有效利用硬件资源。不过仍是要注意失联事件发生时所产生的峰值,某些写得不太规范的应用程序在处理Disconnected事件时,产生的负载高于其所须要的资源。
  • 对于硬件资源的分摊,能够得到更好的故障容错性:若是两个应用程序,从以前各自三个服务器的集群中转移到一个由5台服务器组成的集群,总量上所使用的服务器更少了,对ZooKeeper也能够容忍两台服务器的故障,而不是以前的只能容忍一个服务器故障。

当服务于多租赁的状况下时,运维人员通常会将数据树分割为不一样的子树,每一个子树为某个应用程序所专用。开发人员在设计应用程序时能够考虑在其所用的znode节点前添加前缀,但还有一个更简单的方法来隔离各个应用程序:在链接串中指定路径部分,10.3节中介绍了这方式。每一个应用程序的开发人员在进行应用程序的开发时,就像使用专用的ZooKeeper服务同样。若是运维人员决定将应用程序部署到根路径/application/newapp之下,应用程序能够使用host:port/application/newapp链接串,而不只仅是host:port,经过这种方式,对应用程序所呈现的犹如使用专用服务同样,与此同时,运维人员还能够为/application/newapp节点配置配额限制,以便跟踪应用程序的空间使用状况。

6、文件系统布局和格式

数据存储有两类:事务日志文件和快照文件。
这些文件均以普通文件的形式保存到本地文件系统中,在进行关键路径的事务处理时就会写入事务日志文件,因此强烈建议将这些文件保存到一个专用存储设备上

快照文件将会被写入到DataDir参数所指定的目录中,而事务日志文件将会被写入到DataLogDir参数所指定的目录中。

首先,看一下事务日志目录中的文件,若是列出该目录的信息,会发现只有一个子目录,名为version-2,对日志和快照的格式只作出了一次重大改进,当改变其格式后,发现,将数据经过文件版本进行分离,对于处理版本间的数据迁移是很是有用的。

一、事务日志

在运行一些小测试后的目录内容,有两个事务日志文件:

-rw-r--r-- 1 breed 67108880 Jun 5 22:12 log.100000001
-rw-r--r-- 1 breed 67108880 Jul 15 21:37 log.200000001
能够仔细观察这些文件信息。首先,考虑到测试不多,而这些文件却很是大(每一个都超过6MB);其次这些文件名的后缀中均有一个很大数字。

ZooKeeper为文件预分配大的数据块,来避免每次写入所带来的文件增加的元数据管理开销,若是经过对这些文件进行十六进制转储打印,会发现这些文件中所有以null字符(0)填充,只有在最开始部分有少许的二进制数据,服务器运行一段时间后,其中的null字符逐渐被日志数据替换。

日志文件中包含事务标签zxid,但为了减轻恢复负载,并且为了快速查找,每一个日志文件的后缀为该日志文件中第一个zxid的十六进制形式。经过十六进制表示zxid的一个好处就是能够快速区分zxid中时间戳部分和计数器部分,因此在以前例子中的第一个文件的时间戳为1,而第二个文件的时间戳为2。

不过,还想继续看一看文件中保存了什么内容,对于问题诊断也很是有帮助。有时,开发人员宣称ZooKeeper丢失了某些znode节点信息,此时只有经过查找事务日志文件才能够知道客户端具体删除过哪些节点。

能够经过一下命令来查看第二个日志文件:
java -cp $ZK_LIBS org.apache.zookeeper.server.LogFormatter version-2 log.200000001
这个命令的输出信息以下:
7/15/13... session 0x13...00 cxid 0x0 zxid 0x200000001 createSession 30000
7/15/13... session 0x13...00 cxid 0x2 zxid 0x200000002 create
'/test,#22746573746 ...
7/15/13... session 0x13...00 cxid 0x3 zxid 0x200000003 create
'/test/c1,#6368696c ...
7/15/13... session 0x13...00 cxid 0x4 zxid 0x200000004 create
'/test/c2,#6368696c ...
7/15/13... session 0x13...00 cxid 0x5 zxid 0x200000005 create
'/test/c3,#6368696c ...
7/15/13... session 0x13...00 cxid 0x0 zxid 0x200000006 closeSession null
每一个日志文件中的事务均以可读形式一行行地展现出来。由于只有变动操做才会被记录到事务日志,因此在事务日志中不会看到任何读事务操做。

二、快照

快照文件的命名规则与事务日志文件的命名规则类似,如下为以前例子中的服务器的快照列表信息:
-rw-r--r-- 1 br33d 296 Jun 5 07:49 snapshot.0
-rw-r--r-- 1 br33d 415 Jul 15 21:33 snapshot.100000009
快照文件并不会被预分配空间,因此文件大小也更加准确地反映了其中包含的数据大小。其中后缀表示快照开始时当时的zxid值,以前已经介绍过,快照文件实际上为一个模糊快照,直到事务日志重现以后才会成为一个有效的快照文件。所以在恢复系统时,必须从快照后缀的zxid开始重现事务日志文件,甚至更早的zxid开始重现事务。

快照文件中保存的模糊快照信息一样为二进制格式,所以,能够经过另外一个工具类来检查快照文件的内容:

java -cp ZK_LIBS org.apache.zookeeper.server.SnapshotFormatter version-2 /snapshot.100000009
这个命令的输出信息以下:
----
/
cZxid = 0x00000000000000
ctime = Wed Dec 31 16:00:00 PST 1969
mZxid = 0x00000000000000
mtime = Wed Dec 31 16:00:00 PST 1969
pZxid = 0x00000100000002
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x00000000000000
dataLength = 0
----
/sasd
cZxid = 0x00000100000002
ctime = Wed Jun 05 07:50:56 PDT 2013
mZxid = 0x00000100000002
mtime = Wed Jun 05 07:50:56 PDT 2013
pZxid = 0x00000100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x00000000000000
dataLength = 3
----
....
只有每一个节点的元数据被转储打印出来,这样,运维人员就能够知道一个znode节点什么时候发生了变化,以及哪一个znode节点占用了大量内存。很遗憾,数据信息和ACL策略并无出如今输出中,所以,在进行问题诊断时,记住将快照中的信息与日志文件的信息结合起来分析问题所在。

三、时间戳文件

ZooKeeper的持久状态由两个小文件构成,它们是两个时间戳文件,其文件名为acceptedEpoch和currentEpoch,以前已经讨论过期间戳的概念,而这两个文件则反映了某个服务器进程已接受的和正在处理的信息。虽然这两个文件并不包含任何应用数据信息,但对于数据一致性却相当重要,因此若是你在备份一个ZooKeeper服务器的原始数据文件时,不要忘了这两个文件。

四、已保存的ZooKeeper数据的应用

ZooKeeper数据存储的一个优势是,无论独立模式的服务器仍是集群方式的服务器,数据的存储方式都同样。以前已经介绍过经过事务日志和快照的合并能够获得准确的数据视图,能够将事务日志文件和快照文件拷贝到另外一台设备上进行这些操做(例如在你的便携电脑中),将这些文件放到一个独立模式的服务器下空白的data目录下,而后启动服务,该服务就会真实反映出你所拷贝的那个服务器上的状态信息。这项技术能够从生产环境拷贝服务器的状态信息,用于稍后的复查等用途。

同时也意味着,只须要简单地将这些数据文件进行备份,就能够轻易地完成ZooKeeper服务器的备份,若是采用这种方式进行备份,还须要注意一些问题。首先,ZooKeeper为复制服务,因此系统中存在冗余信息,若是进行备份操做,只须要备份其中一台服务器的数据信息。

当ZooKeeper服务器承认了一个事务,从这时起它就会承诺记录下该状态信息,必定要记住这一点,这一点很是重要。所以若是使用旧的备份文件恢复一个服务器,就会致使服务器违反其承诺。若是刚刚遭遇了全部服务器的数据丢失的状况,这可能不是什么大问题,但若是你的集群在正常工做中,而你将某个服务器还原为旧的状态,你的行为可能会致使其余服务器也丢失了某些信息。

若是要对所有或大多数服务器进行数据丢失的恢复操做,最好的办法是使用最新抓取的状态信息(从最新的存活服务器中获取的备份文件),并在启动服务器以前将状态信息拷贝到其余全部服务器上。

7、四字母命令

四字母命令提供的这一简单方法,可让对系统进行各类各样的检查。四字母命令的主要目标就是提供一个很是简单的协议,使使用简单的工具,如telnet或nc,就能够完成系统健康情况检查和问题的诊断。为简单起见,四字母命令的输出也是可读形式,使得更容易使用这些命令。

对服务器添加一个新的命令也很容易,命令列表也就会增加。本节中将会介绍一些经常使用的命令,对于最新的所有命令列表信息,请参考ZooKeeper文档。

  • ruok
    提供(有限的)服务器的状态信息。若是服务器正在运行,就会返回imok响应信息。事实上“OK”状态只是一个相对的概念,例如,服务器运行中,虽没法与集群中其余服务器进行通讯,然而该服务器返回的状态仍然是“OK”。对于更详细信息及可靠的健康状态检查,须要使用stat命令。
  • stat
    提提供了服务器的状态信息和当前活动的链接状况,状态信息包括一些基本的统计信息,还包括该服务器当前是否处于活动状态,即做为群首或追随者,该服务器所知的最后的zxid信息。某些统计信息为累计值,能够使用srst命令进行重置。
  • srvr
    提供的信息与stat同样,只是忽略了链接状况的信息。
  • dump
    提供会话信息,列出当前活动的会话信息以及这些会话的过时时间。该命令只能在群首服务器上运行。
  • conf
    列出该服务器启动运行所使用的基本配置参数。
  • envi
    列出各类各样的Java环境参数。
  • mntr
    提供了比stat命令更加详细的服务器统计数据。每行输出的格式为key<tab>value。(群首服务器还将列出只用于群首的额外参数信息)。
  • wchs
    列出该服务器所跟踪的监视点的简短摘要信息。
  • wchc
    列出该服务器所跟踪的监视点的详细信息,根据会话进行分组。
  • wchp
    列出该服务器所跟踪的监视点的详细信息,根据被设置监视点的

znode节点路径进行分组。

  • cons,crst
    cons命令列出该服务器上每一个链接的详细统计信息,crst重置这些链接信息中的计数器为0。

8、经过JMX进行监控

四字母命令能够用于系统的监控,但却没有提供系统控制和修改的方法,ZooKeeper经过标准Java管理协议,JMX(Java管理扩展),提供了更强大的监控和管理功能。

本节中,将会使用一个简单的管理控制台工具jconsole来探索经过JMX管理ZooKeeper功能。

jconsole为Java中自带的工具,实际上,相似jconsole这样的JMX工具经常用于监控远程的ZooKeeper服务器,但出于说明的目的,将会在ZooKeeper服务所运行的设备运行该工具。

首先、启动第二个ZooKeeper服务器(即ID为2的服务器),以后,只须要在命令行中简单的输入jconsole命令就能够启动jconsole工具,jconsole启动后,就会看到相似图10-7中所示的窗口。

注意到其中带有“zookeeper”名称的进程,对于本地进程,jconsole会自动发现可链接的进程。
【图10-7:jconsole启动界面】
clipboard.png

如今,只须要在列表中双击该进程就能够链接到ZooKeeper进程上,由于没有启用SSL,此时会提示关于非安全链接的选项,单击非安全链接按钮,以后屏幕中就会出现图10-8所示的窗口。
【图10-8:进程管理的第一个窗口】
clipboard.png

从这个界面中看到,能够经过该工具获取关于ZooKeeper服务器的各类各样有趣的统计信息。JMX支持经过MBean(托管Bean)来将自定义信息暴露给远程管理者,虽然名字听起来比较笨拙,但倒是暴露信息和操做的一个很是灵活的方式。jconsole会在最右侧的信息标签中列出进程暴露的全部MBean信息,如图10-9所示。
【图10-9:jconsole中MBean信息】
clipboard.png

在MBean列表中能够看到ZooKeeper所使用且暴露出来的组件信息,比较关心ZooKeeperService的信息,所以双击该列表项,将会看到一个分级的列表副本以及这些副本的信息,若是打开某些列表中的子项,会看到图10-10所示的信息。
【图10-10:jconsole中关于服务器2的信息】
clipboard.png

经过浏览replica.2的信息,注意到这些信息中还包括其余副本
的信息,但只是一些通讯信息,由于服务器2对其余副本所知信息并很少,因此服务器2没法展现更多其余副本信息,而服务器2很了解本身的信息,因此它能够暴露更多的信息。

当启动服务器1,服务器2就能够与服务器1构成一个法定人数,此时就能够看到服务器2的更多信息。启动服务器1,以后再次经过jconsole检查服务器2信息。图10-11展现了经过JMX暴露的一些额外信息,能够看到服务器2当前角色为追随者,还能够看到数据数的信息。

图10-11还展现了服务器1的一些信息,看到,服务器1的角色为群首角色,同时还有一些额外信息,仅在群首服务器中,FollowerInfo中还会展现追随者的列表。当点击该按钮,会看到链接到服务器1的其余ZooKeeper服务器的原始列表信息。
【图10-11:jconsole中关于服务器1的信息】
clipboard.png

到目前为止,看到相比四字母命令,经过JMX所看到的信息更加优美直观,可是尚未看到有什么新功能,如今看看JMX能够作到而四字母命令没法作到的功能。启动zkCli脚本工具,链接到服务器1,以后运行如下命令:

create -e /me "foo"

经过该命令,会建立一个临时性的znode节点,图10-11所示的服务器1的JMX信息中,能够看到出现了一个关于链接的新信息项,链接的属性中列出了各类各样的信息,这些信息对于调试运行问题很是有用。这个视图中,还看到两个有意思的操做:terminateSession和terminateConnection。

terminateConnection操做会关闭ZooKeeper客户端到服务器之间的链接,而会话依然处于活跃状态,因此此时客户端还能够从新链接到另外一个服务器,客户端会收到失去链接的事件,但能够轻易恢复。

与之相反,terminateSession操做会声明会话已经死亡,客户端与服务器之间的链接将会被关闭,且会话也将因过时而停止,客户端也不能再使用这个会话与其余服务器创建链接。所以,使用terminateSession操做时须要当心,由于该操做会在会话超时以前就致使会话过时,因此在该进程本身发现过时前,其余进程可能已经发现了该进程的会话死亡的状况。

远程链接

JMX代理器运行于ZooKeeper服务器的JVM之中,若是链接远程的ZooKeeper服务器,须要配置好JMX代理器。对与远程链接的JMX协议有若干参数须要配置,本节中,展现了一种JMX的配置方式,来看看JMX提供了什么样功能。若是在生产环境使用JMX,可能须要使用另外一种JMX配置——具体参考如何配置更高级的安全功能。

对JMX的配置能够经过系统属性的方式进行配置,在用于启动ZooKeeper服务器的zkServer.sh脚本中,使用SERVER_JVMFLAGS环境变量来配置这些系统属性。

例如,如下面的配置启动服务,就能够远程链接服务器3的55555端口。

SERVER_JVMFLAGS="-Dcom.sun.management.jmxremote.password.file=passwd \
-Dcom.sun.management.jmxremote.port=55555 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.access.file=access"
 _path_to_zookeeper_/bin/zkServer.sh start   _path_to_server3.cfg_

系统属性参数中用到了密码文件和访问控制文件,这些文件的格式很是简单。首先,建立passwd文件,方式以下:

# user password
admin <password>

注意,密码文件中的密码信息为明文保存,所以只能给密码文件的全部者分配读写权限,若是不这样作,Java就没法启动服务。同时,关闭了SSL功能,这意味着密码信息在网络上会以明文的方式进行传输,若是须要更强的安全级别,JMX也提供了更强有力的选项,但这些已经超出本书所涉及的范围。

对于访问控制文件,将会给admin用户赋予readwrite权限,建立该文件的方式以下:

admin readwrite

9、工具

在ZooKeeper发行包的contrib目录中,能够找到一些软件,这些软件能够帮你集成ZooKeeper到其余的检测系统中去。列出了一部分最受欢迎的软件或工具:

  • 经过C绑定实现的Perl和Python语言的绑定库。
  • ZooKeeper日志可视化的软件。
  • 一个基于网页的集群节点浏览和ZooKeeper数据修改功能的软件。
  • ZooKeeper中自带的zktreeutil和guano都可以从GitHub下载。这些软件能够对ZooKeeper的数据进行导入和导出操做。
  • zktop,也能够从GitHub下载,该软件监控ZooKeeper的负载,并提供Unix的top命令相似的输出。
  • ZooKeeper冒烟测试,能够从GitHub上下载。该软件对ZooKeeper集群提供了一个简单的冒烟测试客户端,这个工具对于开发人员熟悉ZooKeeper很是不错。
相关文章
相关标签/搜索