رفع مشکل

رم سرور پر شده / OOM Killer؛ پیدا کردن عامل و رفع

تهیه: کلودیفای (نگارش با کمک هوش مصنوعی) · انتشار: · زمان مطالعه: ۴ دقیقه

RAMCPUOOMKillerرفع مشکلرم سرور پر شده / OOMKiller؛ پیدا کردن عامل ورفعمجلهٔ کلودیفایclodify.net/blog
پاسخ کوتاه

وقتی رم سرور لینوکس تمام می‌شود، کرنل با OOM Killer یکی از پروسه‌ها (اغلب دیتابیس یا برنامهٔ اصلی) را می‌کشد و سایت با خطای 502 یا قطعی روبه‌رو می‌شود. ابتدا با free -h و htop مصرف را ببینید، با dmesg رخداد OOM را تأیید کنید، پروسهٔ پرمصرف را پیدا و محدود کنید، یک swap کوچک بسازید و اگر مصرف واقعی بیشتر از رم است، پلن بزرگ‌تر بسازید.

نشانه‌ها

  • سایت یا سرویس ناگهان قطع می‌شود و پس از ری‌استارت درست می‌شود.
  • در لاگ Nginx خطای 502 یا connection refused به پروسهٔ پشتی دیده می‌شود.
  • دیتابیس (MySQL/PostgreSQL) بی‌دلیل متوقف شده است.
  • SSH بسیار کند است یا گاهی وصل نمی‌شود.

گام ۱: وضعیت فعلی رم

free -h

نمونه:

               total        used        free      shared  buff/cache   available
Mem:           1.9Gi       1.6Gi        80Mi        20Mi       250Mi       150Mi
Swap:             0B          0B          0B
  • ستون available مهم است، نه free. لینوکس رم آزاد را برای کش دیسک (buff/cache) استفاده می‌کند و در صورت نیاز آزاد می‌کند.
  • available زیر ۱۰ درصد کل و Swap صفر = خطر OOM.

گام ۲: تأیید OOM Killer

sudo dmesg -T | grep -iE "out of memory|killed process" | tail
sudo journalctl -k --since "24 hours ago" | grep -i oom

خروجی مانند Out of memory: Killed process 1234 (mysqld) یعنی کرنل همان پروسه را به‌خاطر کمبود رم کشته است.

root@server: ~
$ dmesg -T | grep -i 'killed process'Out of memory: Killed process 1234 (python3)$ journalctl -k | grep -i oom$ 
شکل ۱ اگر این پیام را می‌بینید، کرنل برای نجات سیستم یک پروسه را بسته است.

گام ۳: پیدا کردن پروسه‌های پرمصرف

# ۱۵ پروسهٔ پرمصرف بر اساس رم
ps aux --sort=-%mem | head -15

# مجموع مصرف بر اساس نام برنامه (مثلاً همهٔ php-fpm ها)
ps -eo comm,rss --sort=-rss | awk '{a[$1]+=$2} END {for (i in a) printf "%-20s %6.0f MB\n", i, a[i]/1024}' | sort -k2 -nr | head

# در داکر
docker stats --no-stream

گام ۴: ساخت swap (کمک اضطراری)

swap فضایی روی دیسک است که وقتی رم پر شود استفاده می‌شود. کندتر از رم است، اما جلوی کشته شدن ناگهانی پروسه‌ها را می‌گیرد:

sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# استفادهٔ محافظه‌کارانه از swap
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swap.conf
sudo sysctl --system

برای سرورهای ۱ تا ۲ گیگ رم، swap یک تا دو گیگ مناسب است. اگر swap مدام پر است، رم واقعاً کم است.

root@server: ~
$ sudo fallocate -l 2G /swapfile$ sudo chmod 600 /swapfile$ sudo mkswap /swapfile && sudo swapon /swapfile$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab$ 
شکل ۲ ساخت swap دو گیگابایتی؛ swap کندتر از رم است و فقط جلوی کرش ناگهانی را می‌گیرد.

گام ۵: محدود کردن برنامه‌های پرمصرف

MySQL / MariaDB

مهم‌ترین تنظیم، innodb_buffer_pool_size است. روی سرورهایی که دیتابیس و وب‌سرور با هم اجرا می‌شوند، حدود ۲۵ تا ۴۰ درصد رم کافی است:

# /etc/mysql/mariadb.conf.d/60-tuning.cnf  (مسیر بسته به نسخه)
[mysqld]
innodb_buffer_pool_size = 512M
max_connections = 50

PHP-FPM

هر پروسهٔ PHP-FPM معمولاً ده‌ها مگابایت رم می‌گیرد. pm.max_children را بر اساس رم آزاد تقسیم بر مصرف هر پروسه تنظیم کنید:

; /etc/php/8.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4

Node.js و Python

  • تعداد worker ها (PM2 cluster، Gunicorn workers) را با رم هماهنگ کنید.
  • نشت حافظه (Memory leak) را با پایش مصرف در طول زمان تشخیص دهید؛ اگر مصرف مدام بالا می‌رود و پایین نمی‌آید، نشت وجود دارد.

داکر

برای هر کانتینر سقف رم بگذارید تا یک کانتینر کل سرور را از کار نیندازد:

services:
  app:
    image: myapp
    mem_limit: 512m

گام ۶: ری‌استارت خودکار سرویس‌ها

حتی با تنظیمات درست، بهتر است سرویس‌ها پس از کرش خودکار بالا بیایند:

sudo systemctl edit mariadb
[Service]
Restart=on-failure
RestartSec=5

در داکر از restart: unless-stopped استفاده کنید.

کی پلن بزرگ‌تر لازم است؟

اگر پس از بهینه‌سازی‌ها همچنان available در ساعات عادی زیر ۱۵ درصد است یا swap به‌طور پیوسته استفاده می‌شود، رم واقعاً کم است. جدول انتخاب رم و پردازنده کمک می‌کند پلن مناسب را انتخاب کنید. با صورتحساب ساعتی، سرور بزرگ‌تر را بسازید، داده‌ها را منتقل و سرور قبلی را حذف کنید.

پلنپردازندهرمدیسکساعتی (تومان)ماهانه تقریبی (تومان)
IR-۱۱ هسته۱ گیگابایت۱۰ گیگابایت۱٬۲۰۰۸۷۶٬۰۰۰ساخت
IR-۲۲ هسته۲ گیگابایت۱۵ گیگابایت۲٬۱۰۰۱٬۵۳۳٬۰۰۰ساخت
IR-۳۲ هسته۴ گیگابایت۲۰ گیگابایت۳٬۰۰۰۲٬۱۹۰٬۰۰۰ساخت
IR-۴۴ هسته۴ گیگابایت۳۰ گیگابایت۴٬۲۰۰۳٬۰۶۶٬۰۰۰ساخت
IR-۵۴ هسته۸ گیگابایت۵۰ گیگابایت۶٬۵۰۰۴٬۷۴۵٬۰۰۰ساخت
IR-۶۸ هسته۱۶ گیگابایت۱۰۰ گیگابایت۱۲٬۹۰۰۹٬۴۱۷٬۰۰۰ساخت

قیمت‌ها زنده از سامانهٔ کلودیفای در تاریخ ۱۱ آبان ۱۴۰۵ خوانده شده‌اند. ترافیک دانلود جداگانه، هر گیگابایت ۱٬۲۵۰ تومان؛ آپلود رایگان.

سؤالات متداول

چرا لینوکس رم را «پر» نشان می‌دهد در حالی که مشکلی نیست؟

لینوکس رم آزاد را برای کش دیسک استفاده می‌کند. ستون available نشان می‌دهد واقعاً چقدر رم برای برنامه‌ها در دسترس است.

swap روی SSD به دیسک آسیب می‌زند؟

با swappiness پایین و استفادهٔ گاه‌به‌گاه، اثر قابل‌توجهی ندارد. swap دائماً پر نشانهٔ کمبود رم است، نه راه‌حل.

OOM Killer کدام پروسه را می‌کشد؟

معمولاً پروسه‌ای که بیشترین رم را دارد (امتیاز oom_score بالاتر)؛ به همین دلیل اغلب دیتابیس قربانی می‌شود.

می‌توانم از کشته شدن یک پروسهٔ مهم جلوگیری کنم؟

با OOMScoreAdjust=-500 در سرویس systemd می‌توانید احتمال آن را کم کنید، اما بهتر است علت کمبود رم را رفع کنید.

آماده‌اید؟ سرورتان را بسازید.

از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی

سرورتان را همین حالا بسازید.

ساعتی بپردازید. هر وقت خواستید حذف کنید.