将 Solr 投入生产

本部分提供了有关如何设置 Solr 以在 *nix 平台(如 Ubuntu)上运行的指南。具体来说,我们将逐步介绍在 Linux 主机上运行单个 Solr 实例的设置过程,然后提供有关如何在同一主机上支持多个 Solr 节点运行的提示。

服务安装脚本

Solr 包含一个服务安装脚本 (bin/install_solr_service.sh),可帮助您在 Linux 上将 Solr 安装为服务。目前,该脚本仅支持 CentOS、Debian、Red Hat、SUSE 和 Ubuntu Linux 发行版。在运行脚本之前,您需要确定有关设置的一些参数。具体来说,您需要决定将 Solr 安装在何处,以及哪个系统用户应为 Solr 文件和进程的所有者。

规划目录结构

我们建议将实时 Solr 文件(如日志和索引文件)与 Solr 发行包中包含的文件分开,因为这使得升级 Solr 变得更加容易,并且被认为是系统管理员应遵循的良好做法。

Solr 安装目录

默认情况下,服务安装脚本会将发行存档解压缩到 /opt 中。您可以在运行安装脚本时使用 -i 选项更改此位置。该脚本还会创建指向 Solr 版本目录的符号链接。例如,如果您为 Solr 9.5.0 运行安装脚本,则将使用以下目录结构

/opt/solr-9.5.0
/opt/solr -> /opt/solr-9.5.0

使用符号链接可使任何脚本不依赖于特定的 Solr 版本。如果您以后需要升级到更高版本的 Solr,则只需更新符号链接以指向升级版本的 Solr 即可。在本页的其余部分中,我们将使用 /opt/solr 来指代 Solr 安装目录。

可写文件单独的目录

您还应将可写的 Solr 文件分隔到不同的目录中;默认情况下,安装脚本使用 /var/solr,但您可以使用 -d 选项覆盖此位置。使用此方法,/opt/solr 中的文件将保持不变,并且 Solr 运行时更改的所有文件都将位于 /var/solr 下。

创建 Solr 用户

出于安全原因,不建议以 root 身份运行 Solr,并且 bin/solr start 命令将拒绝这样做。因此,您应确定将拥有所有 Solr 文件和正在运行的 Solr 进程的系统用户的用户名。默认情况下,安装脚本将创建 solr 用户,但您可以使用 -u 选项覆盖此设置。如果您的组织对创建新用户帐户有特定要求,那么您应在运行脚本之前创建用户。安装脚本将使 Solr 用户成为 /opt/solr/var/solr 目录的所有者。

现在,您已准备好运行安装脚本。

运行 Solr 安装脚本

要运行脚本,您需要下载最新的 Solr 分发存档,然后执行以下操作

tar xzf solr-9.5.0.tgz solr-9.5.0/bin/install_solr_service.sh --strip-components=2

之前的命令将 install_solr_service.sh 脚本从存档中解压到当前目录。如果在 Red Hat 上安装,请确保在运行 Solr 安装脚本之前安装了 lsofsudo yum install lsof)。安装脚本必须以 root 身份运行

sudo bash ./install_solr_service.sh solr-9.5.0.tgz

默认情况下,脚本将分发存档解压到 /opt,将 Solr 配置为将文件写入 /var/solr,并将 Solr 作为 solr 用户运行。因此,以下命令产生的结果与之前的命令相同

sudo bash ./install_solr_service.sh solr-9.5.0.tgz -i /opt -d /var/solr -u solr -s solr -p 8983

您可以使用传递给安装脚本的选项自定义服务名称、安装目录、端口和所有者。要查看可用选项,只需执行

sudo bash ./install_solr_service.sh -help

脚本完成后,Solr 将作为服务安装并在您的服务器上在后台运行(在端口 8983 上)。要验证,您可以执行

sudo service solr status

如果您不想立即启动服务,请传递 -n 选项。然后,您可以稍后手动启动服务,例如,在完成配置设置后。

我们稍后将介绍一些其他配置设置,以便对 Solr 设置进行微调。在继续之前,让我们仔细了解安装脚本执行的步骤。这将为你提供更好的概览,并且在阅读本指南中的其他页面时,将帮助你了解有关 Solr 安装的重要详细信息;例如,当页面引用 Solr 主目录时,你将确切知道它在系统中的位置。

Solr 主目录

Solr 主目录(不要与 Solr 安装目录混淆)是 Solr 管理带有索引文件的核心目录的位置。默认情况下,安装脚本使用 /var/solr/data。如果在安装脚本上使用了 -d 选项,则它将更改为 -d 选项给出的位置中的 data 子目录。花点时间检查系统中 Solr 主目录的内容。如果你没有在 ZooKeeper 中存储 solr.xml,则主目录必须包含一个 solr.xml 文件。Solr 启动时,Solr 控制脚本使用 -Dsolr.solr.home=…​ 系统属性传递主目录的位置。

环境覆盖包含文件

服务安装脚本创建一个环境特定的包含文件,该文件覆盖 bin/solr 脚本使用的默认值。使用包含文件的主要优点是它提供了一个位置,在该位置中定义所有特定于环境的覆盖。花点时间检查 /etc/default/solr.in.sh 文件的内容,这是安装脚本设置的默认路径。如果你在安装脚本上使用了 -s 选项来更改服务名称,则文件名第一部分将不同。对于名为 solr-demo 的服务,该文件将被命名为 /etc/default/solr-demo.in.sh。你可以使用此文件覆盖许多设置。但是,此脚本至少需要定义 SOLR_PID_DIRSOLR_HOME 变量,例如

SOLR_PID_DIR=/var/solr
SOLR_HOME=/var/solr/data

SOLR_PID_DIR 变量设置 控制脚本 将写入包含 Solr 服务器进程 ID 的文件所在的目录。

日志设置

Solr 使用 Apache Log4J 进行日志记录。安装脚本将 /opt/solr/server/resources/log4j2.xml 复制到 /var/solr/log4j2.xml。花点时间通过检查 /etc/default/solr.in.sh 中的以下设置来验证 Solr 包含文件已配置为将日志发送到正确的位置

LOG4J_PROPS=/var/solr/log4j2.xml
SOLR_LOGS_DIR=/var/solr/logs

有关 Log4J 配置的更多信息,请参阅:配置日志记录

init.d 脚本

在 Linux 上运行 Solr 等服务时,通常会设置一个 init.d 脚本,以便系统管理员可以使用服务工具控制 Solr,例如:service solr start。安装脚本会创建一个非常基本的 init.d 脚本来帮助您入门。花点时间检查 /etc/init.d/solr 文件,这是安装脚本设置的默认脚本名称。如果您在安装脚本中使用了 -s 选项来更改服务名称,那么文件名将不同。请注意,以下变量是根据传递给安装脚本的参数为您的环境设置的

SOLR_INSTALL_DIR=/opt/solr
SOLR_ENV=/etc/default/solr.in.sh
RUNAS=solr

SOLR_INSTALL_DIRSOLR_ENV 变量应该是自解释的。RUNAS 变量设置 Solr 进程的所有者,例如 solr;如果您不设置此值,脚本将以 root 身份运行 Solr,这不建议用于生产。您可以使用 /etc/init.d/solr 脚本通过以下操作以 root 身份启动 Solr

service solr start

/etc/init.d/solr 脚本还支持 stoprestartstatus 命令。请记住,Solr 附带的 init 脚本非常基础,旨在向您展示如何将 Solr 设置为服务。但是,使用更高级的工具(如 supervisordupstart)来控制 Solr 作为 Linux 上的服务也很常见。虽然展示如何将 Solr 与 supervisord 等工具集成超出了本指南的范围,但 init.d/solr 脚本应提供足够的指导来帮助您入门。此外,安装脚本将 Solr 服务设置为在主机初始化时自动启动。

进度检查

在下一部分中,我们将介绍一些其他环境设置,以帮助您微调生产设置。但是,在我们继续之前,让我们回顾一下到目前为止我们取得的成就。具体来说,您应该能够使用 /etc/init.d/solr 控制 Solr。请验证以下命令是否适用于您的设置

sudo service solr restart
sudo service solr status

status 命令应提供有关正在运行的 Solr 节点的一些基本信息,类似于

Solr process PID running on port 8983
{
  "version":"5.0.0 - ubuntu - 2014-12-17 19:36:58",
  "startTime":"2014-12-19T19:25:46.853Z",
  "uptime":"0 days, 0 hours, 0 minutes, 8 seconds",
  "memory":"85.4 MB (%17.4) of 490.7 MB"}

如果 status 命令不成功,请在 /var/solr/logs/solr.log 中查找错误消息。

微调您的生产设置

ConcurrentMergeScheduler 的动态默认值

合并调度程序在 solrconfig.xml 中配置,默认为 ConcurrentMergeScheduler。此调度程序使用多个线程在后台合并 Lucene 段。

默认情况下,ConcurrentMergeScheduler 会自动检测 maxThreadCountmaxMergeCount 的默认值。maxThreadCount 设置为 4 或提供给 JVM 的处理器数量的一半(以较大者为准),而 maxMergeCount 设置为 maxThreadCount+5

如果您有旋转磁盘,最好在 SolrConfig.xml 的 IndexConfig 部分 中明确设置 maxThreadCountmaxMergeCount 的值,以便使用适合您硬件的值。

内存和 GC 设置

默认情况下,bin/solr 脚本将最大 Java 堆大小设置为 512M (-Xmx512m),这对于开始使用 Solr 来说很好。对于生产环境,您需要根据搜索应用程序的内存要求增加最大堆大小;对于生产服务器,8 到 16 千兆字节的值并不罕见。当您需要更改 Solr 服务器的内存设置时,请在 include 文件中使用 SOLR_HEAP 变量,例如

SOLR_HEAP="8g"

除非您知道需要,否则不要分配非常大的 Java 堆。有关详细信息,请参见 选择内存堆设置

此外,Solr 控制脚本 附带了一组预配置的 Garbage First 垃圾回收设置,这些设置已被证明可以很好地与 Solr 配合使用,适用于许多不同的工作负载。但是,这些设置可能不适用于您对 Solr 的特定使用。因此,您可能需要更改 GC 设置,这也应该在 /etc/default/solr.in.sh include 文件中的 GC_TUNE 变量中完成。

您还可以参考 JVM 设置 来调整您的内存和垃圾回收设置。

内存不足处理

bin/solr 脚本使用 -XX:+CrashOnOutOfMemoryError JVM 选项在 OutOfMemoryError 异常时使 Solr 崩溃。建议采用此行为。在 SolrCloud 模式下,ZooKeeper 将立即收到通知,表明某个节点遇到了不可恢复的错误。

使用 SolrCloud 投入生产

要在 SolrCloud 模式下运行 Solr,您需要在 include 文件中设置 ZK_HOST 变量以指向您的 ZooKeeper 集群。在生产环境中不支持运行嵌入式 ZooKeeper。例如,如果您有一个 ZooKeeper 集群托管在以下三个主机上的默认客户端端口 2181(zk1、zk2 和 zk3),那么您将设置

ZK_HOST=zk1,zk2,zk3

设置 ZK_HOST 变量后,Solr 将在“云”模式下启动。

ZooKeeper chroot

如果您正在使用其他系统共享的 ZooKeeper 实例,建议使用 ZooKeeper 的 chroot 支持隔离 SolrCloud znode 树。例如,为了确保 SolrCloud 创建的所有 znode 都存储在 /solr 下,您可以在 ZK_HOST 连接字符串的末尾放置 /solr,例如

ZK_HOST=zk1,zk2,zk3/solr

在首次使用 chroot 之前,您需要使用 Solr 控制脚本 在 ZooKeeper 中创建根路径(znode)。我们可以使用 mkroot 命令来实现

bin/solr zk mkroot /solr -z <ZK_node>:<ZK_PORT>

如果您还想使用现有的 solr_home 引导 ZooKeeper,则可以使用 zkcli.sh / zkcli.bat bootstrap 命令,如果 chroot 路径不存在,它还将创建该路径。有关更多信息,请参阅 ZooKeeper 实用程序

未知核心删除

当 Solr 从文件系统加载核心时,它将检查 ZooKeeper 中相应的集群状态。如果没有相应的条目,则将跳过核心并记录警告。这可以防止错误配置(例如连接到错误的 ZooKeeper 实例或 chroot),在这种情况下,一旦更正配置,索引仍然有效。但是,您可能需要手动删除未作为集合有意删除的一部分而成功删除的无用核心。

如果您希望自动删除孤立文件,可以编辑 include 文件将 SOLR_DELETE_UNKNOWN_CORES 设置为 true

SOLR_DELETE_UNKNOWN_CORES=true

Solr 主机名

在 include 文件中使用 SOLR_HOST 变量设置 Solr 服务器的主机名。

SOLR_HOST=solr1.example.com

建议设置 Solr 服务器的主机名,尤其是在以 SolrCloud 模式运行时,因为这决定了节点在向 ZooKeeper 注册时的地址。

管理 UI 中的环境横幅

为了防止意外地对错误的集群进行更改,您可以在 Admin UI 中配置一个可视指示,以指示您当前是否使用生产环境。为此,使用 -Dsolr.environment=prod 设置编辑您的 solr.in.shsolr.in.cmd 文件,或设置名为 environment 的集群属性。允许的值为 devteststageprod。每个值都有预定义的默认标签和颜色。若要指定标签和/或颜色,请使用逗号分隔的格式,如下所示。必须在颜色之前定义标签。可以使用 + 字符代替空格,以避免使用引号。颜色可以是有效的 CSS 颜色或数字,例如,#ff0000 表示亮红色。有效环境配置示例

  • prod(默认标签为“生产”,默认颜色为红色调)

  • test,label=Functional+test(默认颜色仍为黄色,但覆盖标签)

  • dev,label=MyDev,color=blue(按名称覆盖标签和颜色)

  • stage,color=#ff8888(使用代码自定义颜色)

覆盖 solrconfig.xml 中的设置

Solr 允许使用在启动时使用 -Dproperty=value 语法传递的 Java 系统属性覆盖配置属性。例如,在 solrconfig.xml 中,默认自动软提交设置设置为

<autoSoftCommit>
  <maxTime>${solr.autoSoftCommit.maxTime:3000}</maxTime>
</autoSoftCommit>

一般来说,每当您在 Solr 配置文件中看到使用 ${solr.PROPERTY:DEFAULT_VALUE} 语法的属性时,您就知道可以使用 Java 系统属性覆盖它。例如,若要将软提交的 maxTime 设置为 10 秒,则可以使用 -Dsolr.autoSoftCommit.maxTime=10000 启动 Solr,例如

bin/solr start -Dsolr.autoSoftCommit.maxTime=10000

bin/solr 脚本在启动期间只需将以 -D 开头的选项传递给 JVM。对于在生产中运行,我们建议在包含文件中定义的 SOLR_OPTS 变量中设置这些属性。以我们的软提交示例为例,在 /etc/default/solr.in.sh 中,您将执行

SOLR_OPTS="$SOLR_OPTS -Dsolr.autoSoftCommit.maxTime=10000"

Ulimit 设置(*nix 操作系统)

有几个设置应该尽可能地进行监控并设置为最高值,最好是“无限制”。在大多数 *nix 操作系统上,您可以通过在命令提示符下键入以下内容来查看当前值。

ulimit -a

尤其重要的是将这四个设置设置为非常高,如果可能的话设置为无限制。

  • 最大进程数(ulimit -u):65,000 是推荐的最小值。

  • 文件句柄(ulimit -n):65,000 是推荐的最小值。所有副本使用的所有文件都同时打开了其文件句柄,因此它可能会增长得非常大。

  • 虚拟内存(ulimit -v):设置为无限制。这是通过 MMapping 索引使用的。

  • 最大内存大小(ulimit -m):也由 MMap 使用,设置为无限制。

  • 如果您的系统支持,则 sysctl vm.max_map_count 也应设置为无限制。

我们强烈建议永久提高这些设置。永久提高这些设置的确切过程因操作系统而异。某些系统需要编辑配置文件并重新启动服务器。请咨询系统管理员以获取特定环境中的指导。

每次升级内核或操作系统时,请检查这些限制。这些操作可以将这些限制重置为其默认值。

如果超过这些限制,Solr 报告的问题会根据负责超过该限制的特定操作而有所不同。已报告“打开的文件过多”、“连接错误”和“进程数已超过”等错误,以及 SolrCloud 恢复失败。

避免交换(*nix 操作系统)

在运行 Solr 等 Java 应用程序时,让操作系统将内存交换到磁盘是非常糟糕的情况。我们通常更喜欢硬崩溃,以便其他正常的 Solr 节点可以接管,而不是让 Solr 节点交换,从而导致性能低下、超时和系统不稳定。因此,我们的建议是在主机上完全禁用交换或减少“swappiness”。这些说明适用于 Linux 环境。还要注意,在 Docker 容器中运行 Solr 时,必须将这些更改应用于主机

禁用交换

要在 Linux 系统上暂时禁用交换,可以运行 swapoff 命令

sudo swapoff -a

如果要使此设置永久生效,请首先确保主机上有足够的物理 RAM,然后查阅 Linux 系统的文档以了解禁用交换的正确步骤。

减少 Swappiness

另一种选择是减少系统的“swappiness”。Linux 系统默认情况下会非常积极地将内存交换到磁盘,因为默认的“swappiness”值很高。通过将其降低到非常低的值,它将产生与使用 swapoff 几乎相同的效果,但 Linux 仍将在紧急情况下进行交换。要检查当前的 swappiness 设置,请运行

cat /proc/sys/vm/swappiness

接下来,要永久更改设置,请以 root 用户身份打开 /etc/sysctl.conf。然后,更改或将此行添加到文件中

vm.swappiness = 1

或者,可以通过运行此命令暂时更改设置

echo 1 > /proc/sys/vm/swappiness

安全注意事项

管理员应仔细考虑其安全设置,作为转向生产环境的重要步骤。Solr 提供了许多开箱即用的功能来满足用户的安全需求:可以使用一系列安全插件配置身份验证和授权,可以通过启用 SSL/TLS 来增强隐私,并且(在 SolrCloud 中)可以使用 ACL 规则保护 ZooKeeper 数据以防止未经授权的读取和写入。

即使采取了这些措施或其他措施,也强烈建议始终通过防火墙保护 Solr。Solr 不适用于在开放互联网上公开。

强烈建议 Solr 仅侦听严格必需的那些网络接口。为了防止管理员无意中更广泛地公开 Solr,Solr 默认仅侦听环回接口(“127.0.0.1”)。大多数部署都需要将此值更改为限制较少的值,以便可以从其他计算机访问它。这可以通过在环境的“include 脚本”(solr.in.shsolr.in.cmd)中设置 SOLR_JETTY_HOST 值来完成

 ----
 SOLR_JETTY_HOST="0.0.0.0"
 ----

相同的设置也可作为 -Dsolr.jetty.host 系统属性使用。

如果嵌入式 Zookeeper 与 Solr 一起运行,则同样适用于嵌入式 Zookeeper。默认情况下,嵌入式 Zookeeper 仅侦听环回接口(“127.0.0.1”)。绑定主机通过环境的“include 脚本”(solr.in.shsolr.in.cmd)中的 SOLR_ZK_EMBEDDED_HOST 值进行控制

 ----
 SOLR_ZK_EMBEDDED_HOST="0.0.0.0"
 ----

相同的设置也可作为 -Dsolr.zk.embedded.host 系统属性使用。

在每个主机上运行多个 Solr 节点

bin/solr 脚本能够在一台机器上运行多个实例,但对于典型安装,这不是推荐的设置。每个附加实例都需要额外的 CPU 和内存资源。单个实例很容易处理多个索引。

何时忽略建议

对于每项建议,都有例外。对于上述建议,该例外主要适用于讨论极端可扩展性。在单主机上运行多个 Solr 节点的最佳原因是减少对极大堆的需求。

当 Java 堆变得非常大时,即使使用启动脚本默认提供的 GC 调优,也可能导致极长的垃圾回收暂停。堆被认为“非常大”的确切点将根据 Solr 的使用方式而有所不同。这意味着无法给出硬性数字作为阈值,但如果堆达到 16 到 32 GB 左右,则可能是考虑拆分节点的时候了。理想情况下,这意味着更多的机器,但预算限制可能会使这变得不可能。

一旦堆达到 32GB,就会出现另一个问题。在 32GB 以下,Java 能够使用压缩指针,但超过该点,需要更大的指针,这会使用更多的内存并减慢 JVM 的速度。

如果您的用例需要超过 31GB 的堆,那么请考虑使用多个节点,因为它们通常比具有 >32GB 堆的单个节点性能更好。

如果你的用例需要多个实例,至少需要为要运行的每个节点提供唯一的 Solr 主目录;理想情况下,每个主目录都应位于不同的物理磁盘上,以便多个 Solr 节点在访问磁盘上的文件时不必相互竞争。拥有不同的 Solr 主目录意味着你将需要为每个节点提供不同的 include 文件。此外,如果使用 /etc/init.d/solr 脚本将 Solr 作为服务进行控制,则需要为每个节点提供一个单独的脚本。最简单的方法是使用服务安装脚本在同一主机上添加多个服务,例如

sudo bash ./install_solr_service.sh solr-9.5.0.tgz -s solr2 -p 8984

上面显示的命令将添加一个名为 solr2 的服务,该服务在端口 8984 上运行,并使用 /var/solr2 作为可写(又称“实时”)文件;第二个服务器仍将归 solr 用户所有并由其运行,并将使用 /opt 中的 Solr 分发文件。在安装 solr2 服务后,通过执行以下操作验证其是否正常工作

sudo service solr2 restart
sudo service solr2 status