当前位置:   article > 正文

ZooKeeper管理员指南--基于3.6.2版本_zkserver-initialize.sh的作用

zkserver-initialize.sh的作用

前言

翻译自ZK官网, 部分有省略
原文

部署

系统要求

支持的平台

  • 客户端 : Java 库, 客户端
  • 服务端 : Java 库, 服务端
  • 本地客户端: C语言绑定的客户端
  • 第三方贡献: 一些插件
    基本上就是说, GNU/ Linux 支持上面全部4种, 前面两种Java库的全平台支持, 毕竟跨平台嘛, 最后两种只有 GNU/Linux 支持, 其他平台都不支持
    在这里插入图片描述

依赖软件

需要Java 8 或者以上 (JDK8 LTS, JDK 11 LTS, JDK12. JDK9 和 10 不支持). 服务端要组成集群的话, 至少要3个独立的服务器, 在雅虎使用的机器是专门的RHEL 容器, 双核, 2GB 内存, 和 80GB IDE 硬盘.

集群搭建

推荐使用单数的机器, 比如 4个机器, 如果2个机器挂了, 就没有大多数的票, 服务就不行了, 但是5个机器的话, 挂了2个, 剩下3个仍有多数票.

注意: 生产上3个机器应该够了, 但是出于维护的考虑, 用5个机器会好一点, 因为如果维护其中1个机器的话, 还可以有1个机器的容错. 如果使用3个的话, 维护1个就不能容错了. 所有的冗余考虑都需要考虑整体的环境, 比如都使用同一个网络的话, 交换机坏了整个集群也都没用了…

下面的步骤是每个机器都要执行的:

  1. 安装Java JDK
  2. 设置Java堆, 防止内存页交换
  3. 安装 ZK 服务端的包
  4. 创建配置文件, 命名无所谓, 下面是配置模板

tickTime=2000
dataDir=/var/lib/zookeeper/
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

配置参数可以参考配置页面, 集群中的机器需要知道其他机器, 通过 server.id=host:port:port 来配置(第一个端口是成员(Quorum)端口, 第二个端口是专门用于领导选举的端口), 在 3.6.0 版本之后, 可以指定多个服务器地址, 有利于提高可用性因为服务器能够使用多个物理网络接口。指定的server id 会用来作为 myid 文件的内容. 这个 myid 文件会被放在 dataDir 指定的目录中.

  1. myid 文件内容就只是上面指定的 server.id 而已, 比如 “server.1” 的话, 文件内容就是 “1”. id 要求在集群中唯一 且介于 1-255之间, 如果使用高级特性的话, 比如说 TTL 节点, 就只能使用 1-254 (内部原因)

6.创建一个初始化标识文件 initializemyid 相同的目录中, 这个文件要使用一个空的数据目录. 当这个文件出现的时候, 一个空的数据库会被创建然后标识文件会被删除. 当没有这个文件的时候, 1个空的目录表示这个节点将没有投票权利并且 在和一个活跃的 leader 通信之前, 他都不会填充这个数据. 预期的用途就是在创建新的集群的时候应该创建这个文件.

7.如果你的配置文件创建了, 你可以通过以下命令启动ZK 服务器:

$ java -cp zookeeper.jar:lib/*:conf org.apache.zookeeper.server.quorum.QuorumPeerMain zoo.conf

QuorumPeerMain 在启动服务器的同时, 会注册 JMX 管理 beans 会同时被注册. 这样就可以通过 JMX进行管理. 详见. 可以参考 bin/zkServer.sh 中的启动命令.

  1. 通过连接到主机来测试你的部署. 在 Java中, 可以使用

$ bin/zkCli.sh -server 127.0.0.1:2181

单服务器和开发搭建

直接配置一下 配置文件, 然后运行:

bin/zkServer.sh start

管理员

设计一个ZK部署

ZK的可靠性基于:

  1. 只要少数的服务器会宕机. 这里宕机的意思是 机器崩溃, 网络错误 或者 网络和集群大多数分区
  2. 机器运行正常. 表示正常的执行代码, 正常的时钟, 存储和网络组建正常

下面的小节都是基于这两个基础来考虑的

跨机器要求

为了保证大多数机器能相互连通, 如果有F台机器可能失败, 那么应该部署 2*F+1 台服务器. 部署的机器数目最好是单数. 除此之外, 还需要考虑各种异常情况是否独立. 如果所有机器使用相同的交换机, 那么交换机坏了就都坏了, 同样道理的还有共享的电源断路器, 冷却系统等等.

单机器要求

如果你的ZK服务器需要连接其他的应用来获取资源比如说 CPU,存储,网络,内存等等,其性能会大大地受到它们的影响.ZK保证了持久化, 表示它需要使用存储介质来记录变化然后才允许操作成功, 所以要确保其依赖的存储介质不会挂起:

  • ZK的会话日志必须使用专门的设备.(专门的分区是不够的), ZK序列化地写入日志, 和其他进程共享存储设备会导致争用和数秒的延迟.
  • 避免ZK的内存交换.为了让ZooKeeper能够及时运行,内存交换是不被允许的.确保最大堆内存分配不超过物理内存.

维护

很少需要维护但是要记住以下几点:

使用中的数据目录清理

ZK数据目录包含了一些持久化的副本. 可能是快照或者是事务日志文件, 任何变化都会被 znode 记录到 事务日志. 某些情况下, 当日志太大的时候, 会使用 快照的形式 保存到文件系统 并且 新的事务 会使用新的 日志文件.在创建快照的过程中,ZK可能还会把日志写到旧的日志文件里面, 因此 有些比 创建快照时候 更新的事务会在创建快照之前的 日志文件中被找到.

ZK服务器在默认配置下是不会移除快照和事务日志的.

PurgeTxnLog 工具实现了一个简单的持久化策略. API文档 包含了转换的细节.

下面的例子中, 最后的 count 个快照 和 关联的日志还会被保留, 其他的会被删除, 该值通常应该大于3 (尽管不是必须的, 但是它会在日志文件崩溃的时候提供至少3个备份). 这个可以被运行为 cron 任务(定时任务)来每天自动清理日志.

java -cp zookeeper.jar:lib/slf4j-api-1.7.5.jar:lib/slf4j-log4j12-1.7.5.jar:lib/log4j-1.2.17.jar:conf org.apache.zookeeper.server.PurgeTxnLog <dataDir> <snapDir> -n <count>

版本 3.4.0 之后可以通过 autopurge.snapRetainCountautopurge.purgeInterval 配置自动清除

日志清除(Log4j)

使用log4j 内置的 rolling file appender 实现的, 下面会提供一个示例配置.

监督(Supervision)

你可能会想要有一个自动监督每个ZK进程的监督进程. ZK服务器被设计为"快速失败", 也就是说, 如果发生了不可恢复的异常,整个ZK进程都会推出. 而ZK的"自愈性"使得服务器在重启之后可以重新加入集群.

所以可以通过监督进程比如说 daemontools 或者 SMF (其他工具都可以) 来管理ZK服务器来保证服务器异常推出的时候会系统重启(以便其重新加入集群)

同时也推荐配置ZK在发生 OOM 的时候 dump 出日志. 可以通过在启动的时候增加配置参数:

-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=‘kill -9 %p’

“-XX:+HeapDumpOnOutOfMemoryError” “-XX:OnOutOfMemoryError=cmd /c taskkill /pid %%%%p /t /f”

监控(Monitoring)

主要通过一下方式监控:

  • 通过4字母命令
  • 使用JMX
  • 使用 zkServer.sh status命令

日志

Zk 使用 SLF4J 版本 1.7.5 作为日志基础设置. 为了兼容性它绑定了 LOG4J , 但是你可以使用 LOGBACK 或者任何其他的日志框架.

ZK默认的log4j.properties 文件在 conf 目录里面. log4j.properties 可以放在classpath 也可以放在 工作目录(ZK运行的目录)

排查异常

服务器因为文件损坏而无法启动: 服务器可能会因为无法连接数据或者因为事务日志文件损坏而无法启动. 你会看到在加载ZK数据库的时候抛出的IOException. 这种情况下, 首先要保证集群中的其他服务器没有问题, 在命令行端口使用 “stat” 命令来查看它们是否正常. 如果其他服务器都正常的话, 你就可以删除 数据目录损坏的文件, 删除所有 datadir/version-2 和 datalogdir/version-2/ 中的文件, 并重启服务器.

配置参数

ZK的行为是受配置文件管理的, 这个文件被设计为在每个服务器相同的目录布局中使用相同的配置. 如果配置不相同, 确保服务器列表应该一直.

注意: 在 3.5.0 或以上的版本, 有些配置参数放在了动态配置文件里面. 如果它们放在了静态配置文件中, ZK会自动将他们移动套动态配置文件.

最小配置

只需要一下的配置:

  • clientPort: 监听客户端请求的端口; 也就是客户端指定要连接的端口
  • secureClientPort : 使用 SSL 连接的客户端端口. 和 clientPort 两种都指定的话则都生效, 不指定的那个则不生效. 当使用插件 zookeeper.serverCnxnFactory, zookeeper.clientCnxnSocket 作为Netty的时候, 会自动开启SSL模式
  • observerMasterPort : 监听观察者连接的端口, 如果设置了该属性,那么服务器将在 follower 模式和 leader 模式下托管观察者连接,并在观察者模式下尝试连接任何投票的对等点。
  • dataDir: ZK保存内存数据的快照的目录, 除非另外指定, 事务日志的更新也会放在这里.

注意:
小心你放置事务日志的位置, 专门的事务日志设备是确保高性能的关键. 把事务日志放在繁忙的设备上会大大的影响性能.

  • tickTime: 每一次计时的间隔, ZK使用的基础时间, 使用 毫秒 (milliseconds) 作为单位. 被用来当做心跳或者超时, 比如说最小会话超时时间就是2个时钟间隔.

高级配置

这些配置都是可选的, 可以用来调优. 有些配置可以通过Java的系统属性配置, 通常是使用 zookeeper.keyword 的形式:

  • dataLogDir: (无Java系统属性).专门指定事务日志的存放位置,使其不适用 dataDir. 允许使用专门的设备来保存事务日志, 防止和 日志 以及 快照竞争.

高度推荐指定 dataLogDir 以使用单独的设备来提高性能

  • globalOutstandingLimit : (Java系统属性: zookeeper.globalOutstandingLimit).客户端发送过来的请求排队的最大数量. 防止太多的客户端请求撑爆服务器的内存.默认1,000

  • preAllocSize : (Java属性: zookeeper.preAllocSize) 事务日志预分配的空间大小. 预分配空间可以防止日志在写入的时候去磁盘查找空闲的块. 单位是 kb, 默认 64M. 修改这个配置的一个理由是, 当快照产生的很快的时候, 用来减少块的大小(见 snapCount 和 snapSizeLimitInKb)

  • snapCount : (Java属性: zookeeper.snapCount) ZK 使用事务日志和快照来记录事务(考虑 提前写日志 write-ahead log). snapCount 决定了多少个事务日志之后会开始产生快照. 为了防止所有的成员同时生成快照, 每个 ZK服务器会产生一个随机数处于 [snapCount/2+1, snapCount] 之间, 在达到这个随机数之后就会产生快照. 默认的 snapCount 是 100,000.

  • commitLogCount : (zookeeper.commitLogCount) ZK会在内存中维护一部分已提交的请求列表以供服务器间同步最近的请求的使用. 在快照很大的时候(> 100,000), 能提高同步的性能. 默认 500

  • snapSizeLimitInKb : (zookeeper.snapSizeLimitInKb) 和 snapCount , 但是这个使用的是文件大小来进行限制. 在拍摄快照(以及滚转事务日志)之前,事务日志中记录的事务集允许的总字节大小由snapSize确定. 为了防止多个成员同时拍摄快照, 每个成员实际使用的大小为 [snapSize/2+1, snapSize] 间的一个随机值. 默认是 4,194,304 (4GB), 负数表示不开启这个功能.

  • txnLogSizeLimitInKb : (zookeeper.txnLogSizeLimitInKb) 控制单个事务日志文件的大小, 默认关闭. 事务日志文件太大会影响同步性能, 因为leader需要扫描日志文件来找到合适的位置进行同步. 日志文件大小达到这个限制之后就会产生新的事务日志文件

  • maxCnxns : (zookeeper.maxCnxns) 限制每个zk服务器并发的连接数目(每个服务器的客户端端口). 用来放置特定类型的 DOS 工具. 默认是 0, 表示没有限制. 因为 serverCnxnFactory 和 secureServerCnxnFactory 是分开算的, 所以最多的连接数是 2 *maxCnxns

  • maxClientCnxns: 在 socket 层面限制一个客户端(根据ip)允许连接zk集群中某个服务器的最大连接数. 默认60. 设置成0 表示没有限制

  • clientPortAddress : New in 3.3.0: 监听客户端请求的地址(ipv4, ipv6, 或者hostname), 可选的, 默认监听使用 clientPort 的所有连接.

  • minSessionTimeout : New in 3.3.0: 默认2倍 tikeTime,毫秒

  • maxSessionTimeout : New in 3.3.0: 默认20倍 tikeTime ,毫秒

  • fsync.warningthresholdms (Java system property: zookeeper.fsync.warningthresholdms) New in 3.3.4: 日志执行 fsync 的时候超过了这个毫秒数就会打印警告信息, 默认 1000

  • maxResponseCacheSize : (Java system property: zookeeper.maxResponseCacheSize) 缓存序列化信息的最近读取记录的数目, 默认是 400, 负数或者 0 表示不启用, 可以使用 response_packet_cache_hits 和 response_packet_cache_misses 指标来调整这个值

  • maxGetChildrenResponseCacheSize (Java system property: zookeeper.maxGetChildrenResponseCacheSize) New in 3.6.0: 和 maxResponseCacheSize 类型, 但是是作用于 获取子节点的请求

  • autopurge.snapRetainCount: (No Java system property) New in 3.4.0: 默认3, 最小值, 保存最近的 快照 和 其关联的事务日志的数目.

  • autopurge.purgeInterval : (No Java system property) New in 3.4.0: 触发自动清除日志的间隔, 单位小时,默认是0

  • syncEnabled : (Java system property: zookeeper.observer.syncEnabled) New in 3.4.6, 3.5.0: 让观察者和其他参与者一样把事务日志写到磁盘, 减少观察者重启恢复的时间. 默认是true , 设置为 false 关闭.

  • fastleader.minNotificationInterval : (Java system property: zookeeper.fastleader.minNotificationInterval) 连续两次通知检查领导人选举时间的下限。领导者选举的两次连续通知检查之间的时间长度下限。 此间隔确定对等方等待检查选举投票集的时间,并影响选举可以解决的速度。 对于长选举,该间隔遵循从配置的最小值(this)和配置的最大值(fastleader.maxNotificationInterval)开始的退避策略。

  • fastleader.maxNotificationInterval : (Java system property: zookeeper.fastleader.maxNotificationInterval) 和上面的类似, 上限

以下是服务降级的配置
  • connectionTokenFillTime : (Java system property: zookeeper.connection_throttle_fill_time) New in 3.6.0:这是用于调优服务器端连接调节器的参数之一,该调节器是一种基于令牌的速率限制机制,具有可选的概率的服务降级。 用来限流的token统计周期.

  • connectionTokenFillCount : (Java system property: zookeeper.connection_throttle_fill_count) New in 3.6.0: 每个统计周期 每个 token 添加到 bucket 的计数

  • connectionFreezeTime : (Java system property: zookeeper.connection_throttle_freeze_time) New in 3.6.0: 定义每过多长的毫秒数就调整降级概率. -1 表示不开启, 默认 -1.

  • connectionDropIncrease : (Java system property: zookeeper.connection_throttle_drop_increase) New in 3.6.0: connectionFreezeTime 周期内, 如果bucket为空, 就降级概率会增加 connectionDropIncrease , 默认是 0.02

  • connectionDropDecrease : (Java system property: zookeeper.connection_throttle_drop_decrease) New in 3.6.0:每次 connectionFreezeTime 检查周期, 如果 bucket 中的数量超过了阈值, 则服务降级的可能性减少 connectionDropDecrease . 阈值 = connectionMaxTokens * connectionDecreaseRatio, 默认是0.002

  • connectionDecreaseRatio : (Java system property: zookeeper.connection_throttle_decrease_ratio) New in 3.6.0: 见 connectionDropDecrease, 默认是 0

… 后面配置太多了, 有需要再去找吧

关闭数据目录自动创建

New in 3.5: 如果启动的时候还不存在数据目录(配置文件中指定的), 默认会自动创建. 这个行为有时候会非常危险, 想象这样一个例子, 如果你不小心修改了 服务器的 dataDir 的配置, 服务器就会自动在一个新的位置创建新的数据目录, 这样的话就会用一个空的命名空间进行服务器, 这种场景称为 “脑裂” (比如 同时存储了旧的数据 和 新的数据). 如果能够关闭这种创建行为就能避免这种情况了. 通常生产应该关闭自动创建, 但是因为默认的遗留行为目前还无法改变所以要具体情况具体分析.

运行 zkSever.sh 的时候 设置 环境变量 ZOO_DATADIR_AUTOCREATE_DISABLE 为 1 就可以关闭了. 如果是通过类直接运行的话, 使用 zookeeper.datadir.autocreate=false , 比如 -Dzookeeper.datadir.autocreate=false

如果关闭了自动创建, 并且发现目录不存在的话, 就会报错并且启动失败.

关闭了自动创建之后, 用户就要先安装 Zk, 然后创建一个目录文件(和潜在的 txnlog 目录), 然后再启动服务器. zkServer-initialize.sh 脚本会自动创建需要的目录, 并且可选地创建 myid 文件(通过命令行参数). 这个脚本也可以在有自动创建的时候使用. 但是注意,它只会帮你创建目录, 但是不会帮你创建配置文件.

开启 db 存在检查

New in 3.6.0: 默认情况下, 如果 zk 服务器启动的时候 找不到 数据树, 它会把 zxid 设置为0 并且 作为投票成员加入到集群中. 这种情况有时候会很危险, 假如数据目录是在其宕机的时候删除掉的, 那么就可能会丢失新选举的 leader中不存在的事务. 当开启了 db 存在性检查, 它在检测到没有数据树的时候, 服务器会作为非投票者加入集群之后它能够 和 leader 同步并获取到 最新的版本的集群数据. 为了表示自己确实是想要空的目录树, 可以在 myid 所在的目录创建一个 initialize 文件. 这个文件会在server启动的时候检测到然后自动帮你删除.

使用 -Dzookeeper.db.autocreate=false 来开启存在性检查, 如果使用的是 zkServer-initialize.sh , 它会自动帮你创建 initialization 文件.

性能优化选项

… 略

调试可见性配置

… 略

AdminServer 配置

… 略

指标提供者

New in 3.6.0: 下面的选项用来配置指标

默认情况下, zk服务器会通过 AdminServer 和 4字母命令 暴露一些有用的指标

3.6.0 以后你可以配置一个不同的指标提供者, 以提供不同系统的指标支持

3.6.0 之后 Zk 二进制包整合了 Prometheus.io

  • metricsProvider.className : 设置到 "org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider"来开启 Prometheus.io 导出器.

  • metricsProvider.httpPort : Prometheus.io 导出器会开启一个 Jetty 服务器并绑定到这个端口, 默认是 7000. Prometheus 访问地址是 http://hostname:httPort/metrics.

  • metricsProvider.exportJvmInfo : 如果设置为 true Prometheus.io 会暴露关于 JVM 的有用指标.默认为 true.

使用 netty 框架通信

3.5 版本之后 , ZK服务器能够使用 Netty 代替默认的 NIO选项. 通过设置环境变量 zookeeper.serverCnxnFactory 为 org.apache.zookeeper.server.NettyServerCnxnFactory, 对于客户端, 设置 zookeeper.clientCnxnSocket 为org.apache.zookeeper.ClientCnxnSocketNetty.

Qurom TLS

New in 3.5.5

基于 Netty 框架的通信可以设置使用TLS加密通信

注意 Quorum TLS 封装了 leader选举 和 成员通信协议 的加密

  1. 创建SSL keystore JKS 来存储凭据

每个ZK实例都应该创建1个keystore

在这个例子中我们生了一个自签名的证书并且将其私钥一起保存在了keystore.jks里面. 这种适合测试,但是生产上你可以要使用正式的证书.

注意 alias (-alias) 和 distinguished name (-dname) 必须匹配机器使用的hostname,否则hostname验证会无法工作.

keytool -genkeypair -alias ( h o s t n a m e − f ) − k e y a l g R S A − k e y s i z e 2048 − d n a m e " c n = (hostname -f) -keyalg RSA -keysize 2048 -dname "cn= (hostnamef)keyalgRSAkeysize2048dname"cn=(hostname -f)" -keypass password -keystore keystore.jks -storepass password

  1. 从keystore中提取公钥(证书), 这一步可能只有自签名的证书需要.

    keytool -exportcert -alias $(hostname -f) -keystore keystore.jks -file $(hostname -f).cer -rfc

  2. 创建包含了所有ZK实例证书的 SSL truststore

    整个集群中的成员都要使用相同的 truststore, 其中包含了所有集群成员的证书. 这些证书在truststore 中的别名是不同的. 但是命名成什么无所谓.

    keytool -importcert -alias [host1…3] -file [host1…3].cer -keystore truststore.jks -storepass password

  3. 需要使用 NettyServerCnxnFactory 作为 serverCnxnFactory, 因为 NIO 不支持 SSL. 添加以下配置到 zoo.cfg 配置文件:

    sslQuorum=true serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory ssl.quorum.keyStore.location=/path/to/keystore.jks ssl.quorum.keyStore.password=password ssl.quorum.trustStore.location=/path/to/truststore.jks ssl.quorum.trustStore.password=password

  4. 验证集群运行日志中有打印TLS的信息:

    INFO [main:QuorumPeer@1789] - Using TLS encrypted quorum communication INFO [main:QuorumPeer@1797] - Port unification disabled … INFO [QuorumPeerListener:QuorumCnxManager$Listener@877] - Creating TLS-only quorum server socket

在线升级非TLS集群

New in 3.5.5

以下利用 端口一致化(port unification)功能来实现在线 TLS 切换:

  1. 为集群中所有的服务器创建必要的 keystore 和 truststore (按照上节所说)

  2. 添加以下配置并且重启第一个节点

    sslQuorum=false portUnification=true serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory ssl.quorum.keyStore.location=/path/to/keystore.jks ssl.quorum.keyStore.password=password ssl.quorum.trustStore.location=/path/to/truststore.jks ssl.quorum.trustStore.password=password

    注意, 这个时候还没有开启TLS, 但是我们开启 端口一致化

  3. 重复上面的第2步修改其他服务器的配置, 验证你可以看到以下的日志

    INFO [main:QuorumPeer@1791] - Using insecure (non-TLS) quorum communication INFO [main:QuorumPeer@1797] - Port unification enabled … INFO [QuorumPeerListener:QuorumCnxManager$Listener@874] - Creating TLS-enabled quorum server socket

​ 启动完之后要检查一下运行状态是否正常

  1. 每个节点上开启端口一致并且依次重启

    sslQuorum=true

    portUnification=true

  2. 一旦完成之后并确认集群运行状态正常, 就可以关闭端口一致并再次依次重启

    sslQuorum=true

    portUnification=false

ZooKeeper 命令

四字母命令

所有命令都是4个字母组成的, 可以通过 telnet 或者 nc 或者zk客户端端口 触发命令

3个最常用的命令: stat 显示服务器的通用信息和 已连接的客户端. srvrcons 显示关于服务器和连接更详细的信息.

New in 3.5.3: 四字命令需要在使用前配置好允许哪些命令的使用. 使用 4lw.commands.whitelist 这个配置. 后面四字命令会过期, 建议使用 AdminServer

既然以后要过期… 那就略过了.

重点说一下: trace mask

stmk : 设置当前的 trace mask. track mask 是 64位的, 每一位表示开启或者关闭特定目录的服务器上的 trace 日志. Log4J 必须设置为 trace 级别 才能看到 trace 日志信息. 以下是每个位的目录含义:

Trace Mask Bit Values
0b0000000000未使用,保留给未来使用
0b0000000010打印客户端请求, 排除ping请求
0b0000000100未使用,保留给未来使用
0b0000001000打印ping请求
0b0000010000打印当前leader发过来的请求包, 排除ping请求
0b0000100000打印客户端会话的添加, 移除和校验日志
0b0001000000打印传递到客户端的会话的监控事件.
0b0010000000打印当前leader发过来的ping请求
0b0100000000未使用,保留给未来使用
0b1000000000未使用,保留给未来使用

所有剩下的位都是未使用的,保留给未来使用. 多个 mask 使用 位或 合并运算. 默认mask 是 0b0100110010. 因此 默认trace 日志包含了 客户端请求, leader 的包和 会话的信息. 要设置mask的话, 使用 stmk 命令之后, 紧跟着 对应的mask, 以下是 perl 的例子:

$ perl -e “print ‘stmk’, pack(‘q>’, 0b0011111010)” | nc localhost 2181 250

The AdminServer

New in 3.5.0: AdminServer 是一个嵌入式的 jetty 服务器, 为4字命令提供了http接口. 默认情况下, 使用的是 8080端口, 并且名通过 URL 的 “/commnads/[command name]” 触发. 比如 http://localhost:8080/commands/stat, 命令的响应是 json 值. 不同的是, 命令没有被限制为 4个字母, 名可以用多个名称, 比如: stmk 可以用来指代 set_trace_mask. 通过 http://localhost:8080/commands 可以看到所有可用的命令. 见 AdminServer 配置选项 查看如何变更端口和 urls

AdminServer 默认开启, 但是可以被关闭:

  • 设置系统属性 zookeeper.admin.enableServer 为 false
  • 从 classpath 移除 Jetty (如果你想要重写 ZK 的 jetty 依赖, 推荐这种)

注意 TCP 的四字命令在 AdminServer关闭的时候依然有用.

可用的命令如下:

  • connection_stat_reset/crst: 重置所有客户端连接数据.不返回新的字段
  • configuration/conf/config : 打印服务端配置的基本信息. 比如客户端端口, 数据目录的绝对路径
  • connections/cons : 客户端到服务端的连接信息. 注意, 取决于连接数, 这个操作可能会影响服务端的性能. 返回 “connections”, 连接信息对象的列表
  • hash: 历史的 digest 列表中的 Txn digests. 每128个事务会记录一次. 返回 “digests” , 事务digest 对象的列表
  • dirs : logfile目录和快照目录大小的字节数. 返回 “datadir_size” 和 “logdir_size”
  • dump : 会话过期和临时节点的信息. 取决于连接数可能会影响服务器性能. 返回 “expiry_time_to_session_ids” 和 “session_id_to_ephemeral_paths” 的map
  • environment/env/envi : 返回所有环境变量
  • get_trace_mask/gtmk : 当前的 trace mask, set_trace_mask 的只读版本. 参考 四字命令中 stmk 的描述.返回 “tracemask”.
  • initial_configuration/icfg : 打印用来启动节点的配置信息, 返回"initial_configuration"
  • is_read_only/isro : true/false 服务器是否处于只读模式. 返回"read_only".
  • last_snapshot/lsnp : 最近一次完成保存到磁盘的快照的信息. 如果在服务器启动和完成写入快照期间调用, 则返回启动服务器时候读取的快照.返回"zxid" 和"timestamp", 后者单位是秒.
  • leader/lead : 如果集群配置了成员模式则返回当前的leader状态和地址, 返回 “is_leader”, “leader_id”, 和"leader_ip"
  • monitor/mntr : 返回监控信息. 包括性能统计新, 内部队列, 数据树的总结信息等等, 返回各自的字段
  • observer_connection_stat_reset/orst : 重置所有的观察者连接数据. observers的伴生命令, 不返回新的字段.
  • ruok : 不执行任何操作的命令, 用来检查服务器是否在运行中. 有响应不代表加入了集群, 只是代表 admin sever 启动了并绑定到了特定的端口, 不返回新的字段
  • set_trace_mask/stmk : 设置 trace mask,(因此它需要一个参数), get_trace_mask 的写版本. 详见四字命令中的 stmk . 返回 “tracemask”.
  • server_stats/srvr : 返回服务器信息
  • stats/stat : 在 server_stats 的基础上多了 connections 信息. 取决于连接数可能会影响服务器性能
  • stat_reset/srst : 重置服务器统计数据.server_statsstats返回的信息的子集
  • observers/obsr : Information on observer connections to server. Always available on a Leader, available on a Follower if its acting as a learner master. 返回 “synced_observers” (int) and “observers” (list of per-observer properties).
  • system_properties/sysp : 所有已定义的系统属性
  • voting_view : 提供当前集群中的投票成员. 返回 “current_config” 的 map
  • watches/wchc : 通过会话聚合的监控信息. 取决于连接数可能会影响服务器性能. 返回 "session_id_to_watched_paths " 的 map
  • watches_by_path/wchp : 通过路径聚合的监控信息.取决于连接数可能会影响服务器性能. 返回 “path_to_session_ids” 的 map
  • watch_summary/wchs : 汇总的监控信息, 返回: “num_total_watches”, “num_paths”, 和 “num_connections”
  • zabstate : Zab 协议当前节点的运行阶段 和 它是否是投票成员, 可能阶段: ELECTION, DISCOVERY, SYNCHRONIZATION, BROADCAST.返回 “voting” 和"zabstate" 字段

数据文件管理

ZK保存数据于数据目录, 保存事务日志在事务日志目录. 默认两个是一样的, 可以为事务日志单独配置一个目录. 使用专门的设备来保存事务日志能提高性能.

数据目录

可能会包含以下2或者3个文件:

  • myid - 包含单独的ASCII 可读的整数表示服务器的 id
  • initialize - 出现的时候表示想要空的数据树. 会清除已创建的数据树
  • snapshot - 持有数据库的模糊快照

每个ZK服务器都有一个单独的id, 这个id用于两个地方: myid文件 和 配置文件. myid文件标志了给定了数据目录的服务器. 配置文件列举了其他服务器的连接地址并通过 服务器id标志. 当一个zk 服务器实例启动, 它会从myid文件读取它的id, 使用那个 id, 来从配置文件中查看自己应该监听那个端口.

保存在 数据目录的 快照文件是 模糊快照, 表示zk服务器正在拍摄快照, 数据树正在发生变化. 快照的最后是 zxid, zk事务id, 即在拍摄快照开始时最后提交的事务的ZooKeeper事务id。因此,快照包括在快照进行时发生的数据树更新的子集。快照可能不会关联任何实际存在的数据树, 由此我们称之为模糊快照. 不过,ZooKeeper仍然可以使用这个快照进行恢复,因为它利用了更新的幂等特性。通过对模糊快照重放事务日志,ZooKeeper在日志末尾获得系统的状态。

日志目录

日志目录包含了ZK的事务日志. 在更新执行之前, ZK保证表示该事务的更新操作会写入到固定存储器.当事务的数量达到阈值的时候, 会创建一个新的事务日志文件. 该阈值使用 snapCount 和 snapSizeLimitInKb 参数计算出来的. 日志文件的后缀是写入到日志中的第一个事务的zxid.

文件管理

不同配置 和 独立zk 和 集群zk服务器的 快照 和 事务日志文件格式并无不同. 可以直接复制到开发环境的独立的zk服务器来排查问题.

使用旧的日志和快照文件, 可以查看ZK服务器的上个状态甚至恢复成那个状态. LogFormatter 类允许管理员查看日志中的事务.

ZK服务器创建快照和日志文件, 但是不会删除它们. 文件保留策略由ZK外部实现. 服务器本身只需要最新的完整的模糊快照, 所有的跟随它的日志文件, 还有它之前的最后的日志文件. 后者是因为拍摄快照的时候, 也会同时进行更新, 所以该日志文件也是必须的. 这是可能的因为 拍摄快照 和 日志滚动 某种程度上是独立于Zk的. 查看 维护 一节来设置文件保留策略.

注意: 这些文件中的数据都是没有加密的. 可采取措施防止未授权的访问, 比如说访问控制. 这些措施也是zk外部进行的, 独立于zk本身的配置文件.

恢复

查看 ZK工具集合

要避免的事情

  • 不一致的服务器列表: 客户端使用的ZooKeeper服务器列表必须与每个ZooKeeper服务器拥有的ZooKeeper服务器列表匹配. 如果客户端的服务器列表是实际服务器列表的子集还好, 但是如果不同的话, 会出现奇怪的问题. 另外, 服务器之间的服务器列表也要保持一致.
  • 错误的事务日志位置: 事务日志是ZK性能的关键. ZK响应前需要把事务同步到磁盘. 建议使用专门的设备放置事务日志.如果没有的话, 提高 snapCount 减少快照生成的数量. 尽管无法消灭问题, 但是会提供更多的资源给事务日志.
  • 错误的java堆大小: 设置好java堆大小, 防止内存页交换到磁盘上. 磁盘是 ZK 的命门. 所有东西都是排序的, 如果处理某个请求的时候交换到了磁盘上, 那么后续的请求可能也会一起放到磁盘上. 千万要避免内存交换. 要保守估计堆大小: 如果有 4G 内存, 不要设置堆内存为 6G 设置是 4G. 对于4G机器, 建议是3G, 因为操作系统 和 缓存本身需要占用内存. 最好还是进行负载测试, 并且保存内存够用而不会导致内存交换.
  • 暴露在公共环境的部署: zk集群应该部署在可信任的环境, 比如 防火墙之后.

最佳实践

略… 原文没啥营养

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/804591
推荐阅读
相关标签
  

闽ICP备14008679号