重要的系统配置

edit

理想情况下,Elasticsearch 应该单独运行在一台服务器上,并使用其所有可用资源。为此,您需要配置操作系统,以允许运行 Elasticsearch 的用户访问比默认允许的更多资源。

以下设置必须在进入生产环境之前考虑:

开发模式 vs 生产模式

edit

默认情况下,Elasticsearch 假设您处于开发模式。如果上述任何设置配置不正确,将会在日志文件中写入警告,但您仍然可以启动并运行您的 Elasticsearch 节点。

一旦您配置了像network.host这样的网络设置,Elasticsearch就会认为您正在进入生产环境,并将上述警告升级为异常。这些异常将阻止您的Elasticsearch节点启动。这是一个重要的安全措施,以确保您不会因为服务器配置错误而丢失数据。

配置系统设置

edit

配置系统设置的位置取决于您用于安装 Elasticsearch 的软件包,以及您使用的操作系统。

当使用.zip.tar.gz包时,可以配置系统设置:

当使用RPM或Debian包时,大多数系统设置都在系统配置文件中设置。然而,使用systemd的系统要求在systemd配置文件中指定系统限制。

ulimit

edit

在Linux系统上,可以使用ulimit来临时更改资源限制。通常需要在切换到运行Elasticsearch的用户之前,以root身份设置这些限制。例如,要将打开的文件句柄数(ulimit -n)设置为65,535,可以执行以下操作:

sudo su  
ulimit -n 65535 
su elasticsearch 

成为root

更改最大打开文件数。

成为 elasticsearch 用户以便启动 Elasticsearch。

新限制仅在当前会话期间适用。

您可以查询所有当前应用的限制,使用 ulimit -a

/etc/security/limits.conf

edit

在Linux系统上,可以通过编辑/etc/security/limits.conf文件为特定用户设置持久性限制。要将elasticsearch用户的最大打开文件数设置为65,535,请将以下行添加到limits.conf文件中:

elasticsearch  -  nofile  65535

此更改仅在下一次 elasticsearch 用户打开新会话时生效。

Ubuntu 和 limits.conf

Ubuntu 忽略由 init.d 启动的进程的 limits.conf 文件。要启用 limits.conf 文件,请编辑 /etc/pam.d/su 并取消注释以下行:

# session    required   pam_limits.so

系统配置文件

edit

当使用RPM或Debian包时,可以在系统配置文件中指定环境变量,该文件位于:

每分钟转数

/etc/sysconfig/elasticsearch

Debian

/etc/default/elasticsearch

然而,系统限制需要通过systemd指定。

Systemd 配置

edit

在使用 systemd 的系统上使用 RPM 或 Debian 包时,系统限制必须通过 systemd 指定。

systemd 服务文件(/usr/lib/systemd/system/elasticsearch.service)包含默认应用的限制。

要覆盖这些设置,请添加一个名为 /etc/systemd/system/elasticsearch.service.d/override.conf 的文件(或者, 您可以运行 sudo systemctl edit elasticsearch,它会在您的默认编辑器中自动打开该文件)。在此文件中设置任何更改, 例如:

[Service]
LimitMEMLOCK=infinity

完成后,运行以下命令以重新加载单元:

sudo systemctl daemon-reload

禁用交换

edit

大多数操作系统会尽可能多地使用内存用于文件系统缓存,并积极地将未使用的应用程序内存交换出去。这可能导致JVM堆的部分甚至其可执行页面被交换到磁盘上。

交换对性能和节点稳定性非常不利,应不惜一切代价避免。它可能导致垃圾收集持续几分钟而不是毫秒,并可能导致节点响应缓慢甚至从集群中断开连接。在一个具有弹性的分布式系统中,让操作系统杀死节点更为有效。

有三种方法可以禁用交换。首选选项是完全禁用交换。如果这不是一个选项,是否优先考虑最小化swappiness与内存锁定取决于您的环境。

禁用所有交换文件

edit

通常情况下,Elasticsearch 是唯一运行在服务器上的服务,其内存使用由 JVM 选项控制。因此,无需启用交换空间。

在Linux系统上,您可以通过运行以下命令暂时禁用交换空间:

sudo swapoff -a

这不需要重启 Elasticsearch。

要永久禁用它,您需要编辑 /etc/fstab 文件并注释掉任何包含 swap 的行。

在Windows上,可以通过完全禁用分页文件来实现等效操作,方法是进入系统属性 → 高级 → 性能 → 高级 → 虚拟内存

配置 swappiness

edit

Linux系统上的另一个选项是确保sysctl值vm.swappiness设置为1。这减少了内核进行交换的倾向,并且在正常情况下不应导致交换,同时仍然允许整个系统在紧急情况下进行交换。

启用 bootstrap.memory_lock

edit

另一个选项是在Linux/Unix系统上使用 mlockall,或在Windows上使用 VirtualLock, 以尝试将进程地址空间锁定到RAM中,防止任何Elasticsearch堆内存被交换出去。

一些平台在使用内存锁定时仍然会交换堆外内存。为了防止堆外内存交换,请禁用所有交换文件

要启用内存锁定,请在 elasticsearch.yml 中将 bootstrap.memory_lock 设置为 true

bootstrap.memory_lock: true

mlockall 可能会导致JVM或shell会话退出,如果它尝试分配的内存超过了可用内存!

启动 Elasticsearch 后,您可以通过检查此请求输出中的 mlockall 值来查看此设置是否成功应用:

GET _nodes?filter_path=**.mlockall

如果你看到mlockallfalse,那么这意味着mlockall请求失败了。你还将在日志中看到一行带有更多信息的行,其中包含无法锁定JVM内存的文字。

在Linux/Unix系统上,最可能的原因是运行Elasticsearch的用户没有锁定内存的权限。可以通过以下方式授予此权限:

.zip and .tar.gz

在启动Elasticsearch之前,以root身份设置ulimit -l unlimited。 或者,在/etc/security/limits.conf中将memlock设置为unlimited

# 允许用户 'elasticsearch' mlockall
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited
RPM and Debian
LimitMEMLOCK 设置为 infinitysystemd 配置中。

另一个可能导致 mlockall 失败的原因是 JNA 临时目录(通常是 /tmp 的子目录)以 noexec 选项挂载。可以通过使用 ES_JAVA_OPTS 环境变量指定一个新的 JNA 临时目录来解决这个问题:

export ES_JAVA_OPTS="$ES_JAVA_OPTS -Djna.tmpdir=<path>"
./bin/elasticsearch

或在jvm.options配置文件中设置此JVM标志。

文件描述符

edit

这仅与Linux和macOS相关,如果在Windows上运行Elasticsearch,可以安全地忽略。在Windows上,JVM使用一个API,该API仅受可用资源的限制。

Elasticsearch 使用了大量的文件描述符或文件句柄。文件描述符耗尽可能会导致灾难性后果,并很可能导致数据丢失。请确保将运行 Elasticsearch 的用户打开文件描述符的数量限制增加到 65,535 或更高。

对于.zip.tar.gz包,在启动Elasticsearch之前,以root身份设置ulimit -n 65535,或者在/etc/security/limits.conf中将nofile设置为65535

在 macOS 上,您还必须将 JVM 选项 -XX:-MaxFDLimit 传递给 Elasticsearch,以便它能够利用更高的文件描述符限制。

RPM 和 Debian 包已经默认将文件描述符的最大数量设置为 65535,不需要进一步配置。

您可以使用Nodes stats API检查为每个节点配置的max_file_descriptors,方法如下:

GET _nodes/stats/process?filter_path=**.max_file_descriptors

虚拟内存

edit

Elasticsearch 默认使用 mmapfs 目录来存储其索引。默认的操作系统对 mmap 计数的限制可能太低,这可能导致内存不足异常。

在 Linux 上,您可以通过以 root 身份运行以下命令来增加限制:

sysctl -w vm.max_map_count=262144

要永久设置此值,请在 /etc/sysctl.conf 中更新 vm.max_map_count 设置。重启后验证,请运行 sysctl vm.max_map_count

RPM 和 Debian 软件包将自动配置此设置。无需进一步配置。

您可以使用以下命令找出正在运行的 Elasticsearch 进程的当前 mmap 计数,其中 $PID 是正在运行的 Elasticsearch 进程的进程 ID:

wc -l /proc/$PID/maps

线程数量

edit

Elasticsearch 使用多个线程池来处理不同类型的操作。 确保它能够在需要时创建新线程非常重要。请确保 Elasticsearch 用户可以创建的线程数至少为 4096。

这可以通过在启动Elasticsearch之前以root身份设置ulimit -u 4096来完成,或者通过在/etc/security/limits.conf中将nproc设置为4096来完成。

当作为服务在 systemd 下运行时,软件包分发将自动配置 Elasticsearch 进程的线程数。无需额外配置。

DNS缓存设置

edit

Elasticsearch 在启用安全管理器的情况下运行。启用安全管理器后,JVM 默认无限期缓存正向主机名解析,并默认缓存十秒的负向主机名解析。Elasticsearch 使用默认值覆盖此行为,以缓存六十秒的正向查找,并缓存十秒的负向查找。这些值应适用于大多数环境,包括 DNS 解析随时间变化的环境。如果不适用,您可以编辑 JVM 选项 中的 es.networkaddress.cache.ttles.networkaddress.cache.negative.ttl 值。请注意,networkaddress.cache.ttl=networkaddress.cache.negative.ttl=Java 安全策略 中被 Elasticsearch 忽略,除非您删除 es.networkaddress.cache.ttles.networkaddress.cache.negative.ttl 的设置。

确保JNA临时目录允许可执行文件

edit

这仅与Linux相关。

Elasticsearch 使用 Java Native Access (JNA) 库,以及另一个名为 libffi 的库,用于执行一些平台相关的本地代码。在 Linux 上,支持这些库的本地代码在运行时被提取到一个临时目录中,然后映射到 Elasticsearch 地址空间中的可执行页。这要求底层文件不在以 noexec 选项挂载的文件系统上。

默认情况下,Elasticsearch 会在 /tmp 目录下创建其临时目录。然而,一些强化过的 Linux 安装默认会将 /tmp 挂载为 noexec 选项。这会阻止 JNA 和 libffi 正常工作。例如,在启动时,JNA 可能会因 java.lang.UnsatisfiedLinkerError 异常或类似 failed to map segment from shared object 的消息而无法加载,或者 libffi 可能会报告类似 failed to allocate closure 的消息。请注意,异常消息可能会因 JVM 版本而异。此外,依赖于通过 JNA 执行本地代码的 Elasticsearch 组件可能会因显示 because JNA is not available 的消息而失败。

要解决这些问题,请从您的 /tmp 文件系统中移除 noexec 选项,或者通过设置 $ES_TMPDIR 环境变量来配置 Elasticsearch 使用不同的临时目录位置。例如:

  • 如果你直接从shell运行Elasticsearch,请按如下方式设置$ES_TMPDIR

    export ES_TMPDIR=/usr/share/elasticsearch/tmp
  • 对于通过RPM或DEB包安装的情况,环境变量需要通过系统配置文件进行设置。
  • 如果你使用systemd将Elasticsearch作为服务运行,请在服务覆盖文件[Service]部分添加以下行:

    Environment=ES_TMPDIR=/usr/share/elasticsearch/tmp

如果您需要更精细地控制这些临时文件的位置,您也可以使用 JVM 标志 -Djna.tmpdir= 配置 JNA 使用的路径,并且可以通过设置 LIBFFI_TMPDIR 环境变量来配置 libffi 使用的临时文件路径。未来的 Elasticsearch 版本可能需要额外的配置,因此您应尽可能设置 ES_TMPDIR

Elasticsearch 不会删除其临时目录。您应在 Elasticsearch 未运行时删除剩余的临时目录。最好自动执行此操作,例如在每次重启时。如果您在 Linux 上运行,可以通过使用 tmpfs 文件系统来实现这一点。

TCP 重传超时

edit

每对 Elasticsearch 节点通过多个 TCP 连接进行通信,这些连接 保持打开,直到其中一个节点关闭或 节点之间的通信因底层基础设施的故障而中断。

TCP通过隐藏通信应用程序的临时网络中断,在偶尔不可靠的网络上提供可靠的通信。您的操作系统将在通知发送方任何问题之前,重新传输任何丢失的消息多次。Elasticsearch必须等待重新传输发生,并且只能在操作系统决定放弃时做出反应。因此,用户也必须等待一系列重新传输完成。

大多数Linux发行版默认重传任何丢失的数据包15次。重传以指数方式退避,因此这15次重传需要超过900秒才能完成。这意味着Linux需要很多分钟才能通过这种方法检测到网络分区或节点故障。Windows默认只重传5次,这对应于大约13秒的超时时间。

Linux 默认允许在可能经历非常长时间的数据包丢失的网络中进行通信,但这个默认设置在大多数 Elasticsearch 安装使用的高质量网络上是过度的,甚至是有害的。当集群检测到节点故障时,它会通过重新分配丢失的分片、重新路由搜索以及可能选举新的主节点来做出反应。高可用性集群必须能够及时检测节点故障,这可以通过减少允许的重传次数来实现。与远程集群的连接也应优先于 Linux 默认设置,更快地检测故障。因此,Linux 用户应减少 TCP 重传的最大次数。

您可以通过以root身份运行以下命令,将TCP重传的最大次数减少到5。五次重传对应的超时时间大约为13秒。

sysctl -w net.ipv4.tcp_retries2=5

要永久设置此值,请在 /etc/sysctl.conf 文件中更新 net.ipv4.tcp_retries2 设置。重启后验证,请运行 sysctl net.ipv4.tcp_retries2

此设置适用于所有TCP连接,并且也会影响与Elasticsearch集群以外的系统的通信可靠性。如果您的集群通过低质量网络与外部系统通信,那么您可能需要为net.ipv4.tcp_retries2选择一个更高的值。因此,Elasticsearch不会自动调整此设置。

相关配置

edit

Elasticsearch 还实现了自己的内部健康检查,其超时时间比 Linux 上的默认重传超时时间要短得多。由于这些是应用级别的健康检查,它们的超时时间必须允许应用级别的效应,例如垃圾回收暂停。您不应减少与这些应用级别健康检查相关的任何超时时间。

您还必须确保您的网络基础设施不会干扰节点之间的长连接,即使这些连接看起来是空闲的。当连接达到一定年龄时会断开连接的设备是Elasticsearch集群问题的常见来源,必须避免使用。