ZooKeeper 集群配置

虽然 Solr 与 Apache ZooKeeper 捆绑在一起,但强烈建议你在生产中使用外部 ZooKeeper 设置。

虽然使用 Solr 的嵌入式 ZooKeeper 实例对于入门来说很好,但你不应该在生产中使用它,因为它不提供任何故障转移:如果托管 ZooKeeper 的 Solr 实例关闭,ZooKeeper 也会关闭。任何依赖它的分片或 Solr 实例都无法与其或彼此通信。

解决此问题的办法是设置一个外部 ZooKeeper 集群,它是由运行 ZooKeeper 的多台服务器组成,这些服务器相互通信以协调集群的活动。

ZooKeeper 节点有多少?

要回答的第一个问题是你将在集群中运行的 ZooKeeper 节点数。

在规划要配置的 ZooKeeper 节点数时,请记住 ZooKeeper 集群的主要原则是维护大多数服务器以服务请求。此大多数称为法定人数

“ZooKeeper 服务要处于活动状态,必须有大多数可以相互通信的非故障机器。要创建可以容忍 F 台机器故障的部署,你应该指望部署 2xF+1 台机器

— ZooKeeper 管理员指南

https://zookeeper.net.cn/doc/r3.9.1/zookeeperAdmin.html

为了正确维护法定人数,强烈建议在集群中使用奇数个 ZooKeeper 服务器,以便维护大多数。

解释一下原因,考虑以下场景:如果你有两个 ZooKeeper 节点,其中一个宕机,这意味着只有 50% 的可用服务器可用。由于这不是大多数,因此 ZooKeeper 将不再提供服务请求。

但是,如果你有三个 ZooKeeper 节点,其中一个宕机,你有 66% 的服务器可用,并且 ZooKeeper 将继续正常运行,同时你修复宕机的那个节点。如果你有 5 个节点,你可以在必要时继续使用两个宕机节点运行。

通常不建议超过 5 个节点。虽然看起来更多节点可提供更高的容错性和可用性,但实际上由于发生大量节点间协调,效率会降低。除非您有真正庞大的 Solr 集群(规模为 1000 个节点),否则请尝试遵循 3 个的一般规则,或者如果您有较大的集群,则可以尝试 5 个。

可以在 https://zookeeper.net.cn/doc/r3.9.1/zookeeperAdmin.html#sc_zkMulitServerSetup 上的 ZooKeeper 文档中找到有关 ZooKeeper 集群的更多信息。

下载 Apache ZooKeeper

设置 Apache ZooKeeper 的第一步当然是下载该软件。它可从 https://zookeeper.net.cn/releases.html 获得。

Solr 当前使用 Apache ZooKeeper v3.9.1。

在使用外部 ZooKeeper 集群时,您需要将本地安装保持为与 Solr 分发的最新版本同步。由于在这种情况下它是一个独立应用程序,因此它不会作为标准 Solr 升级的一部分进行升级。

ZooKeeper 安装

安装包括将文件解压到您希望 ZooKeeper 存储其内部数据的特定目标目录中。实际目录本身并不重要,只要您知道它在哪里即可。

解压 ZooKeeper 包的命令是

tar xvf zookeeper-3.9.1.tar.gz

此位置是此服务器上 ZooKeeper 的 <ZOOKEEPER_HOME>

必须在将运行 ZooKeeper 的每台服务器上重复安装和解压 ZooKeeper。

ZooKeeper 集群的配置

安装后,我们将首先了解 ZooKeeper 的基本配置,然后了解将每个节点配置为集群一部分的特定参数。

初始配置

要配置 ZooKeeper 实例,请创建一个名为 <ZOOKEEPER_HOME>/conf/zoo.cfg 的文件。ZooKeeper 安装中包含一个示例配置文件,即 conf/zoo_sample.cfg。如果您愿意,可以编辑并重命名该文件,而不是新建一个文件。

该文件应包含以下信息以启动

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
4lw.commands.whitelist=mntr,conf,ruok

参数如下

tickTime

必需

默认值:无

ZooKeeper 所做工作的一部分是确定哪些服务器在任何给定时间正在运行,并且最小会话超时定义为两个“滴答”。tickTime 参数以毫秒为单位指定每个滴答应持续多长时间。

dataDir

必需

默认值:无

这是 ZooKeeper 将存储有关集群的数据的目录。在首次启动 ZooKeeper 之前,此目录必须为空。

clientPort

必需

默认值:无

Solr 将通过此端口访问 ZooKeeper。

4lw.commands.whitelist

可选

默认值:无

此设置允许 Solr 管理 UI 查询 ZooKeeper。也可以选择使用 * 启用所有“4 个字母的单词”,列出的三个(mntrconfruok)将启用管理 UI。

这些是每个 ZooKeeper 节点上需要使用的基本参数,因此必须将此文件复制到或创建在此节点上。

接下来,我们将自定义此配置以在集合中使用。

集合配置

要完成集合的配置,我们需要设置其他参数,以便每个节点知道它在集合中的位置以及其他每个节点的位置。

以下每个示例都假设您在具有不同主机名的不同服务器上安装 ZooKeeper。

完成后,您的 zoo.cfg 文件可能如下所示

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
4lw.commands.whitelist=mntr,conf,ruok

initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

autopurge.snapRetainCount=3
autopurge.purgeInterval=1

我们已将这些参数添加到我们已有的三个参数中

initLimit

必需

默认值:无

以刻度为单位的时间量,允许跟随者连接并与领导者同步。在此情况下,您有 5 个刻度,每个刻度为 2000 毫秒,因此服务器将等待长达 10 秒以连接并与领导者同步。

syncLimit

必需

默认值:无

以刻度为单位的时间量,允许跟随者与 ZooKeeper 同步。如果跟随者落后于领导者太多,它们将被丢弃。

server.X

必需

默认值:无

这些是集合中所有服务器的服务器 ID(X 部分)、主机名(或 IP 地址)和端口。ID 区分集合的每个节点,并允许每个节点知道其他每个节点的位置。端口可以是您选择的任何端口;ZooKeeper 的默认端口是 2888:3888

由于我们已将服务器 ID 分配给特定主机/端口,因此我们还必须定义此节点是列表中的哪个服务器。我们使用存储在数据目录(由 dataDir 参数定义)中的 myid 文件来执行此操作。myid 文件的内容仅为服务器 ID。

在上述配置示例的情况下,您将使用内容“1”(不带引号)创建文件 /var/lib/zookeeper/1/myid,如下例所示

1
autopurge.snapRetainCount

可选

默认值:3

清除旧快照和事务日志时要保留的快照和相应事务日志的数量。

ZooKeeper 会自动保留一个事务日志,并在进行更改时向其中写入。当前状态的快照会定期获取,并且此快照会取代早于该快照的事务日志。但是,ZooKeeper 永远不会清理旧快照或旧事务日志;随着时间的推移,它们会悄无声息地填满每台服务器上的可用磁盘空间。

为避免这种情况,请设置 autopurge.snapRetainCountautopurge.purgeInterval 参数,以启用定期进行自动清理(清除)。autopurge.snapRetainCount 参数会在进行清理时保留已定义数量的快照和事务日志。此参数可以配置为高于 3,但不能低于 3。

autopurge.purgeInterval

可选

默认值:0

清除任务之间的间隔时间(小时)。此参数的默认值为 0,因此必须将其设置为 1 或更高才能启用快照和事务日志的自动清理。如果愿意,可以将其设置为 24,即每天一次。

我们将在每个节点上重复此配置。

在第二个节点上,更新 <ZOOKEEPER_HOME>/conf/zoo.cfg 文件,使其与节点 1 上的内容匹配(尤其是服务器主机和端口)

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
4lw.commands.whitelist=mntr,conf,ruok

initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

autopurge.snapRetainCount=3
autopurge.purgeInterval=1

在第二个节点上,创建一个内容为“2”的 myid 文件,并将其放入 /var/lib/zookeeper 目录中。

2

在第三个节点上,更新 <ZOOKEEPER_HOME>/conf/zoo.cfg 文件,使其与节点 1 和 2 上的内容匹配(尤其是服务器主机和端口)

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
4lw.commands.whitelist=mntr,conf,ruok

initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

autopurge.snapRetainCount=3
autopurge.purgeInterval=1

并在 /var/lib/zookeeper 目录中创建 myid 文件

3

如果要创建 5 节点集群(一种罕见的情况),请对服务器 4 和 5 重复此操作。

ZooKeeper 环境配置

为了在以后集群出现问题时便于进行故障排除,建议在启用日志记录和适当的 JVM 垃圾回收 (GC) 设置的情况下运行 ZooKeeper。

  1. 创建一个名为 zookeeper-env.sh 的文件,并将其放入 <ZOOKEEPER_HOME>/conf 目录中(与放置 zoo.cfg 的位置相同)。此文件需要存在于集群的每台服务器上。

  2. 将以下设置添加到文件中

    ZOO_LOG_DIR="/path/for/log/files"
    ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
    
    SERVER_JVMFLAGS="-Xms2048m -Xmx2048m -verbose:gc -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -Xloggc:$ZOO_LOG_DIR/zookeeper_gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=9 -XX:GCLogFileSize=20M"

    属性 ZOO_LOG_DIR 定义 ZooKeeper 将打印其日志的服务器上的位置。ZOO_LOG4J_PROP 设置日志级别和日志记录器。

    使用 SERVER_JVMFLAGS,我们为垃圾回收和记录 GC 相关事件定义了几个参数。其中一个系统参数是 -Xloggc:$ZOO_LOG_DIR/zookeeper_gc.log,它会将垃圾回收日志放入我们为 ZooKeeper 日志定义的同一目录中,并将其放入名为 zookeeper_gc.log 的文件中。

  3. 查看 <ZOOKEEPER_HOME>/conf/log4j.properties 中的默认设置,尤其是 log4j.appender.ROLLINGFILE.MaxFileSize 参数。这会设置日志文件将被滚动覆盖的大小,默认值为 10MB。

  4. zookeeper-env.sh 和对 log4j.properties 所做的任何更改复制到集群中的每台服务器上。

上述说明仅适用于 Linux 服务器。默认的 zkServer.sh 脚本包括对 zookeeper-env.sh 文件的支持,但脚本的 Windows 版本 zkServer.cmd 不支持。要在 Windows 服务器上进行相同的配置,需要直接在 zkServer.cmd 中进行更改。

此时,您已准备好启动 ZooKeeper 集群。

有关 ZooKeeper 的更多信息

ZooKeeper 通过其他配置提供了强大的功能,但深入研究这些配置超出了 Solr 文档的范围。有关更多信息,请参阅 ZooKeeper 文档

启动和停止 ZooKeeper

启动 ZooKeeper

要启动集群,请使用 <ZOOKEEPER_HOME>/bin/zkServer.shzkServer.cmd 脚本,如下所示

Linux 操作系统
zkServer.sh start
Windows 操作系统
zkServer.cmd start

需要在将运行 ZooKeeper 的每台服务器上运行此命令。

您应该在定义的存储目录中看到 ZooKeeper 日志。但是,在启动后,您可能还看不到 zookeeper_gc.log,因为它可能要等到第一次进行垃圾回收后才会出现。

关闭 ZooKeeper

要关闭 ZooKeeper,请在每台服务器上使用相同的 zkServer.shzkServer.cmd 脚本,并使用“stop”命令

Linux 操作系统
zkServer.sh stop
Windows 操作系统
zkServer.cmd stop

Solr 配置

启动 Solr 时,您必须提供 ZooKeeper 的地址,否则 Solr 将不知道如何使用它。这可以通过两种方式完成:在 Solr 集群的每个节点上每次启动时定义连接字符串(ZooKeeper 正在运行的服务器列表),或编辑 Solr 的包含文件作为永久系统参数。下面介绍了这两种方法。

在 Solr 中引用 ZooKeeper 的位置时,最好使用集群中所有服务器的地址。如果其中一台服务器宕机,Solr 将能够自动将其请求发送到列表中的另一台服务器。

ZooKeeper 版本 3.5 及更高版本支持服务器地址和角色的动态重新配置。但请注意,Solr 只能与静态 ZooKeeper 连接字符串中列出的服务器通信。

使用 chroot

如果您的集群除了 Solr 之外还与其他系统共享或将要共享,您应该考虑定义特定于应用程序的znodes,或仅包含 Solr 文件的层次命名空间。

为每个应用程序创建 znode 后,在告诉 Solr 访问 ZooKeeper 的位置时,将它的名称(也称为chroot)添加到连接字符串的末尾。

使用 bin/solr 命令创建 chroot

bin/solr zk mkroot /solr -z zk1:2181,zk2:2181,zk3:2181

请参阅部分 创建 znode 了解此命令的更多示例。

创建 znode 后,它的行为类似于文件系统上的目录:Solr 存储在 ZooKeeper 中的数据嵌套在主数据目录下,不会与使用同一 ZooKeeper 集群的其他系统或进程的数据混合。

或者,Solr 可以作为第一个 Solr 实例启动的一部分自动创建 znode,请阅读以下内容了解示例。

将 -z 参数与 bin/solr 配合使用

让 Solr 指向您创建的 ZooKeeper 集群只需在使用 bin/solr 脚本时使用 -z 参数。

例如,要让 Solr 实例指向您在端口 2181 上启动的 ZooKeeper,该 ZooKeeper 在三台服务器上带有 chroot /solr(请参阅上面的 使用 chroot),您需要执行以下操作

bin/solr start -e cloud -z zk1:2181,zk2:2181,zk3:2181/solr

如果 znode 不存在,您可以将 ZK_CREATE_CHROOT 环境变量设置为 true,以便在启动时自动创建它

ZK_CREATE_CHROOT=true bin/solr start -e cloud -z zk1:2181,zk2:2181,zk3:2181/solr

更新 Solr Include 文件

如果您更新 Solr Include 文件(solr.in.shsolr.in.cmd),它将覆盖与 bin/solr 一起使用的默认值,您将不必对 bin/solr 命令使用 -z 参数。

Linux:solr.in.sh

要查找的部分将被注释掉

# Set the ZooKeeper connection string if using an external ZooKeeper ensemble
# e.g. host1:2181,host2:2181/chroot
# Leave empty if not using SolrCloud
#ZK_HOST=""

移除行首的注释标记并输入 ZooKeeper 连接字符串

# Set the ZooKeeper connection string if using an external ZooKeeper ensemble
# e.g. host1:2181,host2:2181/chroot
# Leave empty if not using SolrCloud
ZK_HOST="zk1:2181,zk2:2181,zk3:2181/solr"

Windows:solr.in.cmd

要查找的部分将被注释掉

REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble
REM e.g. host1:2181,host2:2181/chroot
REM Leave empty if not using SolrCloud
REM set ZK_HOST=

移除行首的注释标记并输入 ZooKeeper 连接字符串

REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble
REM e.g. host1:2181,host2:2181/chroot
REM Leave empty if not using SolrCloud
set ZK_HOST=zk1:2181,zk2:2181,zk3:2181/solr

现在,您不必在启动 Solr 时输入连接字符串。

增加文件大小限制

ZooKeeper 旨在容纳小文件,按千字节计算。默认情况下,ZooKeeper 的文件大小限制为 1MB。尝试写入或读取大于此大小的文件会导致错误。

某些 Solr 功能(例如,文本分析同义词、LTR 和 OpenNLP 命名实体识别)需要配置资源,这些资源可能大于默认限制。可以通过 Java 系统属性 jute.maxbuffer 来配置 ZooKeeper,以增加此限制。请注意,此配置既需要用于 ZooKeeper 服务器,也需要用于连接到服务器的所有客户端,并且必须在指定它的所有位置都相同。

在 ZooKeeper 节点上配置 jute.maxbuffer

必须在每个外部 ZooKeeper 节点上配置 jute.maxbuffer。这可以通过以下任何一种方式实现;但请注意,只有第一个选项适用于 Windows

  1. <ZOOKEEPER_HOME>/conf/zoo.cfg 中,例如,要将文件大小限制增加到小于 10MB 的一个字节,请添加此行

    jute.maxbuffer=0x9fffff
  2. <ZOOKEEPER_HOME>/conf/zookeeper-env.sh 中,例如,要将文件大小限制增加到 50MiB,请添加此行

    JVMFLAGS="$JVMFLAGS -Djute.maxbuffer=50000000"
  3. <ZOOKEEPER_HOME>/bin/zkServer.sh 中,在脚本顶部附近添加一个 JVMFLAGS 环境变量赋值,例如,要将文件大小限制增加到 5MiB

    JVMFLAGS="$JVMFLAGS -Djute.maxbuffer=5000000"

为 ZooKeeper 客户端配置 jute.maxbuffer

bin/solr 脚本调用充当 ZooKeeper 客户端的 Java 程序。当您使用 Solr 捆绑的 ZooKeeper 服务器,而不是设置外部 ZooKeeper 集群时,下面描述的配置也将配置 ZooKeeper 服务器。

将设置添加到 Solr 包含文件(bin/solr.in.shsolr.in.cmd)中的 SOLR_OPTS 环境变量

Linux:solr.in.sh

要查找的部分将开始

# Anything you add to the SOLR_OPTS variable will be included in the java
# start command line as-is, in ADDITION to other options. If you specify the
# -a option on start script, those options will be appended as well. Examples:

添加以下行以将文件大小限制增加到 2MB

SOLR_OPTS="$SOLR_OPTS -Djute.maxbuffer=0x200000"

Windows:solr.in.cmd

要查找的部分将开始

REM Anything you add to the SOLR_OPTS variable will be included in the java
REM start command line as-is, in ADDITION to other options. If you specify the
REM -a option on start script, those options will be appended as well. Examples:

添加以下行以将文件大小限制增加到 2MB

set SOLR_OPTS=%SOLR_OPTS% -Djute.maxbuffer=0x200000

保护 ZooKeeper 连接

您可能还希望保护 ZooKeeper 和 Solr 之间的通信。

要设置 znode 的 ACL 保护,请参阅部分 ZooKeeper 访问控制