内存和 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 RAM 中的一部分或全部,具体取决于 Metabase 的活动。但从机器的角度来看,即使 Metabase 只使用分配的 RAM 的一小部分,JVM 也会始终使用已分配的 2GB 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.