故障排除内存和 JVM 问题

Metabase 运行在 Java 虚拟机 (JVM) 上,并且根据其配置方式,它可能会使用服务器的文件系统来存储一些信息。因此,JVM 或文件系统的问题可能会阻止 Metabase 运行。

Java 版本

Metabase 应运行在 Java 21 版本上(旧版本不受支持)。

搜索 Java 版本时,始终使用您选择的主版本中的最新次要版本。例如,在选择 Java 21.0.1 和 Java 21.0.4 之间时,请选择最新版本(在本例中为 21.0.4)。

我们建议在单个服务器上只运行一个 Java 版本,因为在单个服务器上运行多个 Java 版本可能会导致应用程序问题。如果您需要运行多个需要不同 Java 版本的应用程序,请考虑使用容器(因为容器旨在解决此问题)。否则,只需确保所有应用程序都可以使用单个 Java 版本运行。

Metabase 的内存使用

Metabase 以 JAR 文件的形式发布,运行在 Java 虚拟机 (JVM) 上。

区分 Metabase 的内存使用和 JVM 的内存使用非常重要。

JVM 将消耗恒定量的内存。默认情况下,JVM 将使用机器 RAM 的约四分之一(尽管您可以更改您希望 JVM 使用的 RAM 量)。

JVM 应用程序(如 Metabase)将消耗和释放分配给 JVM 的 RAM。但是,JVM 不会将未使用的 RAM 释放给机器;JVM 的内存使用将是恒定的。

因此,在具有 8 GB RAM 的机器上,默认情况下 JVM 将使用 2 GB RAM。Metabase 将使用这些 JVM 分配的 2 GB RAM 的一部分或全部,具体取决于 Metabase 的活动。但从机器的角度来看,即使 Metabase 只使用了分配的 RAM 的一小部分,JVM 也会始终使用分配的 2 GB RAM。

诊断内存问题

鉴于上述关于 JVM 如何处理内存的解释,如果您遇到 Metabase 的性能问题,并且认为这不是由于您的数据仓库造成的,那么您需要检查以下危险信号

Metabase 因 Java 堆空间 OutOfMemoryError 而崩溃

JVM 通常可以确定系统上有多少 RAM 可用,并自动为堆内存使用设置一个合理的上限。然而,在某些共享托管环境中,这并不总是按预期工作。其常见症状是出现以下错误消息

java.lang.OutOfMemoryError: Java heap space

如果您看到此“内存不足”(OOM) 错误,您需要为 JVM 分配更多内存

当您将内存使用量随时间的变化以折线图形式查看时,您会看到锯齿状模式

您可以使用工具查看 Metabase 如何随时间使用其可用的内存。请查看

您需要检查的特定 Prometheus 指标是 jvm_memory_bytes_used{area=”heap”}

一个需要注意的危险信号:锯齿状模式。Metabase 会迅速消耗大量内存,这将触发垃圾回收,释放内存,然后 Metabase 又会迅速再次消耗内存。这种内存使用量上下波动的模式是频繁垃圾回收周期的标志。垃圾回收会占用 CPU 周期,从而减慢您的应用程序。

如果您看到这种情况,您需要增加分配给 JVM 的内存量

为 JVM 分配更多内存

您可以设置 JVM 选项以向 JVM 堆分配更多内存。例如,您的 Java 运行时可能会使用 -X 标志来执行此操作

java -Xmx2g -jar metabase.jar

向上调整内存分配,直到 Metabase 运行良好,但请确保将该数字保持低于机器上可用的总 RAM 量,因为 Metabase 不是唯一运行的进程。为机器上的其他进程留下 1 到 2 GB 的 RAM 通常就足够了,因此您可以在具有 2 GB RAM 的机器上将 -Xmx 设置为 1g,在具有 4 GB RAM 的机器上设置为 2g,依此类推。您可能需要尝试这些设置,以找到一个能使 Metabase 和所有其他程序良好协作的设置(并且这种尝试可能需要升级到具有更多内存的机器)。

您还可以使用环境变量 JAVA_OPTS 来设置 JVM 参数,而不是直接将它们传递给 java。这在运行 Docker 镜像时特别有用

docker run -d -p 3000:3000 -e "JAVA_OPTS=-Xmx2g" metabase/metabase

诊断导致 OutOfMemoryErrors 的内存问题

如果 Metabase 实例在运行相当长一段时间后才出现内存不足的情况,则可能是某个特定事件(例如大型查询)触发了 OutOfMemoryError。诊断内存使用情况的一种方法是在触发 OutOfMemoryError 时启用堆转储。要启用此功能,您需要向 java 调用添加两个标志

java -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/a/directory -jar metabase-jar

-XX:HeapDumpPath 标志指定转储文件的位置——当前目录是默认位置。当发生 OutOfMemoryError 时,JVM 会将一个 hprof 文件转储到指定的目录。这些 hprof 文件可能很大(-Xmx 参数的大小),因此请确保您的磁盘有足够的空间。这些 hprof 文件可以使用许多不同的工具读取,例如 jhat(JDK 中包含)或 Eclipse Memory Analyzer Tool

Metabase 无法读取或写入文件或文件夹 (IOError)

如果您看到有关文件权限的错误,例如 Metabase 无法读取 SQLite 数据库或自定义 GeoJSON 地图文件,请查看我们Docker 故障排除指南中“Metabase 无法读写文件或目录”部分。

警告:sun.reflect.Reflection.getCallerClass 不受支持

不用担心。

WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.

如果您看到上述错误,请忽略它。您的 Metabase 完全正常运行。

阅读其他版本的 Metabase 的文档。

这有帮助吗?

感谢您的反馈!
想改进这些文档吗?提出修改建议。
© . This site is unofficial and not affiliated with Metabase, Inc.