JVM 设置编辑

jvm.options 设置文件 中配置 JVM 设置。也可以通过 LS_JAVA_OPTS 环境变量设置 JVM 设置。

此文件包含以特殊语法编写的 JVM 参数列表,每行一个参数

  • 仅包含空格的行将被忽略
  • # 开头的行将被视为注释并被忽略

    # this is a comment
  • - 开头的行将被视为 JVM 选项,该选项独立于 JVM 版本应用

    -Xmx2g
  • 以数字开头,后跟 :,再后跟 - 的行将被视为 JVM 选项,该选项仅在 JVM 版本与该数字匹配时才适用

    8:-Xmx2g
  • 以数字开头,后跟 -,再后跟 : 的行将被视为 JVM 选项,该选项仅在 JVM 版本大于或等于该数字时才适用

    8-:-Xmx2g
  • 以数字开头,后跟 -,再后跟另一个数字,最后是 : 的行将被视为 JVM 选项,该选项仅在 JVM 版本介于这两个数字(含)之间时才适用

    8-9:-Xmx2g
  • 所有其他行都将被拒绝

设置内存大小编辑

执行 Logstash 的 JVM 的内存可以分为两个区域:堆内存和堆外内存。堆是指 Java 堆,其中包含 Logstash 在运行期间创建的所有 Java 对象,有关如何调整其大小的说明,请参阅 设置 JVM 堆大小。不属于堆的部分称为堆外内存,由 Logstash 使用和控制的内存组成,通常是线程堆栈、直接内存和内存映射页面,有关全面说明,请查看 设置堆外内存大小。在堆外空间中,有一些空间由 JVM 使用,其中包含虚拟机执行所需的所有数据结构。Logstash 无法控制此内存,并且很少自定义设置。

设置 JVM 堆大小编辑

以下是一些调整 JVM 堆大小的技巧

  • 对于典型的摄取场景,建议的堆大小不应小于 4GB,也不应大于 8GB。
  • 如果堆大小太小,CPU 利用率可能会不必要地增加,导致 JVM 不断进行垃圾回收。您可以通过将堆大小加倍以查看性能是否有所改善来检查此问题。
  • 不要将堆大小增加到超过物理内存的量。必须留出一些内存来运行操作系统和其他进程。作为大多数安装的一般准则,不要超过物理内存的 50-75%。您拥有的内存越多,您可以使用的百分比就越高。
  • 将最小 (Xms) 和最大 (Xmx) 堆分配大小设置为相同的值,以防止堆在运行时调整大小,这是一个非常耗时的过程。
  • 您可以使用 Java 附带的 jmap 命令行实用程序或使用 VisualVM 对 JVM 堆进行更准确的测量。有关更多信息,请参阅 分析堆

设置堆外内存大小编辑

除了分配给堆大小的内存外,操作系统、持久队列 mmap 页面、直接内存和其他进程也需要内存。

内部 JVM 数据结构、线程堆栈、内存映射文件和用于输入/输出 (IO) 操作的直接内存都是堆外 JVM 内存的一部分。内存映射文件不是 Logstash 进程堆外内存的一部分,但在从磁盘分页文件时会消耗 RAM。这些映射文件加快了对持久队列页面的访问速度,这是一种性能改进(或权衡),可以减少昂贵的磁盘操作,例如读取、写入和查找。某些网络 I/O 操作还求助于进程内直接内存使用,以避免例如在网络套接字之间复制缓冲区。Elastic Agent、Beats、TCP 和 HTTP 输入等输入插件使用直接内存。线程堆栈区域包含 JVM 创建的每个 Java 线程的堆栈帧列表;每个帧都保留在方法调用期间传递的局部参数。如果需要根据处理需求调整大小,请继续阅读 设置 JVM 堆栈大小

插件根据其类型(输入、过滤器和输出)具有不同的线程模型。每个输入插件都在其自己的线程中运行,并且可能会生成其他线程。例如,每个 JDBC 输入插件都会启动一个调度程序线程。基于 Netty 的插件(如 TCP、Beats 或 HTTP 输入)会生成一个线程池,其中包含 2 * 核心数个线程。输出插件也可以启动辅助线程,例如每个 Elasticsearch 输出实例的连接管理线程。此外,每个管道都有自己的线程来管理管道生命周期。

总而言之,我们有 3 类内存使用,其中 2 类可以由 JVM 限制,而另一类则依赖于可用的空闲内存

内存类型 配置使用 使用对象

JVM 堆

-Xmx

任何正常的对象分配

JVM 直接内存

-XX:MaxDirectMemorySize

beats、tcp 和 http 输入

本机内存

不适用

持久队列页面、线程堆栈

在计算理想的内存分配时,请牢记这些内存需求。

内存大小调整编辑

必须估计 JVM 内存总分配量,并使用 Java 堆和直接内存设置间接控制。默认情况下,JVM 的堆外直接内存限制与堆大小相同。查看 beats 输入内存使用。考虑将 -XX:MaxDirectMemorySize 设置为堆大小的一半或任何可以容纳您希望这些插件处理的负载的值。

在进行容量计算时,请记住,JVM 不能消耗主机的可用内存总量,因为操作系统和其他进程也需要内存。

对于在多个管道上启用了持久队列 (PQ) 的 Logstash 实例,我们可以使用以下公式估算内存消耗

pipelines number * (pipeline threads * stack size + 2 * PQ page size) + direct memory + Java heap

每个持久队列都要求至少头部和尾部页面存在并可在内存中访问。默认页面大小为 64 MB,因此每个 PQ 至少需要 128 MB 的堆内存,这可能是每个管道内存消耗的重要来源。请注意,内存映射文件的大小不能用上限来限制。

堆栈大小是一个取决于所用 JVM 的设置,但可以使用 -Xss 设置进行自定义。

默认情况下,直接内存空间与 Java 堆一样大,但可以使用 -XX:MaxDirectMemorySize 设置进行自定义。

示例

考虑一个运行 10 个管道的 Logstash 实例,该实例具有不启动其他线程的简单输入和输出插件,它有 1 个管道线程、1 个输入插件线程和 12 个工作线程,总计 14 个。请记住,默认情况下,JVM 分配的直接内存等于为 Java 堆分配的内存。

计算结果为

  • 本机内存:1.4GB [源自 10 * (14 * 1Mb + 128Mb)]
  • 直接内存:4GB
  • Java 堆:4GB

设置 JVM 堆栈大小编辑

大型配置可能需要额外的 JVM 堆栈内存。如果您看到堆栈溢出错误,请尝试增加 JVM 堆栈大小。在 jvm.options 设置文件 中添加类似于以下内容的条目

-Xss4M

请注意,默认堆栈大小因平台和操作系统版本而异。您可以通过运行以下命令找出默认值

java -XX:+PrintFlagsFinal -version | grep ThreadStackSize

根据默认堆栈大小,首先乘以 4 倍,然后是 8 倍,然后是 16 倍,直到溢出错误解决。

使用 LS_JAVA_OPTS编辑

LS_JAVA_OPTS 环境变量也可用于覆盖 jvm.options 文件 设置文件 中的 JVM 设置。此变量的内容将添加到在 jvm.options 文件中配置的选项中,并将覆盖这两个位置中存在的任何设置。

例如,要设置不同的语言环境来启动 Logstash 实例

LS_JAVA_OPTS="-Duser.country=DE -Duser.language=de" bin/logstash -e 'input { stdin { codec => json } }'