故障排除内存和 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 的文档。