عیبیابی مشکلات حافظه و JVM
متابیس روی Java Virtual Machine (JVM) اجرا میشود، و بسته به نحوهٔ پیکربندی آن، ممکن است از filesystem سرور برای ذخیره برخی اطلاعات استفاده کند. مشکلات با JVM یا filesystem بنابراین میتوانند از اجرای متابیس جلوگیری کنند.
نسخه Java
متابیس باید روی نسخه Java 21 اجرا شود (نسخههای قدیمیتر پشتیبانی نمیشوند).
هنگام جستجو برای نسخههای Java، همیشه از آخرین نسخه minor از نسخه major که انتخاب میکنید استفاده کنید. مثلاً، هنگام انتخاب بین Java 21.0.1 و Java 21.0.4، آخرین نسخه را انتخاب کنید (در این مورد، 21.0.4).
توصیه میکنیم فقط یک نسخه Java روی یک سرور واحد اجرا کنید، چون اجرای بیش از یک نسخه Java روی یک سرور واحد میتواند مشکلات اپلیکیشن ایجاد کند. اگر نیاز به اجرای چندین اپلیکیشن دارید که هر کدام نیاز به نسخه java متفاوتی دارند، استفاده از containerها را در نظر بگیرید (چون containerها برای حل این مشکل طراحی شدهاند). در غیر این صورت، فقط مطمئن شوید که میتوانید همه اپلیکیشنهای خود را با یک نسخه Java واحد اجرا کنید.
استفاده از حافظه متابیس
متابیس بهعنوان یک فایل JAR که روی Java Virtual Machine (JVM) اجرا میشود ship میشود.
مهم است که استفاده از حافظه متابیس را از استفاده از حافظه JVM متمایز کنیم.
JVM مقدار ثابتی از حافظه را مصرف میکند. بهطور پیشفرض، JVM حدود یک چهارم RAM ماشین را استفاده میکند (اگرچه میتوانید مقدار RAM که میخواهید JVM استفاده کند را تغییر دهید).
اپلیکیشنهای JVM (مثل متابیس) RAM اختصاص داده شده به JVM را مصرف و آزاد میکنند. با این حال، JVM RAM استفاده نشده را به ماشین آزاد نمیکند؛ استفاده از حافظه JVM ثابت خواهد بود.
پس روی یک ماشین با 8 GB RAM، بهطور پیشفرض JVM 2 GB RAM را استفاده میکند. متابیس برخی یا همه این 2 GB RAM اختصاص داده شده به JVM را استفاده میکند، بسته به فعالیت متابیس. اما از دیدگاه ماشین، JVM همیشه آن 2GB RAM اختصاص داده شده را استفاده میکند، حتی وقتی متابیس فقط کسری از آن RAM اختصاص داده شده را استفاده میکند.
تشخیص مشکلات حافظه
با توجه به توضیح بالا از نحوهٔ مدیریت حافظه توسط JVM، اگر مشکلات عملکردی با متابیس دارید که فکر نمیکنید به دلیل data warehouse شما باشد، میخواهید این پرچمهای قرمز را بررسی کنید:
متابیس به دلیل Java heap space OutOfMemoryError crash میکند
JVM معمولاً میتواند بفهمد چقدر RAM در سیستم در دسترس است و بهطور خودکار یک حد بالای منطقی برای استفاده از heap memory تنظیم کند. در برخی محیطهای میزبانی مشترک، با این حال، این همیشه طبق میل کار نمیکند. علامت معمول این یک پیام خطا مثل این است:
java.lang.OutOfMemoryError: Java heap space
اگر این خطای "Out of memory" (OOM) را میبینید، باید حافظه بیشتری به JVM اختصاص دهید.
وقتی استفاده از حافظه را در طول زمان بهعنوان یک نمودار خطی مشاهده میکنید، یک الگوی sawtooth میبینید
میتوانید از ابزارها برای مشاهده نحوهٔ استفاده متابیس از حافظه در دسترس خود در طول زمان استفاده کنید. بررسی کنید:
متریک Prometheus خاصی که باید بررسی کنید jvm_memory_bytes_used{area="heap"} است
یک پرچم قرمز برای مراقبت: الگوی sawtooth. متابیس به سرعت مقدار زیادی حافظه مصرف میکند، که garbage collection را trigger میکند، که حافظه را آزاد میکند، که متابیس دوباره به سرعت مصرف میکند. این الگوی بالا-پایین-بالا-پایین استفاده از حافظه امضای چرخههای مکرر garbage collection است. garbage collection چرخههای CPU را مسدود میکند، که میتواند اپلیکیشن شما را کند کند.
اگر این را میبینید، باید مقدار حافظه اختصاص داده شده به JVM را افزایش دهید.
اختصاص حافظه بیشتر به JVM
میتوانید یک گزینه JVM تنظیم کنید تا حافظه بیشتری به heap JVM اختصاص دهد. بهعنوان مثال، runtime Java شما ممکن است از flag -X برای انجام این کار استفاده کند:
java -Xmx2g -jar metabase.jar
تخصیص حافظه را بالا تنظیم کنید تا متابیس راضی به نظر برسد، اما مطمئن شوید که عدد را کمتر از کل مقدار RAM در دسترس روی ماشین خود نگه دارید، چون متابیس تنها فرآیند در حال اجرا نخواهد بود. باقی گذاشتن 1 تا 2 GB RAM برای فرآیندهای دیگر روی ماشین بهطور کلی کافی است، بنابراین ممکن است -Xmx را روی 1g روی یک ماشین با 2 GB RAM، 2g روی یکی با 4 GB RAM، و غیره تنظیم کنید. ممکن است نیاز به آزمایش با این تنظیمات داشته باشید تا یکی پیدا کنید که متابیس و همه چیز دیگر را به خوبی با هم کار میکند (و این آزمایش ممکن است نیاز به ارتقا به یک ماشین با حافظه بیشتر داشته باشد).
همچنین میتوانید از متغیر محیطی JAVA_OPTS برای تنظیم args JVM به جای ارسال مستقیم آنها به java استفاده کنید. این بهطور خاص هنگام اجرای Docker image مفید است:
docker run -d -p 3000:3000 -e "JAVA_OPTS=-Xmx2g" metabase/metabase
تشخیص مشکلات حافظه که باعث OutOfMemoryErrors میشوند
اگر instance متابیس راهاندازی میشود و برای مدت زمان قابل توجهی قبل از تمام شدن حافظه اجرا میشود، ممکن است یک رویداد خاص، مثل یک کوئری بزرگ، OutOfMemoryError را trigger کند. یک راه برای تشخیص اینکه حافظه کجا استفاده میشود فعال کردن heap dumpها وقتی یک OutOfMemoryError trigger میشود است. برای فعال کردن این، باید دو flag به invocation java اضافه کنید:
java -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/a/directory -jar metabase-jar
flag -XX:HeapDumpPath مشخص میکند dump کجا قرار گیرد---دایرکتوری فعلی پیشفرض است. وقتی یک OutOfMemoryError اتفاق میافتد، JVM یک فایل hprof را به دایرکتوری مشخص شده dump میکند. این فایلهای hprof میتوانند بزرگ باشند (اندازه argument -Xmx) بنابراین مطمئن شوید دیسک شما فضای کافی دارد. این فایلهای hprof میتوانند با ابزارهای مختلفی، مثل jhat (که با JDK شامل میشود) یا Eclipse Memory Analyzer Tool خوانده شوند.
متابیس نمیتواند از یک فایل یا پوشه بخواند یا بنویسد (IOError)
اگر خطایی دربارهٔ مجوزهای فایل میبینید، مثل اینکه متابیس نمیتواند یک پایگاه داده SQLite یا یک فایل نقشه GeoJSON سفارشی را بخواند، بخش "Metabase can't read to/from a file or directory" را در راهنمای عیبیابی Docker بررسی کنید.
WARNING: sun.reflect.Reflection.getCallerClass پشتیبانی نمیشود
نگران آن نباشید.
WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
اگر خطای بالا را میبینید، آن را نادیده بگیرید. متابیس شما کاملاً سالم است و طبق انتظار عمل میکند.