SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor

آیا VPS به swap نیاز دارد؟ راهنمای تنظیم و اندازه

بیشتر ایمیج‌های ابری بدون swap هستند. در این مقاله می‌آموزید چه زمانی به swap نیاز دارید، چگونه اندازه آن را تعیین کنید، vm.swappiness را تنظیم کرده و از zram استفاده کنید.

آیا VPS شما به swap نیاز دارد؟

بیشتر ایمیج‌های ابری بدون swap عرضه می‌شوند و در یک VPS کوچک، پاسخ معمولاً مثبت است؛ یک فایل swap اضافه کنید. swap باعث نمی‌شود یک سرور 1 GB مانند یک سرور 2 GB عمل کند. swap به هسته (kernel) فضایی می‌دهد تا صفحات حافظهٔ غیرفعال (cold anonymous pages) را در آن قرار دهد؛ این کار باعث می‌شود page cache مفید باقی بماند و OOM killer (روال هسته که برای آزاد کردن حافظه، یک پردازش را انتخاب و آن را متوقف می‌کند) به آخرین راهکار تبدیل شود، نه اولین راهکار.

خلاصه اینکه: در سروری که چند سرویس با طول عمر بالا را اجرا می‌کند، یک فایل swap کوچک ارزش فضای دیسکی که اشغال می‌کند را دارد. در سروری که یک پردازش به‌طور مرتب سعی می‌کند بیش از کل حافظهٔ دستگاه را تخصیص دهد، swap شما را نجات نخواهد داد و فقط باعث می‌شود شکستِ برنامه کندتر رخ دهد و تشخیص آن دشوارتر شود. باقی این راهنما دربارهٔ نحوهٔ تشخیص این دو وضعیت و دو هزینه‌ای است که فقط در VPS ظاهر می‌شوند.

هر دستوری که در ادامه می‌آید نیاز به دسترسی root روی سرور خودتان دارد، بنابراین آن‌ها را در سرور خود اجرا کنید و خروجی دستگاه دیگران را کپی نکنید.

عملکرد واقعی swap و آنچه انجام نمی‌دهد

حافظه در Linux به دو نوع تقسیم می‌شود. صفحات مبتنی بر فایل (File backed pages)، کپی‌هایی از مواردی هستند که از قبل روی دیسک وجود دارند: برنامه‌های شما و هر فایلی که اخیراً خوانده‌اید. این مجموعه، page cache نامیده می‌شود. صفحات ناشناس (Anonymous pages)، حافظه‌ای هستند که هیچ فایلی در پشت آن‌ها نیست: heap و stack، به‌علاوه بخش عمده‌ای از آنچه یک دیتابیس در زمان اجرا تخصیص می‌دهد.

هنگامی که حافظه کم می‌آید، هسته (kernel) باید صفحات را بازیابی کند. بازیابی یک صفحه مبتنی بر فایلِ تمیز (clean)، کم‌هزینه است، زیرا کپی آن روی دیسک موجود است و صفحه می‌تواند بعداً دوباره خوانده شود. اما یک صفحه ناشناس این‌طور نیست، زیرا تنها کپی آن در RAM قرار دارد. بدون swap، هسته برای حافظه ناشناس دو انتخاب دارد: آن را نگه دارد یا فرآیندی که مالک آن است را بکشد (kill کند).

سروری که swap ندارد همچنان paging انجام می‌دهد. فقط حافظه اشتباه را paging می‌کند. تحت فشار، هسته page cache را کوچک می‌کند و صفحات فایلی را که به‌زودی دوباره به آن‌ها نیاز خواهد داشت، بیرون می‌راند؛ از جمله کدهای اجرایی برنامه‌هایی که در حال اجرا هستند. آن صفحات به صورت major page faults بازمی‌گردند. شما خواندن دیسک را در ستون bi از vmstat و افزایش شمارنده pgmajfault در /proc/vmstat مشاهده می‌کنید، در حالی که si و so در تمام مدت روی صفر باقی می‌مانند. سیستم در حال thrashing است و شمارنده‌های swap هیچ چیزی را گزارش نمی‌کنند.

آنچه swap انجام نمی‌دهد، افزایش ظرفیت است. اگر working set، یعنی صفحاتی که واقعاً در حال استفاده هستند، بزرگ‌تر از RAM باشد، swap یک خطای out of memory را به یک سرور بسیار کند تبدیل می‌کند. گاهی اوقات این همان معامله‌ای است که می‌خواهید، زیرا می‌توان به یک سرور کند وارد شد و آن را تعمیر کرد، در حالی که یک دیتابیسِ کشته‌شده (killed) قابل تعمیر نیست. گاهی اوقات این وضعیت بدتر است، زیرا یک سرور کند در حالی که تمام اتصالات را باز نگه داشته، مدام در health checkها شکست می‌خورد. پیش از افزودن swap، تصمیم بگیرید که کدام حالت را ترجیح می‌دهید.

چرا ایمیج‌های ابری بدون swap عرضه می‌شوند؟

این یک انتخاب آگاهانه است. یک ایمیج باید روی تمام پلن‌هایی که یک ارائه‌دهنده می‌فروشد بوت شود؛ بنابراین یک پارتیشن swap ثابت، فضای دیسک را در پلن‌های کوچک هدر می‌دهد و در پلن‌های بزرگ نیز بی‌فایده است. سرعت swap همچنین به فضای ذخیره‌سازی زیرمجموعه guest بستگی دارد که ایمیج نمی‌تواند از قبل از آن آگاه باشد. علاوه بر این، سازندگان ایمیج برای رفتارهای قابل پیش‌بینی بهینه‌سازی می‌کنند، زیرا تشخیص علت مرگ یک پردازش که بلافاصله متوقف می‌شود، در میان مجموعه‌ای از سرورها آسان‌تر از ماشینی است که روشن می‌ماند اما به هر درخواست با چند ثانیه تأخیر پاسخ می‌دهد.

این دلایل برای ماشین‌های یک‌بارمصرف (disposable) صادق است. یک VPS که آن را نگه می‌دارید، موضوع متفاوتی است. شما آن را به جای جایگزینی، تعمیر می‌کنید؛ بنابراین چند ثانیه paging معمولاً بهتر از متوقف شدن یک سرویس است. نبود swap را به عنوان یک تنظیم پیش‌فرض در نظر بگیرید که برای مورد استفادهٔ شخص دیگری ساخته شده است.

آیا در VPS از swap file استفاده کنیم یا swap partition؟

از یک فایل استفاده کنید. استفاده از پارتیشن به معنای تغییر اندازه فایل‌سیستم ریشه (root) در یک دیسک است که از قبل پارتیشن‌بندی شده است؛ این کار ریسک بالایی دارد و هیچ مزیت عملی به همراه ندارد. فایل را می‌توان با دستورات معمولی ایجاد یا حذف کرد و می‌توانید بدون دستکاری جدول پارتیشن، اندازه آن را در آینده تغییر دهید.

سرعت، عامل تعیین‌کننده نیست. در زمان swapon، هسته سیستم‌عامل نقشه extent فایل را یک‌بار می‌خواند و سپس عملیات I/O را مستقیماً به بلاک‌دیوایس می‌فرستد؛ بنابراین فایل‌سیستم در هر عملیات page in و page out در مسیر قرار نمی‌گیرد. روی یک دیسک واحد، عملکرد swap file و swap partition یکسان است.

دو محدودیت وجود دارد که باید از آن‌ها آگاه باشید. swap را روی فایل‌سیستم‌های تحت شبکه مانند NFS (network file system) قرار ندهید. همچنین در btrfs، قابلیت copy on write و فشرده‌سازی (compression) فایل باید غیرفعال باشد؛ به همین دلیل است که btrfs ابزار کمکی اختصاصی خود را برای ایجاد swap file ارائه می‌دهد.

نحوه افزودن یک فایل swap در Ubuntu یا Debian

پیش از اعمال هرگونه تغییر، وضعیت فعلی را بررسی کنید.

swapon --show
free -h
findmnt -no FSTYPE /

خروجی خالی از swapon --show به این معناست که هیچ swap فعالی وجود ندارد؛ این وضعیت عادی برای یک image ابری تازه است. دستور findmnt نوع فایل‌سیستم ریشه را نمایش می‌دهد که تعیین‌کننده نحوه ایجاد فایل است. در ext4، که اکثر imageهای ابری از آن استفاده می‌کنند، استفاده از fallocate ایمن است.

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

دستور chmod عمداً پیش از mkswap قرار گرفته است. اگر آن را نادیده بگیرید، mkswap با خطای mkswap: /swapfile: insecure permissions 0644, fix with: chmod 0600 /swapfile به شما هشدار می‌دهد. یک فایل swap با دسترسی خواندن عمومی، حافظه‌ای که سایر پردازش‌ها به آن منتقل (page out) شده‌اند را در اختیار تمام کاربران سیستم قرار می‌دهد. یک دستور mkswap سالم، اندازه فایل را با خطی مشابه Setting up swapspace version 1, size = 2 GiB (2147479552 bytes) تأیید می‌کند.

در xfs یا btrfs، دستور آخر ممکن است با خطای swapon: /swapfile: swapon failed: Invalid argument شکست بخورد. در XFS این اتفاق به این دلیل رخ می‌دهد که fallocate بخش‌های نوشته‌نشده (unwritten extents) باقی می‌گذارد؛ بنابراین به جای آن، بایت‌ها را مستقیماً بنویسید.

sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress

در btrfs علت این موضوع قابلیت copy on write است و btrfs-progs فعلی، فلگ‌های صحیح را برای شما تنظیم می‌کند.

sudo btrfs filesystem mkswapfile --size 2g /swapfile

در هر صورت، کار را با chmod 600، اجرای mkswap در صورت نیاز، و سپس swapon به پایان برسانید و نتیجه را تأیید کنید.

swapon --show
free -h

دستور swapon --show باید /swapfile را با نوع file و اندازه درخواستی شما لیست کند، و free -h باید یک ردیف Swap را نشان دهد که تقریباً هیچ استفاده‌ای از آن نشده است. صفر بودن میزان استفاده از swap در یک تنظیمات تازه، صحیح است. هسته سیستم‌عامل تنها زمانی صفحات را به آنجا منتقل می‌کند که دلیل موجهی داشته باشد.

برای ماندگاری پس از reboot، ورودی را اضافه کرده و بلافاصله آن را تست کنید.

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo swapoff /swapfile
sudo swapon -a
swapon --show

دستور swapon -a فایل /etc/fstab را می‌خواند، بنابراین اگر خطی اشتباه باشد، همان لحظه با خطا مواجه می‌شوید. یک غلط تایپی که تست نشود، در زمان reboot ناخواسته خود را نشان می‌دهد؛ یعنی زمانی که سیستم بالا می‌آید اما swap مورد انتظار شما فعال نیست.

برای حذف swap در آینده، دستور sudo swapoff /swapfile را اجرا کنید، خط مربوطه را از fstab حذف کرده و سپس sudo rm /swapfile را انجام دهید. دستور swapoff باید ابتدا تمام صفحات منتقل‌شده را به RAM بازگرداند، بنابراین در یک سیستم پرمشغله ممکن است با خطای swapoff: /swapfile: swapoff failed: Cannot allocate memory مواجه شود. مقداری از حافظه را آزاد کرده و دوباره تلاش کنید.

اندازه فایل swap چقدر باید باشد؟

وظیفه این فایل نگهداری صفحات anonymous سرد است، بنابراین آنچه اهمیت دارد میزان حافظه‌ای است که واقعاً بلااستفاده مانده است، نه مقدار کل RAM موجود در پلن. حافظه بلااستفاده همگام با افزایش اندازه پلن رشد نمی‌کند، بنابراین با بزرگ‌تر شدن پلن‌ها، ضریب آن کاهش می‌یابد. این همان قاعده‌ای است که در این راهنما استفاده شده است.

ChartSwap file size this guide sets, by plan RAM
The data behind this chart
[
  {
    "label": "1 GB plan",
    "swap_gb": 2,
    "swap_x_ram": 2
  },
  {
    "label": "2 GB plan",
    "swap_gb": 2,
    "swap_x_ram": 1
  },
  {
    "label": "4 GB plan",
    "swap_gb": 2,
    "swap_x_ram": 0.5
  },
  {
    "label": "8 GB plan",
    "swap_gb": 4,
    "swap_x_ram": 0.5
  },
  {
    "label": "16 GB plan",
    "swap_gb": 4,
    "swap_x_ram": 0.25
  }
]

در کوچک‌ترین پلن، اندازه swap برابر با 2 GB است که 2 برابر RAM محسوب می‌شود، زیرا یک سرور 1 GB فضای خالی بسیار کمی دارد و یک جهش ناگهانی در مصرف حافظه باعث فعال شدن OOM killer می‌شود. در بالاترین سطح جدول، اندازه فایل به 4 GB یا 0.25 برابر RAM محدود می‌شود، زیرا انتقال (paging) این حجم از داده روی حافظه اشتراکی آن‌قدر طول می‌کشد که سرور در حین انجام آن عملاً از دسترس خارج می‌شود. اگر محدودیت فضای دیسک دارید، این اعداد را کاهش دهید، زیرا این فایل فضای واقعی دیسک را اشغال می‌کند.

تنها دلیل کلاسیک برای تعیین اندازه swap برابر یا بیشتر از RAM، قابلیت hibernation است که کل تصویر حافظه را در swap می‌نویسد. یک VPS قابلیت hibernation ندارد، بنابراین این قاعده برای شما صدق نمی‌کند.

پارامتر vm.swappiness دقیقاً چه چیزی را تغییر می‌دهد؟

vm.swappiness یک درصد از RAM نیست و یک آستانه (threshold) نیز محسوب نمی‌شود. این پارامتر نشان‌دهنده هزینه نسبی است که هسته (kernel) برای بازپس‌گیری صفحات ناشناس (anonymous pages) در مقایسه با صفحات فایل (file pages) در نظر می‌گیرد. مقدار پیش‌فرض آن 60 است. با کاهش این مقدار، هسته ترجیح می‌دهد page cache را حذف کند. با افزایش آن، هسته ترجیح می‌دهد حافظه ناشناس را به swap منتقل کند.

این یک مبادله در هر دو جهت است. در vm.swappiness = 10، یک دیتابیس بخش بیشتری از تخصیص‌های خود را در حافظه اصلی نگه می‌دارد و هزینه آن را با خواندن مجدد فایل‌هایی که به‌تازگی از cache حذف کرده است، می‌پردازد. در سیستمی که وظیفه اصلی آن سرویس‌دهی فایل است، این رویکرد اشتباه است، زیرا در آنجا page cache کار مفید را انجام می‌دهد.

تنظیم آن روی 0 به معنای غیرفعال کردن swap نیست. این مقدار به هسته می‌گوید که از بازپس‌گیری حافظه ناشناس تا زمانی که حافظه تقریباً تمام نشده است خودداری کند، که این کار باعث می‌شود OOM killer زودتر وارد عمل شود تا اینکه آن را به تأخیر بیندازد. اگر می‌خواهید swap نداشته باشید، فایل swap را حذف کنید.

sysctl vm.swappiness
printf 'vm.swappiness = 10\n' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system
sysctl vm.swappiness

یک sysctl -w ساده فقط تا reboot بعدی باقی می‌ماند و پس از آن دیگر اعمال نمی‌شود، بنابراین فایل را در مسیر /etc/sysctl.d/ بنویسید. هسته‌های نسخه 5.8 به بعد، مقادیر 0 تا 200 را می‌پذیرند. مقادیر بالای 100 تنها زمانی منطقی هستند که سرعت swap تقریباً با سرعت RAM برابر باشد، که این وضعیت در مورد zram صدق می‌کند.

zram: حافظه swap که به جای دیسک، از CPU استفاده می‌کند

zram یک بلاک‌دیوایس فشرده است که در RAM قرار دارد. از آن به عنوان swap استفاده کنید تا صفحاتی که قرار بود به دیسک منتقل شوند، فشرده شده و در حافظه باقی بمانند. در این حالت هیچ I/O دیسکی وجود ندارد و سهمیه دیسک نیز مصرف نمی‌شود. هزینه این کار، مصرف زمان CPU برای هر عملیات page in و page out، به‌علاوه اشغال بخشی از RAM توسط صفحات فشرده است که دیگر در دسترس برنامه‌های شما نخواهد بود.

نسبت‌های فشرده‌سازی بین 2:1 تا 3:1 معمولاً برای صفحات ناشناس (anonymous pages) گزارش می‌شوند. عدد دقیق مربوط به سیستم خود را می‌توانید توسط zramctl در ستون‌های DATA و COMPR مشاهده کنید. به‌جای برنامه‌ریزی بر اساس اعداد معمول، اندازه‌گیری کنید؛ زیرا برخی از بارهای کاری حاوی داده‌هایی هستند که به‌سختی فشرده می‌شوند.

sudo apt install zram-tools

مقادیر ALGO=zstd و PERCENT=25 را در /etc/default/zramswap تنظیم کنید، سپس سرویس را ری‌استارت کرده و نتیجه را بررسی کنید.

sudo systemctl restart zramswap
zramctl
swapon --show

PERCENT درصدی از کل RAM است؛ بنابراین عدد 25 روی یک سیستم 4 گیگابایتی، تا 1 گیگابایت را برای صفحات فشرده رزرو می‌کند. با مقادیر کم شروع کنید و تنها در صورتی که zramctl نشان داد دیوایس در حال پر شدن است، آن را افزایش دهید. تنظیم PRIORITY در همان فایل تعیین می‌کند که هسته سیستم‌عامل ابتدا کدام swap را پر کند: اولویت بالاتر برنده است. یک فایل swap دیسکی که با دستور معمولی swapon اضافه شده باشد، اولویت منفی دریافت می‌کند؛ بنابراین zram ابتدا استفاده می‌شود و فایل swap سرریز را می‌گیرد. swapon --show هر دو مقدار را در ستون PRIO نمایش می‌دهد. در توزیع‌هایی که به‌جای zram-tools از systemd-zram-generator استفاده می‌کنند، تنظیمات مشابه در /etc/systemd/zram-generator.conf قرار دارند.

zram برای سیستمی که توان پردازشی (CPU) مازاد دارد و فضای دیسک آن کم است، مناسب است. اگر منبعی که با کمبود آن مواجه هستید CPU است، این انتخاب اشتباهی است؛ زیرا عملیات فشرده‌سازی برای تصاحب همان سهم پردازشی با برنامه‌های شما رقابت می‌کند.

دو دام در استفاده از swap که فقط در VPS گریبان‌گیر شما می‌شوند

دام اول مربوط به دیسک است. یک فایل swap با حجم 2 GB، بلافاصله پس از ایجاد، 2 GB از فضای دیسک پلن شما را اشغال می‌کند، زیرا این فضا باید از قبل تخصیص داده شود. df -h / بلافاصله به همان میزان کاهش می‌یابد و تا زمانی که فایل را حذف نکنید، بازیابی نمی‌شود. در پلن‌های کوچک، این مقدار بخش قابل‌توجهی از فضا است و پر شدن کامل فایل‌سیستم root، مشکلات بسیار بیشتری نسبت به مزایای swap ایجاد می‌کند. این فایل در خروجی du نیز محاسبه می‌شود؛ نکته‌ای که هنگام جستجو برای یافتن فضای خالی و زمانی که df و du در مورد محل مصرف دیسک اختلاف دارند، باید به خاطر داشته باشید.

دام دوم مربوط به تأخیر (latency) است. عملیات I/O مربوط به swap شما به حافظه‌ای ارسال می‌شود که میزبان (host) آن را با سایر مهمان‌ها (guests) به اشتراک گذاشته است و شما از داخل سیستم‌عامل خود، بار کاری آن‌ها را نمی‌بینید. شما فقط اثر آن را مشاهده می‌کنید: فرایند page-in که معمولاً سریع انجام می‌شود، گاهی بسیار طولانی‌تر می‌شود و فرایندی که منتظر آن است تا زمان رسیدن صفحه متوقف می‌ماند. این همان استدلالی است که در مورد زمان CPU steal در یک میزبان اشتراکی به کار می‌رود، با این تفاوت که اینجا به جای صف اجرا (run queue)، صف دیسک (disk queue) درگیر است. این تأخیر را روی سرور خودتان اندازه‌گیری کنید، زیرا هر عدد تأخیری که منتشر شده باشد، مربوط به همسایگانِ شخص دیگری است.

چگونه متوجه شویم که استفاده از swap به عملکرد سیستم آسیب می‌زند؟

استفاده از swap به خودی خود مشکل‌ساز نیست، بلکه ترافیک swap است که اهمیت دارد. سروری که چند صد مگابایت داده در swap دارد اما فعالیت paging در آن دیده نمی‌شود، صرفاً حافظه‌ای را که ساعت‌ها مورد استفاده قرار نگرفته به آنجا منتقل کرده است و این همان نتیجه‌ای است که انتظار داشتید.

به جای مقادیر کل، نرخ‌ها را زیر نظر بگیرید.

vmstat 1 5

si و so نشان‌دهنده میزان داده‌های swap شده (ورودی و خروجی) بر حسب کیلوبایت در ثانیه هستند. در یک سیستم سالم، این مقادیر فارغ از عددی که در ستون swpd نمایش داده می‌شود، باید نزدیک به صفر باقی بمانند. تداوم so همزمان با افزایش si به این معناست که صفحات حافظه مدام در حال نوشتن و بلافاصله فراخوانی مجدد هستند؛ این وضعیت thrashing نام دارد.

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  3 1048572  38210   4096  61440  912 1180  2210  1290 1402 2890  9  7 12 72  0

نمونه فوق سیستمی را نشان می‌دهد که دچار مشکل شده است و واضح‌ترین نشانه آن در ستون‌های swap نیست. این نشانه wa با مقدار 72 است که یعنی پردازنده بیشتر وقت خود را در انتظار I/O سپری کرده و b با مقدار 3 که یعنی سه پردازش مسدود شده‌اند.

اطلاعات فشار یا PSI (Pressure Stall Information) پاسخ مستقیم‌تری به این پرسش می‌دهد.

cat /proc/pressure/memory
some avg10=8.42 avg60=5.11 avg300=2.03 total=1284729
full avg10=3.10 avg60=1.94 avg300=0.71 total=498210

some avg10=8.42 به این معناست که در 10 ثانیه گذشته، حداقل یک وظیفه (task) به مدت 8.42 درصد از زمان، به دلیل انتظار برای حافظه متوقف شده است. full زمانی را محاسبه می‌کند که تمام وظایف غیرفعال (non-idle) متوقف شده‌اند؛ بنابراین مقدار پایدار در full به معنای آسیب قابل‌اندازه‌گیری است، نه صرفاً یک هشدار. اگر این فایل وجود ندارد، یعنی هسته سیستم شما PSI را به‌طور پیش‌فرض غیرفعال کرده است و نیاز به افزودن psi=1 به خط فرمان هسته (kernel command line) دارید.

برای مشاهده اینکه کدام پردازش‌ها صفحاتی را در swap نگه داشته‌اند:

sudo awk '/^Name:/{n=$2} /^VmSwap:/ && $2+0 > 0 {printf "%10d kB  %s\n", $2, n}' /proc/[0-9]*/status | sort -rn | head

و برای اینکه بفهمید آیا OOM killer قبلاً وارد عمل شده است یا خیر:

sudo journalctl -k --grep "Out of memory"

یک مورد شناسایی‌شده به شکل Out of memory: Killed process 2199 (mysqld) total-vm:1275860kB, anon-rss:129252kB, file-rss:0kB, shmem-rss:0kB, UID:114 pgtables:504kB oom_score_adj:0 نمایش داده می‌شود و لاگ سرویس در همان ثانیه عبارت Main process exited, code=killed, status=9/KILL را ثبت می‌کند. اگر این خطوط را در سیستمی بدون swap مشاهده کردید، افزودن یک swap file ارزان‌ترین راهکاری است که می‌توانید امتحان کنید.

زمانی که swap راه‌حل اشتباهی است

حافظه swap برای فشارهای مقطعی یا داده‌های غیرفعال (cold) زمان می‌خرد. این حافظه برای فرآیندی که تا لحظه مرگ رشد می‌کند هیچ فایده‌ای ندارد و باعث می‌شود تشخیص آن شکست دشوارتر شود، زیرا سیستم به جای شکست سریع و راه‌اندازی مجدد، دقایق اضافی را صرف paging می‌کند.

به جای آن، برای فرآیند محدودیت (Cap) تعیین کنید. یک سرویس systemd در یک فایل drop-in، پارامترهای MemoryMax= و MemorySwapMax= را می‌پذیرد؛ این همان روشی است که می‌توانید حافظه و CPU را برای یک سرویس با systemd محدود کنید بدون اینکه نیاز باشد تغییری در خود برنامه ایجاد کنید. کانتینرها نیز در یک سطح بالاتر همین کنترل‌ها را دارند و تنظیم آن‌ها روشی است که از مصرف کل منابع سرور توسط یک سرویس Compose جلوگیری می‌کند. هر دو روش باعث می‌شوند فرآیند با یک نام مشخص در لاگ‌ها متوقف شود و شما بتوانید آن را پیدا کنید، به جای اینکه اجازه دهید هسته سیستم‌عامل (kernel) بر اساس امتیاز (score)، قربانی را انتخاب کند.

این کار را زمانی انجام دهید که سرور جدید و خلوت است. ایجاد فایل swap و تنظیم یک محدودیت حافظه تنها چند دقیقه زمان می‌برد و این کار بخشی از وظایفی است که باید در ده دقیقه اول راه‌اندازی یک VPS جدید انجام شود.

FAQ

آیا افزودن swap باعث می‌شود یک VPS با 1 GB رم، مانند یک VPS با 2 GB رم عمل کند؟

خیر. سرعت swap بسیار کمتر از RAM است و هسته سیستم‌عامل (kernel) فقط صفحاتی را به آن منتقل می‌کند که آن‌ها را «سرد» (کم‌استفاده) تشخیص دهد. swap در واقع فضایی برای مدیریت پیک‌های مصرف و نگهداری حافظه‌ای است که تخصیص یافته اما استفاده نمی‌شود. اگر حجم کاری شما به‌طور فعال بیشتر از RAM موجود، حافظه بخواند و بنویسد، swap باعث می‌شود به‌جای دریافت خطای Out of Memory، سیستم دچار paging مداوم شود؛ در این حالت سرور روشن می‌ماند اما آن‌قدر کند پاسخ می‌دهد که عملاً غیرقابل استفاده است. در چنین شرایطی، RAM را افزایش دهید یا محدودیت مصرف برای پردازش مربوطه تعیین کنید.

یک VPS با 1 GB یا 2 GB رم به چه مقدار swap نیاز دارد؟

2 GB برای هر دو کافی است و پس از آن نیازی نیست با افزایش RAM، مقدار swap را هم افزایش دهید. swap صفحات ناشناس (anonymous pages) سرد را نگه می‌دارد و مقدار حافظه واقعاً سرد در یک سرور، با افزایش کل RAM رشد نمی‌کند. قانون قدیمیِ «دو برابر RAM» مربوط به قابلیت hibernation است که کل تصویر حافظه را روی دیسک می‌نویسد، در حالی که یک VPS هرگز hibernate نمی‌شود. تعیین swap بیش از 4 GB، عمدتاً باعث می‌شود در صورت بروز مشکل، سیستم برای مدت طولانی‌تری روی فضای ذخیره‌سازی مشترک با سایر کاربران کند شود.

آیا تنظیم vm.swappiness روی 0 راه درستی برای متوقف کردن swap است؟

خیر، و این کار دقیقاً آن چیزی نیست که از نامش برداشت می‌شود. vm.swappiness = 0 قابلیت swap را غیرفعال نمی‌کند. این تنظیم به هسته می‌گوید تا زمانی که حافظه تقریباً تمام نشده، از بازپس‌گیری صفحات ناشناس خودداری کند؛ این کار احتمال وقوع OOM kill را افزایش می‌دهد، نه کاهش. همچنین تمام فشار بازپس‌گیری را به page cache منتقل می‌کند که باعث می‌شود خواندن فایل‌ها بیشتر از دیسک انجام شود. اگر اصلاً swap نمی‌خواهید، دستور sudo swapoff -a را اجرا کرده و خط مربوطه را از fstab حذف کنید. اگر می‌خواهید میزان swap کمتر شود، vm.swappiness = 10 را امتحان کنید و ستون‌های si و so را در خروجی vmstat قبل و بعد از تغییر مقایسه کنید.

آیا باید به‌جای swap file از zram استفاده کنم؟

زمانی که توان پردازشی (CPU) کافی دارید و فضای دیسک محدود است از zram استفاده کنید، و زمانی که شرایط برعکس است، swap file را به کار بگیرید. zram صفحات را فشرده کرده و در RAM نگه می‌دارد، بنابراین از I/O دیسک کاملاً جلوگیری می‌کند؛ البته این کار هزینه CPU برای هر عملیات ورود و خروج صفحه دارد و فضایی که اشغال می‌کند، همان RAM است که دیگر در دسترس برنامه‌ها نیست. در یک VPS با سهمیه CPU محدود، این هزینه روی منبعی تحمیل می‌شود که خودتان با کمبود آن مواجه هستید. استفاده از هر دو به‌صورت همزمان معمول است: با استفاده از PRIORITY در /etc/default/zramswap، اولویت بالاتری به zram بدهید و یک swap file روی دیسک برای سرریز (overflow) نگه دارید.

چرا با وجود اینکه دستور free حافظه آزاد را نشان می‌داد، OOM killer فعال شد؟

free وضعیت را در یک لحظه گزارش می‌دهد، در حالی که تخصیص حافظه در یک آن رخ می‌دهد. اگر پردازشی سریع‌تر از آنکه سیستم بتواند حافظه آزاد کند، درخواست یک بلوک بزرگ حافظه داشته باشد، کشته می‌شود؛ حتی اگر میانگین مصرف حافظه مناسب به نظر برسد. لاگ هسته را با sudo journalctl -k --grep "Out of memory" بخوانید؛ این دستور نام پردازش کشته‌شده و میزان حافظه اشغال‌شده (resident size) آن را در آن لحظه نشان می‌دهد. سپس بررسی کنید که آیا این توقف ناشی از محدودیت cgroup بوده یا کل سیستم؛ زیرا یک container یا یک unit در systemd که برای آن MemoryMax= تنظیم شده، در صورت رسیدن به محدودیت خود کشته می‌شود، حتی اگر میزبان (host) همچنان حافظه آزاد داشته باشد.

#swap#memory#oom#zram#linux-performance