疑難排解記憶體與 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 配置的 2GB 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

診斷導致 OutOfMemoryError 的記憶體問題

如果 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 文件