zookeeper03-ZooKeeper的安装和配置

1、安装ZooKeeper(独立模式)

1、部署环境

  • 软件版本
    • ZooKeeper:apache-zookeeper-3.5.9-bin.tar.gz
  • 系统环境
    • 10.1.1.11:CentOSLinuxrelease7.7.1908(Core)

2、下载ZooKeeper

官网:https://zookeeper.apache.org
下载地址:https://archive.apache.org/dist/zookeeper/
安装包:apache-zookeeper-3.5.9-bin.tar.gz    --注意,要下载二进制安装包(名称带bin的)

3、安装ZooKeeper

]# tar zvfx ./apache-zookeeper-3.5.9-bin.tar.gz -C /usr/local/    --解压之后在/usr/local/目录下生成一个名为apache-zookeeper-3.5.9-bin的文件夹

4、配置zookeeper的环境变量

--向/etc/profile文件中添加如下配置
]# vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/apache-zookeeper-3.5.9-bin/
export PATH=$PATH:$ZOOKEEPER_HOME/bin
#为了查看事务日志和快照(在一台服务器上开启即可)
#JAVA_OPTS="$JAVA_OPTS -Djava.ext.dirs=$ZOOKEEPER_HOME:$ZOOKEEPER_HOME/lib"
#为了使用超级管理员super(在一台服务器上开启即可)。使用方式addauth digest super:asdf
#export SERVER_JVMFLAGS
#SERVER_JVMFLAGS=-Dzookeeper.DigestAuthenticationProvider.superDigest=super:T+4Qoey4ZZ8Fnni1Yl2GZtbH2W4=

--使配置生效
]# source /etc/profile

5、修改ZooKeeper的配置文件

--将zoo_sample.cfg文件修改为zoo.cfg
]# cp /usr/local/apache-zookeeper-3.5.9-bin/conf/{zoo_sample.cfg,zoo.cfg}
 
--修改zoo.cfg文件
]# vim /usr/local/apache-zookeeper-3.5.9-bin/conf/zoo.cfg
#ZooKeeper服务法心跳时间,单位为ms
tickTime=2000
#投票选举新leader的初始化时间
initLimit=10
#leader与follower心跳检测最大容忍时间,响应超过syncLimit*tickTime,leader认为follower“死掉”,从服务器列表中删除follower
syncLimit=5
#ZooKeeper对外服务端口
clientPort=2181
#快照目录
dataDir=/tmp/zookeeper/data
#事务日志目录
dataLogDir=/tmp/zookeeper/log
#允许执行reconfig命令
#reconfigEnabled=true
#允许执行四字母命令
#4lw.commands.whitelist=*

--创建目录
]# mkdir -p /tmp/zookeeper/{data,log}

6、添加ZooKeeper服务器编号

  • 在${dataDir}目录(也就是ZooKeeper的数据目录/tmp/zookeeper/data )下创建一个myid文件,并写入一个数值,比如0。
  • myid文件里存放的数值就是ZooKeeper服务器的编号。
]# echo '1' > /tmp/zookeeper/data/myid

7、启动Zookeeper服务

]# zkServer.sh start               --启动zookeeper服务(因为加了zookeeper的环境变量,因此可以不用使用绝对路径/usr/local/apache-zookeeper-3.5.9-bin/bin/zkServer.sh)
]# zkServer.sh stop                --停止zookeeper服务
]# zkServer.sh status              --查看zookeeper服务的状态

]# zkServer.sh start-foreground    --在前台启动zookeeper服务
]# zkServer.sh print-cmd           --打印启动zookeeper服务时的环境变量

2、安装ZooKeeper(仲裁模式)

1、部署环境

  • 软件版本
    • ZooKeeper:apache-zookeeper-3.5.9-bin.tar.gz
  • 系统环境
    • 10.1.1.11:CentOSLinuxrelease7.7.1908(Core)
    • 10.1.1.12:CentOSLinuxrelease7.7.1908(Core)
    • 10.1.1.13:CentOSLinuxrelease7.7.1908(Core)

2、下载ZooKeeper

官网:https://zookeeper.apache.org
下载地址:https://archive.apache.org/dist/zookeeper/
安装包:apache-zookeeper-3.5.9-bin.tar.gz    --注意,要下载二进制安装包(名称带bin的)

3、安装ZooKeeper

]# tar zvfx ./apache-zookeeper-3.5.9-bin.tar.gz -C /usr/local/    --解压之后在/usr/local/目录下生成一个名为apache-zookeeper-3.5.9-bin的文件夹

4、配置zookeeper的环境变量

--向/etc/profile文件中添加如下配置
]# vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/apache-zookeeper-3.5.9-bin/
export PATH=$PATH:$ZOOKEEPER_HOME/bin
#为了查看事务日志和快照(在一台服务器上开启即可)
#JAVA_OPTS="$JAVA_OPTS -Djava.ext.dirs=$ZOOKEEPER_HOME:$ZOOKEEPER_HOME/lib"
#为了使用超级管理员super(在一台服务器上开启即可)。使用方式addauth digest super:asdf
#export SERVER_JVMFLAGS
#SERVER_JVMFLAGS=-Dzookeeper.DigestAuthenticationProvider.superDigest=super:T+4Qoey4ZZ8Fnni1Yl2GZtbH2W4=

--使配置生效
]# source /etc/profile

5、修改ZooKeeper的配置文件

  • 1-4步骤与独立模式一样。
--将zoo_sample.cfg文件修改为zoo.cfg
]# cp /usr/local/apache-zookeeper-3.5.9-bin/conf/{zoo_sample.cfg,zoo.cfg}
   
--修改zoo.cfg文件
]# vim /usr/local/apache-zookeeper-3.5.9-bin/conf/zoo.cfg
#ZooKeeper服务法心跳时间,单位为ms
tickTime=2000
#投票选举新leader的初始化时间
initLimit=10
#leader与follower心跳检测最大容忍时间,响应超过syncLimit*tickTime,leader认为follower“死掉”,从服务器列表中删除follower
syncLimit=5
#ZooKeeper对外服务端口
clientPort=2181
#快照目录
dataDir=/tmp/zookeeper/data
#事务日志目录
dataLogDir=/tmp/zookeeper/log
#ZooKeeper集群中服务器的列表    --和独立模式不同的地方,
server.1=10.1.1.11:2888:3888
server.2=10.1.1.12:2888:3888
server.3=10.1.1.13:2888:3888
#允许执行reconfig命令
#reconfigEnabled=true
#允许执行四字母命令
#4lw.commands.whitelist=*
#禁止leader为客户端提供服务
#leaderServes=no
   
--创建目录
]# mkdir -p /tmp/zookeeper/{data,log}
  • 为了便于讲解上面的配置,这里抽象出一个公式,即server.A=B:C:D
    • A是一个数字,代表服务器的编号,就是myid文件里面的值。集群中每台服务器的编号都必须唯一,所以要保证每台服务器中的myid文件中的值不同。
    • B代表服务器的IP地址。
    • C表示服务器与集群中的leader服务器交换信息的端口。
    • D表示ZooKeeper服务器用于选举leader时相互通信的端口。

6、添加ZooKeeper服务器编号

  • 在${dataDir}目录(也就是ZooKeeper的数据目录/tmp/zookeeper/data )下创建一个myid文件,并写入一个数值,比如0。
  • myid文件里存放的数值就是ZooKeeper服务器的编号。(集群中每台服务器的编号都必须唯一
--分别在三台机器的数据目录中添加myid文件,其内容是服务器的编号(在同一个集群中,编号唯一):
--10.1.1.11
]# echo '1' > /tmp/zookeeper/data/myid
--10.1.1.12
]# echo '2' > /tmp/zookeeper/data/myid
--10.1.1.13
]# echo '3' > /tmp/zookeeper/data/myid

7、启动Zookeeper服务

]# zkServer.sh start               --启动zookeeper服务(因为加了zookeeper的环境变量,因此可以不用使用绝对路径/usr/local/apache-zookeeper-3.5.9-bin/bin/zkServer.sh)
]# zkServer.sh stop                --停止zookeeper服务
]# zkServer.sh status              --查看zookeeper服务的状态

]# zkServer.sh start-foreground    --在前台启动zookeeper服务
]# zkServer.sh print-cmd           --打印启动zookeeper服务时的环境变量

3、ZooKeeper的配置选项

  • 官方说明:http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
  • 熟悉ZooKeeper不同的配置选项,可以获得更高的性能,也更容易诊断问题所在。
  • 为了保证ZooKeeper服务的正常运行,必须对其进行正确的配置。根据我们的经验,不适当或不一致的配置是问题的主要来源。因此,在集群中所有参与投票的ZooKeeper服务器配置必须相同。
  • ZooKeeper服务器在启动时从一个名为zoo.cfg的配置文件读取所有选项。如果多个服务器所扮演的角色相似,其基本配置信息是一样的,可以共享一个文件。data目录下的myid文件用于区分各个服务器,对每个服务器来说myid文件必须是唯一的,因此这个目录可以保存一些差异化文件。myid文件中包含的服务器ID作为配置文件的索引,这样一个特定的ZooKeeper服务器可以知道如何配置自己参数。当然,如果服务器具有不同的配置参数(例如,事务日志保存在不同的地方) ,每个服务器就需要使用自己唯一的配置文件。
  • 配置参数通常在配置文件中设置。很多参数也可以通过Java的系统属性传递,其形式通常为zookeeper.propertyName,在启动服务器时,通过-D选项设置这些属性。不过,系统属性所对应的特定参数对服务来说是插入的配置,配置文件中的配置参数优先于系统属性中的配置

3.1、基本配置

  • 有些配置参数没有默认值,必须为每个部署设置。

1、clientPort

  • 客户端连接到此服务器的TCP端口。默认情况下,服务器将在它的所有接口上侦听这个端口上的连接,除非设置了clientPortAddress。clientPort的值可以是任意数字,不同的ZooKeeper服务器可以监听不同的端口。
  • 默认端口为2181

2、dataDir

  • dataDir是存储内存中数据库的模糊快照的目录。如果此服务器是集群的一部分,则id文件也将在此目录中。
  • dataDir不需要配置到一个专用存储设备上,快照将会以后台线程的方式写入,且并不会锁定数据库,在快照完成之前,对存储的写入不会同步。

3、dataLogDir

  • dataLogDir是事务日志存储的目录。事务日志对该目录所处的存储设备上的其他活动非常敏感,服务端会尝试对事务日志进行顺序写入,因为在服务端确认事务前,数据必须同步到存储中,该设备的其他活动(尤其是快照的写人)可能导致同步时磁盘过于忙碌,从而影响写入的吞吐能力。因此,最佳的方法是使用专用的日志存储设备,将dataLogDir配置的目录指向该设备
  • 如果不设置dataLogDir,事务日志将存储到dataDir指定的目录。

4、tickTime

  • tick是ZooKeeper使用的时间基本度量单位,以毫秒为单位,该值还决定了会话超时的存储器大小。
  • Zookeeper集群中使用的超时时间单位通过tickTime指定,实际上tickTime设置了超时时间的下限值,因为最小的超时时间为一个tick时间,客户端最小会话超时事件为两个tick时间。
  • tickTime的默认值是3000毫秒,更低的tickTime值可以更快地发现超时问题,但也会导致更高的网络流量(心跳消息)和更高CPU使用率(会话存储器的处理)

3.2、存储配置

  • 本节介绍一些可以应用于独立模式,也可以应用于集群模式下的配置,这些参数不设置的话并不会影响ZooKeeper的功能,但有些参数(如dataLogDir)最好还是配置。

1、preAllocSize

  • 设置预分配给事务日志文件(zookeeper.preAllocSize)的大小,以KB为单位。(设置事务日志文件的大小)
  • 当写入事务日志文件时,服务端每次会分配preAllocSize值大小的存储,通过这种方式可以分摊文件系统在磁盘上分配存储空间和更新元数据的开销,更重要的是,该方式也减少了磁盘寻址的次数。
  • preAllocSize的默认值是64MB。减小该值的一个原因是事务日志不会增长那么大。因为每次快照后都会重新启动一个新的事务日志,如果每次快照之间的事务数量很少,而且事务本身也很小,那么64MB就显然太大了。例如,如果我们每1000个事务进行一次快照,每个事务的平均大小为100字节,那么100KB的则更加合适。默认的preAllocSize适用于默认的snapCount和平均大小大于512字节的事务。

2、snapCount

  • 每次快照之间的事务数(zookeeper.snapCount)。
  • 当Zookeeper服务器重启后,需要恢复其状态。恢复状态所需的两个主要时间段是::读取快照所需的时间,以及快照启动后应用事务的时间。在读取快照后,通常会最小化必须应用的事务数量。然而,快照确实对服务器的性能有影响,即使快照是在后台线程中写入的。
  • snapCount的默认值是100000。因为进行快照时会影响性能,所以集群中所有服务器最好不要在同一时间进行快照操作,只要仲裁数量的服务器不会一同进行快照,处理时间就不会受影响。因此,每次快照中实际的事务数是一个接近snapCount值的随机数。
  • 注意,如果snapCount数已经达到,但前一个快照正在进行中,则不会启动新的快照,服务器也将继续等到下一个snapCount数量的事务后再开启一个新的快照。

3、autopurge.snapRetainCount

  • 清除快照和日志时,需要保留的快照数量和相应的事务日志。
  • ZooKeeper将会定期对快照和事务日志进行清除,autopurge.snapRetainCount值指定需要保留的快照数。显然,并不是所有的快照都可以被删除,因为那样就不可能进行服务器的恢复操作。autopurge.snapRetainCount的最小值为3,也是默认值。

4、autopurge.purgeInterval

  • 对快照和日志进行清除的时间间隔,以小时为单位。如果设置为一个非0的数字,autopurge.purgeInterval指定了清除的时间间隔。如果设置为0,默认情况下,清除不会自动执行,需要通过ZooKeeper发行包中的zkCleanup.sh脚本手动运行。

5、fsync.warningthresholdms

  • 事件同步到存储时,超过fsync.warningthresholdms设置的时间就会产生一个警告消息,以毫秒为单位。
  • fsync.warningthresholdms的默认值是1000毫秒
  • ZooKeeper服务器在应答消息前会将事件同步到存储中。如果同步消耗了太长时间,系统性能就会受到严重影响,服务器会跟踪同步调用的持续时间,如果超过fsync.warningthresholdms只就会产生一个警告消息。

6、weight.x=n

  • 通常使用在集群模式下,该选项指定了服务器的权重为n,表示该服务器在进行投票时其有n票。在ZooKeeper中一些事件需要进行投票,比如leader选举中和原子广播协议中。
  • 默认情况下,一个服务器的权重值为1

7、traceFile

  • 跟踪ZooKeeper的操作,并将操作记录到跟踪日志中,跟踪日志的文件名为traceFile.year.month.day,除非设置了该选项(requestTraceFile),否则跟踪功能将不会启用。
  • 该选项用来提供ZooKeeper所进行操作的详细视图。不过,要想记录这些日志,ZooKeeper服务器必须将这些操作序列化,并写入磁盘,这将争用CPU和磁盘。如果你使用了该选项,请确保不要将跟踪文件放到日志文件的存储设备中。我们还需要知道,跟踪选项还可能影响系统运行,甚至很难重现跟踪选项关闭时发生的问题。另外还有个有趣的问题,traceFile选项的Java系统属性配置中不含有zookeeper前缀,而且系统属性的名称也与配置选项名称不同,这一点请小心。

3.3、网络配置

  • 限制服务器和客户端之间的通信,以及超时。

1、globalOutstandingLimit

  • ZooKeeper中待处理的最大请求数(zookeeper.globaloutstandingLimit)。
  • ZooKeeper客户端提交请求的速度比ZooKeeper服务器处理请求的速度要快很多。这将导致请求在ZooKeeper服务器上排队,并最终(如在几秒钟内)导致服务器内存溢出。为了防止发生这种情况,如果ZooKeeper服务器中待处理的请求达到globalOutstandingLimit值,服务器就会开始限制客户端的请求,但是globalOutstandingLimit并不是硬性限制。每个客户端必须至少有一个未完成的请求,否则连接将开始超时。因此,在达到globalOutstandingLimit后,服务器只有在没有任何待处理的请求时才会继续接收客户端的请求。
  • 为了确定某个服务器的全局限制值,只需将该参数的值除以服务器的数量。目前还没有更智能的方式去计算全局待处理的请求数量,并据此实施限制。因此,该限制值为待处理请求的上限值。事实上,在服务器之间实现负载的完美均衡通常是不可能的,因此,即使没有达到全局限制,一些运行速度稍慢或负载稍重的服务器也可能被限制住吞吐量。
  • globalOutstandingLimit的默认值是1000个。你可能并不会修改该参数值,但有许多客户端正在发送非常大的请求,您可能需要降低该值,但我们从未看到在实践中需要更改它。

2、maxClientCnxns

  • 允许每个IP地址的并发socket连接的最大数量。
  • ZooKeeper使用流量控制和限制来避免过载情况。建立连接所使用的资源远远高于正常请求所需的资源。我们曾看到过这样的案例,客户端每秒创建很多ZooKeeper连接,最后导致拒绝服务(Dos)。为了解决这个问题,我们添加了这个选项,通过它可以在某个IP地址已经有maxClientCnxns个连接时拒绝该IP地址的新连接。
  • maxClientCnxns的默认值是60个
  • 注意,每个服务器独自地维护着连接的数量。如果我们的集群中有5台服务器,并且使用默认的并发连接数60,一个欺诈性的客户端会随机连接到这5个不同的服务器,正常情况下,该客户端可以建立近300个连接(以单个IP地址),之后才会触发某个服务器的限制。

3、clientPortAddress

  • 指定服务器IP地址接收客户端连接。默认情况下,Zookeeper服务器会监听所有网络接口地址。
  • 有些服务器配置了多个网络接口,其中一个网络接口用于内网通信,另一个网络接口用于公网通信,如果你并不希望服务器在公网接口接受客户端的连接,只需要将clientPortAddress设置为内网接口的地址。

4、minSessionTimeout

  • 会话的最小超时时间,单位为毫秒。当客户端建立一个连接后就会请求一个明确的超时值,而客户端实际获得的超时值不会低于minSessionTimeout的值。
  • ZooKeeper开发人员希望能够立即准确地检测出客户端故障。遗憾的是,系统不可能实时处理这种情况,而是通过心跳和超时来处理。超时取决于ZooKeeper客户端与服务器之间的响应能力,更重要的是两者之间的网络延时和可靠性。超时时间最小值为客户端与服务器之间的往返时间,但偶尔还是可能发生丢包现象,当这种情况发生时,因为重传超时导致接收响应时间的增加,并会导致接收重发包的延时。
  • minSessionTimeout的默认值是tickTime的2倍。该参数值过低可能会导致错误的客户端故障检测,该参数值过高会延迟客户端故障的检测时间。

5、maxSessionTimeout

  • 会话的最大超时时间值,单位为毫秒。当客户端建立一个连接后就会请求一个明确的超时值,而客户端实际获得的超时值不会高于maxSessionTimeout的值。
  • 虽然该参数并不会影响系统的性能,但却可以限制一个客户端消耗系统资源的时间,maxSessionTimeout默认值是tickTime的20倍

3.4、集群配置

  • 在配置ZooKeeper集群时,我们需要对每台服务器进行配置,使其具有正确的时间和服务器列表,以便服务器之间能够相互连接并检测故障。在所有ZooKeeper服务器上这些参数必须保持一致。

1、initLimit

  • 对于follower最初连接到leader时的超时值,单位为tick值的倍数。
  • 当某个follower与leader进行初次连接时,可能会有相当多的数据要传输,尤其是follower已经远远落后的时候。initLimit应该根据leader和follower之间的网络传输速度和要传输的数据量来设置。如果ZooKeeper存储的数据量特别大(即存在大量的znode节点或大数据集)或者网络非常缓慢,就需要增大initLimit值。因为该值取决于环境,所以没有默认值。你需要为该参数配置适当的值,以便可以传输所期望的最大快照。因为一次可能有多个传输发生,所以您可能希望将initLimit设置为预期时间的两倍。如果配置initLimit值过高,那么首次连接到故障的服务器就会消耗更多的时间,同时还会增加恢复时间。出于这个原因,最好在follower与leader之间进行网络基准测试,以你规划的数据量来测试出你所期望的时间。

2、syncLimit

  • follower与leader进行同步(sync)的超时时间,单位为tick值的倍数。
  • follower总是会稍稍落后于leader,但是如果因为服务器负载或网络问题,就会导致follower落后leader太多,甚至需要放弃该follower。如果leader与follower无法进行sync操作,而且超过了syncLimit时间,就会放弃该follower。与initLimit类似,syncLimit也没有默认值,必须设置。与initLimit不同的是,syncLimit并不依赖于ZooKeeper存储的数据量,而是依赖于网络的延迟和吞吐量。在高延迟网络环境中,发送数据和获得响应需要更长的时间,此时就需要增加syncLimit。即使在相对低延迟的网络中,您也可能需要增加syncLimit,因为任何相对较大的事务都可能需要一段时间才能发送给follower。

3、leaderServes

  • 指示leader是否为客户端提供服务(zookeeper.leaderServes),值为"yes"或"no"。
  • leader需要做很多工作,它需要与所有follower进行通信并会执行所有的变更操作,也就意味着leader的负载会高于follower的负载。如果leader过载,整个系统可能都会受到影响。
  • 如果设置为"no",则可以减轻leader为客户端连接提供服务的负担,使leader将所有资源用于处理follower发送给它的写请求,这样可以提高系统状态变更操作的吞吐能力。换句话说,如果leader自己不直接处理任何客户端连接,那么follower就会有更多的客户端,因为原本会连接到leader的客户端会被分散到follower上,尤其是集群中服务器数量比较少的时候。leaderServes的默认值是"yes"。

4、server.x=[hostname]:n:n[:observer]

  • 服务器x的配置参数。
  • ZooKeeper服务器需要知道它们如何通信。配置文件中该配置项就指定了服务器x的配置信息,其中x是服务器的ID值(一个整数)。当服务器启动时,它就会读取data目录下myid文件中的值,之后服务器就会使用这个值查找server.x条目,它将使用这个条目中的数据配置自己。如果需要连接到另一个服务器y,就会使用server.y条目的配置信息来与这个服务器进行通信。
  • hostname是网络中服务器的名称。后面两个是TCP端口号,第一个端口用于发送事务第二个端口用于leader选举,典型的端口配置为2888:3888。如果最后一个字段标记了observer属性,该服务器就会进入观察者模式。
  • 注意,所有的服务器使用相同的server.x配置信息,这一点非常重要,否则的话,因服务器之间可能无法正确建立连接而导致整个集群无法正常工作。

5、cnxTimeout

  • 在leader选举期间打开连接的超时时间(zookeeper.cnxTimeout)。
  • ZooKeeper服务器在leader选举时相互连接。这个值决定了服务器再次尝试之前等待连接完成的时间。cnxTimeout的默认值是5秒,该值足够大,也许你并不需要修改。

6、electionAlg

  • 选举算法。
  • 它在不同的leader选举算法中进行选择,但除了一个默认算法外,其他算法都已经弃用了,所以你并不需要配置这个选项。

3.5、不安全的选项

  • 下面的选项可能很有用,但是在使用它们时要小,因为他们是在非常特殊的情况下使用的。大多数运维人员认为并不需要这些配置。

1、forceSync

  • 用于控制是否将数据同步到存储(zookeeper.forceSync),可用的值是"yes"或"no"。
  • forceSync的默认值是yes,即只有将事务在同步到存储设备后才会应答。同步系统调用的开销很大,而且也是事务处理中最大的延迟原因之一。
  • 如果forcesync配置为no,事务会在写入到操作系统后就立刻应答,但在将事务写入磁盘之前,这些事务常常缓存于内存之中。将forceSync设置为no将提高性能,但代价是服务器崩溃或停电故障时可恢复性。

2、jute.maxbuffer(仅适用于Java系统属性)

  • 请求或响应的最大大小,以字节为单位。这个选项只能通过Java的系统属性进行配置,并且选项名称没有zookeeper前缀。
  • ZooKeeper中内置了一些健康检查,其中之一就是对可传输的znode节点数据大小的检查。ZooKeeper用于存储配置数据,配置数据一般由少量的元数据信息(大约几百字节)所组成。默认情况下,如果请求或响应消息大于1MB,就会被系统拒绝。你可能想使用这个属性使健全检查变小,或者你真的疯了,增加它。
  • 注意:修改健康检查值
    • 虽然通过jute.maxbuffer指定的限制值可以进行大块数据的写人操作,但当获取有很多子znode的znode的子znode列表时就会出现问题。如果一个znode节点含有几十万个子znode,每个子znode的名字长度平均为10个字符,在试着返回子znode列表时就会命中默认的最大缓冲大小检查,此时就会导致连接被重置

3、skipACL

  • 跳过所有ACL检查(zookeeper.skipACL)。
  • 处理ACL检查会有一定的开销,通过该选项可以关闭ACL检查功能,这样做可以提高性能,但也会将数据完全暴露给任何一个可以连接到服务器的客户端。

4、readonlymode.enabled(仅适用于Java系统属性)

  • 将该配置设置为true可以启用服务器的只读模式。客户端可以以只读模式的请求连接到服务器并读取信息(可能是已过期的信息),即使该服务器在仲裁中因分区问题而被分隔。为了启用只读模式,客户端需要将canereadonly设置为true。
  • 该功能可以使客户端即使在网络分区发生时也能读取(不能写入)ZooKeeper的状态。在这种情况下,被分区而分离的客户端依然可以继续取得进展,并不需要等待分区问题被修复。需要注意的是,如果ZooKeeper服务器与集群的其他服务器断开连接,则可能会以只读模式结束服务。

3.6、日志

  • ZooKeeper采用SLFAJ库(Java简易日志门面)作为日志的抽象层,默认使用Log4J进行实际的日志记录功能。使用两层日志抽象看起来似乎有些多余,事实也是如此。在本节中,我们将会简单介绍如何配置Log4J,虽然Log4]非常灵活且功能强大,但是也有点复杂。关于Log4]有专门的书籍介绍,本节中,我们只是简单介绍其基本功能。
  • 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         (1)
zookeeper.console.threshold=INFO
zookeeper.log.dir=.
zookeeper.log.file=zookeeper.log
zookeeper.log.threshold=INFO
zookeeper.log.maxfilesize=256MB
zookeeper.log.maxbackupindex=20
zookeeper.tracelog.dir=${zookeeper.log.dir}
zookeeper.tracelog.file=zookeeper_trace.log
log4j.rootLogger=${zookeeper.root.logger}    (2)

#控制台
#添加"console"到rootlogger上面,如果你想使用这个
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender            (3)
log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold}    (4)
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout       (5)
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n

#将ROLLINGFILE添加到rootLogger以获得日志文件输出
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender     (6)
log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold}     (7)
log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file}
log4j.appender.ROLLINGFILE.MaxFileSize=${zookeeper.log.maxfilesize}
log4j.appender.ROLLINGFILE.MaxBackupIndex=${zookeeper.log.maxbackupindex}
log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n

#添加TRACEFILE到rootLogger,以获取日志文件输出
#将TRACE级别及以上的消息记录到日志文件
log4j.appender.TRACEFILE=org.apache.log4j.FileAppender
log4j.appender.TRACEFILE.Threshold=TRACE
log4j.appender.TRACEFILE.File=${zookeeper.tracelog.dir}/${zookeeper.tracelog.file}
log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout

#注意我们在这里包含了log4j的NDC (%x)
log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n
    • (1)第一组配置中,所有配置项均以zookeeper.开头,配置了该文件的默认值。它们实际上是系统属性,可以通过java命令行指定-D参数来覆盖它们。第一行的日志配置中,默认配置了日志消息的级别为INFO,即所有低于INFO级别的日志消息都会被丢弃,使用的appender为CONSOLE,你可以指定多个appender,例如,你如果想将日志信息同时输出到CONSOLE(控制台)和ROLLINGFILE时,可以将zookeeper.root.logger配置为INFO、CONSOLE、ROLLINGFILE。
    • (2)rootLogger指定了处理所有日志消息的记录器,因为我们没有定义任何其他记录器。
    • (3)这一行将名称CONSOLE与实际处理消息输出的类关联起来。在这里使用的是ConsoleAppender类。
    • (4)在appender的定义中也可以过滤消息,该行配置了这个appender会忽略所有低于INFO级别的消息,因为zookeeper.root.logger中定义了全局阈值为INFO。
    • (5)appender使用布局类对日志在输出前进行格式化操作。除了消息本身之外,我们使用模式布局来记录消息级别、时间、线程信息和调用位置信息。
    • (6)RollingFileAppender实现了滚动日志文件的输出,而不是只输出到单个日志文件或控制台。除非ROLLINGFILE被rootLogger引用,否则这个appender将被忽略。
    • (7)定义ROLLINGFILE的输出级别为INFO。
  • 日志记录功能会影响进程的性能,特别是开启了DEBUG级别时,与此同时,DEBUC级别提供了大量有价值的信息,可以帮我们诊断问题。有一个方法可以平衡性能和开销问,因此我们可以配置appender的日志级别为DEBUC,而rootLogger的级别为WARN。当服务器运行时,如果你需要诊断正在发生的问题,你可以通过JMX动态调整rootLogger的级别为INFO或DEBUG,更详细地检查系统的活动情况。

4、配置ZooKeeper集群

  • 在集群模式下处理请求以及选举leader都与仲裁的概念有关,如果ZooKeeper集群中存有法定人数的服务器已经启动,整个集群就可以继续工作。
  • 与之相关的一个概念是观察者(observer)。观察者与集群一同工作,接收客户端请求并处理来自leader的状态变更,但是leader在处理请求时并不会等待观察者处理请求的应答,同时集群在进行leader选举时也不会考虑观察者的通知消息。

4.1、多数原则

  • 当集群中拥有足够的Zookeeper服务器来处理请求时,我们称这组服务器的集合为quorum(仲裁法定人数)。当然,我们不希望有两组不相交的服务器集合同时处理请求,否则我们就会进入脑裂模式中。我们可以避免脑裂问题,通过定义仲裁法定人数的数量至少为所有服务器中的多数。(注:半数服务器不构成多数,您必须拥有超过一半的服务器数量才能拥有多数。)
  • 当配置多个服务器来组成ZooKeeper集群时,我们默认使用多数原则作为仲裁法定人数。ZooKeeper自动检测到它应该在复制模式下运行,因为在配置文件中有多个服务器,它默认使用多数仲裁。

4.2、配置法定人数和权重

  • 我们之前提到过关于法定人数的一个重要属性是,如果一个法定人数解散了,集群中另一个法定人数形成,这两个法定人数中至少有一个服务器交集。多数原则的法定人数无疑满足了这一交集的属性。
  • 一般,法定人数并未限制必须满足多数原则,ZooKeeper也允许灵活的配置法定人数。我们使用的特定方案是将服务器分组为不相交的集合,并为服务器分配权重。通过这种方案来组成法定人数,我们需要使多数组中的服务器形成多数投票原则。例如,我们有三个组,每个组中有三个服务器,每个服务器的权重值为1。在这种情况下,我们需要四个服务器来组成法定人数:某个组中的两个服务器,另一组中的两台服务器。总之,其数学逻辑归结为:如果我们有G个组,我们所需要的服务器为一个Gʹ(|G'| > |G|/2)组的服务器,同时对于G'组中的服务器集合g,我们还需要集合g中的集合gʹ满足集合g'的所有权重值之和Wʹ不小于集合g的权重值之和(如: Wʹ > W/2)。

2.2.1、集群分组

  • 通过以下配置选项可以创建一个组:
  • group.x=n[:n]
    • 启用法定人数的分层构建方式。x为组的标识符,等号后面的数字对应服务器的标识符。等号的右边是用冒号分隔的服务器标识符列表。注意,组与组之间不能存在交集,所有组的并集组成了整个ZooKeeper集群,换句话说,集群中的每个服务器必须在某个组中被列出一次。
  • 这里有一个例子,ZooKeeper集群中的九个服务器被分成三个不同的组:
    • group.1=1:2:3
    • group.2=4:5:6
    • group.3=7:8:9
  • 这个例子中,每个服务器的权重都一样,为了构成法定人数,我们需要两个组及这两个组中各取两个服务器,也就是总共4个服务器。但根据法定人数多数原则,我们至少需要5个服务器来构成一个法定人数。注意,法定人数不是由任意的四个服务器子集组成,例如,一个组全部服务器加上另一个组的一个服务器并不能构成法定人数。
  • 当我们在不同的数据中心部署ZooKeeper时,这种配置有很多好处。例如,一组可能表示运行于不同数据中心的一组服务器,即使这个数据中心崩溃, ZooKeeper服务也可以继续提供服务。
  • 在跨三个数据中心部署的方式可以容忍某个数据中心的故障,我们可以在其中两个数据中心中分别部署三个服务器,而在第三个数据中心只部署一个服务器。如果某个数据中心不可用,其他两个数据中心还能组成法定人数。这种配置的优点是,七台服务器中的任何四台都可以构成一个法定人数。一个缺点是服务器的数量在数据中心之间不平衡。第二个缺点是,一旦一个数据中心变得不可用,其他数据中心中任何服务器的崩溃都无法容忍。
  • 如果只有两个数据中心可用,我们可以使用权重值来表示优先权,例如,根据每个数据中心的客户端数量来配置权重值。只有两个数据中心时,如果每个服务器的权重值都一样,我们就无法容忍任何一个数据中心的失效,但是如果我们对某个服务器分配了更高的权重值,我们就可以容忍这两个数据中心中某个数据中心的失效。假设,我们在每个数据中心中分配三个服务器,并且我们将这些服务器均放到同一组中:
    • group.1=1:2:3:4:5:6
  • 因为所有的服务器默认情况下权重值都一样,因此只要6个服务器中有4个服务器有效时就可以构成法定人数。当然,这也意味着如果某个数据中心失效,我们就不能形成法定人数,即使另一个数据中心的三个服务器均有效。

2.2.2、服务器的权重

  • 为了给服务器分配不同的权重,我们使用以下配置选项:
  • weight.x=n
    • 与group选项一起配合使用,通过该选项可以为某个服务器形成法定人数时分配一个权重值n,n是服务器在投票时的权重。ZooKeeper中leader选举和原子广播协议中均需要投票。默认情况下,服务器的权重值为1。如果配置文件中定义了组的选项,但未指定权重值,那么所有的服务器的权重值都是1。
  • 假设某个数据中心只要其所有服务器都可用时,即使在其他数据中心失效,这个数据中心也可以提供服务,我们暂且称该数据中心为D1。我们可以为D1中的某个服务器分配更高的权重,以便可以更容易与其他服务器组成法定人数。
  • 假设D1中有服务器1、2和3。我们使用下面的语句为服务器1分配权重:
    • weight.1=2
  • 通过以上配置,我们就有了7个投票,在构成法定人数时,我们只需要4个投票。如果没有weight.1=2,任何服务器都需要与其他三个服务器来构成法定人数,但有了这个参数配置,服务器1与两个服务器就可以构成法定人数。因此,只要D1可用,即使其他数据中心发生故障,服务器1、2和3也能构成法定人数并继续提供服务。
  • 通过以上不同的法定人数配置的若干示例,我们看到该配置对部署的影响。我们提供的分层方案非常灵活,通过不同的权重值和组的管理可以提供不同的分层配置。

4.3、观察者

  • 观察者(observer)是ZooKeeper服务器中不参与投票但保证状态更新顺序的特殊服务器。将ZooKeeper服务器配置为观察者,只需要在其配置文件中添加:
    • peerType=observer
  • 你还需要在每个服务器的配置文件的服务器定义中添加:observer,如下所示:
    • server.1=localhost:2181:3181:observer
posted @ 2022-01-21 18:51  麦恒  阅读(225)  评论(1编辑  收藏  举报