سرور مجازی

هارد NVMe و رم DDR4 در سرور مجازی کجا سرعت را بیشتر می کنند؟

هارد NVMe روی دیتابیس، وردپرس و هر باری که خواندن و نوشتن کوچک زیادی دارد اثر محسوسی دارد، ولی رباتی که بیشتر وقتش منتظر شبکه است با آن سریع تر نمی شود. با fio، vmstat و iostat می توانید همین را روی سرور خودتان اندازه بگیرید.

نوشته تیم فنی پیکوهاستبه روزرسانی: ۲۳ شهریور ۱۴۰۵۱۵ دقیقه مطالعه

تفاوت SSD و هارد NVMe در رابط اتصال است

SSDهای SATA و NVMe هر دو معمولاً داده را روی حافظه فلش NAND نگه می دارند و فرقشان در مسیری است که درخواست از پردازنده تا درایو طی می کند. SSD با رابط SATA از پروتکل AHCI استفاده می کند که در دوره هاردهای مکانیکی طراحی شد. طبق مشخصات AHCI 1.3.1 اینتل، هر پورت یک فهرست فرمان با حداکثر ۳۲ خانه دارد و NCQ هم تا ۳۲ فرمان را در صف نگه می دارد. هارد NVMe مجموعه فرمانی دارد که برای ذخیره سازی روی PCI Express تعریف شده و درایو بدون کنترلر SATA مستقیم به باس PCIe وصل می شود.

مشخصات NVMe نسخه 1.4 تا ۶۵٬۵۳۵ صف I/O تعریف می کند که هر کدام تا ۶۵٬۵۳۵ فرمان در انتظار را نگه می دارد. کرنل لینوکس هم با لایه blk-mq برای هسته های پردازنده صف های جداگانه می سازد تا درخواست ها پشت یک قفل مشترک منتظر نمانند. در عمل وقتی چند پردازه هم زمان از دیسک می خوانند و روی آن می نویسند، سربار نرم افزاری هر عملیات کمتر است و درایو درخواست ها را موازی جواب می دهد.

سرعت خواندن ترتیبی SSDهای SATA امروزی به سقف رابط SATA نزدیک است و NVMe روی PCIe این محدودیت را ندارد. ولی در سرور، عدد خواندن ترتیبی کمتر از دو چیز دیگر اهمیت دارد: تاخیر هر عملیات کوچک و رفتار درایو وقتی درخواست های هم زمان زیاد می شوند.

IOPS، throughput و تاخیر را جدا بسنجید

سرعت دیسک را با سه عدد متفاوت می سنجند و بنچمارکی که یک عدد بزرگ نشان می دهد معمولاً فقط یکی از آنها را اندازه گرفته است:

  • IOPS تعداد عملیات خواندن یا نوشتنی است که دیسک در هر ثانیه تمام می کند. معمولاً با بلوک های ۴ کیلوبایتی و دسترسی تصادفی اندازه گرفته می شود و به رفتار دیتابیس و فایل های کوچک نزدیک است.
  • throughput حجم داده در هر ثانیه است، مثلاً مگابایت بر ثانیه. با بلوک های بزرگ و خواندن یا نوشتن ترتیبی اندازه گرفته می شود و به کپی فایل بزرگ، بکاپ و بازگردانی مربوط است.
  • تاخیر (latency) زمانی است که یک عملیات تا تمام شدن لازم دارد. میانگین آن کافی نیست و صدک های بالا مثل صدک ۹۹ را هم باید دید، چون کاربر همان کندی های گاه به گاه را حس می کند.

عدد IOPS در عمق صف بالا ممکن است خیلی بزرگ باشد، در حالی که بار واقعی سرور شما شاید هیچ وقت آن تعداد درخواست هم زمان نسازد. ستون aqu-sz در خروجی iostat میانگین طول صف دیسک را روی سرور خودتان نشان می دهد. تست fio را یک بار هم با عمق صفی نزدیک به همان عدد اجرا کنید تا نتیجه به بار واقعی نزدیک تر باشد.

کدام بارها تفاوت هارد NVMe را حس می کنند

هارد NVMe وقتی برنامه را سریع تر می کند که برنامه منتظر دیسک بماند؛ دیتابیسی که در رم جا نمی شود، وردپرس پرافزونه بدون کش، SQLite با نوشتن زیاد، build و بکاپ از این دسته اند. جزئیات هر کدام:

  • دیتابیس MySQL، MariaDB یا PostgreSQL وقتی داده های پرکاربرد در رم جا نمی شوند و کوئری ها باید از دیسک بخوانند. این دیتابیس ها هنگام ثبت تراکنش لاگ را روی دیسک همگام می کنند، پس به تاخیر نوشتن هم حساس اند.
  • وردپرس و ووکامرس با افزونه های زیاد. اگر کش صفحه و OPcache درست تنظیم نشده باشند، هر بازدید فایل های PHP زیادی را می خواند و کوئری های زیادی به دیتابیس می فرستد. برای اینکه ببینید کندی از کش است یا از کوئری ها، راهنمای افزایش سرعت ووکامرس را بخوانید.
  • ربات یا برنامه ای که با SQLite کار می کند و برای هر پیام یک تراکنش نوشتن جدا باز می کند. SQLite در تنظیم پیش فرض (synchronous=FULL) هر تراکنش را با همگام سازی روی دیسک تمام می کند، پس تعداد زیاد تراکنش کوچک مستقیماً به تاخیر نوشتن دیسک وابسته می شود.
  • کامپایل، composer install، npm install و ساخت ایمیج Docker که تعداد زیادی فایل کوچک می سازند و می خوانند.
  • بکاپ گیری و بازگردانی، به خصوص وقتی هم زمان با بار عادی سایت اجرا می شوند.

در وردپرس، وب سرور و لایه کش تعیین می کنند چه تعداد درخواست اصلاً به PHP و دیتابیس برسد. اگر بین وب سرورها مردد هستید، مقایسه لایت اسپید و آپاچی برای وردپرس را هم ببینید.

در این بارها هارد NVMe تفاوت کمی ایجاد می کند:

  • ربات تلگرامی که بیشتر وقتش منتظر پاسخ API تلگرام یا یک API دیگر است. زمان پاسخ این ربات ها را شبکه تعیین می کند و محل سرور از نوع دیسک مهم تر است؛ مقایسه لوکیشن ها در انتخاب سرور مجازی ایران یا خارج آمده است.
  • برنامه ای که داده هایش در رم جا می شود. لینوکس رم آزاد را برای کش فایل ها استفاده می کند (ستون buff/cache در خروجی free) و خواندن های تکراری بدون رفتن سراغ دیسک از همین کش جواب داده می شوند.
  • پراکسی، API سبک و سایت استاتیک کوچکی که بعد از چند درخواست اول بیشتر محتوا را از کش می خواند.

همسایه های پرمصرف و سقف I/O در سرور مجازی

در سرور مجازی سرعت دیسک علاوه بر نوع درایو به بار ماشین های دیگر روی همان میزبان و سقف I/O سرویس بستگی دارد. دیسک فیزیکی یا بین چند ماشین مجازی روی یک میزبان مشترک است، یا از یک سیستم ذخیره سازی شبکه ای می آید که چند میزبان از آن استفاده می کنند. اگر ماشین دیگری روی همان سخت افزار بکاپ بزرگی بگیرد یا دیتابیس سنگینی اجرا کند، صف درایوها پر می شود و تاخیر عملیات شما هم بالا می رود. به این وضعیت همسایه پرسروصدا (noisy neighbour) می گویند.

در KVM می شود برای دیسک هر ماشین مجازی سقف IOPS یا مگابایت بر ثانیه گذاشت. این سقف شما را در برابر همسایه ها محافظت می کند، ولی هر قدر هم درایو زیرین سریع باشد، سرور شما بیشتر از همان سقف نمی گیرد. پس برچسب هارد NVMe به تنها سرعت دیسک سرور مجازی را مشخص نمی کند و بهتر است سقف I/O سرویس را از ارائه دهنده بپرسید.

از داخل سرور هم نوع درایو معلوم نیست. در KVM دیسک معمولاً با درایور virtio به ماشین مجازی داده می شود و در خروجی lsblk با نامی مثل vda دیده می شود، هر درایوی که زیر آن باشد. برای همین اندازه بگیرید، یک بار در ساعت خلوت و یک بار در ساعت شلوغ. اگر تاخیر در این دو زمان خیلی فرق دارد، احتمالاً بار میزبان روی سرور شما اثر می گذارد.

مجازی سازی KVM چه چیزهایی را جدا می کند

KVM به هر سرور مجازی کرنل و سخت افزار مجازی مستقل می دهد، ولی پردازنده، دیسک و شبکه همچنان از منابع میزبان می آیند و میزان جداسازی آنها به تنظیمات و سیاست فروش ارائه دهنده بستگی دارد.

KVM بخشی از کرنل لینوکس است و با قابلیت مجازی سازی سخت افزاری پردازنده (Intel VT-x یا AMD-V) ماشین مجازی کامل می سازد. هر ماشین مجازی سخت افزار مجازی خودش را دارد، از کارت شبکه تا دیسک، و سیستم عامل را با کرنل خودش اجرا می کند. روی سرور KVM می توانید کرنل و ماژول هایش را عوض کنید، Docker را مثل یک سرور معمولی نصب کنید و فایل swap بسازید. در مجازی سازی کانتینری مثل OpenVZ یا LXC کرنل میزبان بین همه مشترک است و این کارها معمولاً محدود یا غیرممکن است.

سهم هر منبع در KVM این طور تعیین می شود:

  • رمی که به ماشین مجازی داده شده در اختیار همان ماشین است، مگر اینکه میزبان به مجموع ماشین ها بیشتر از رم فیزیکی خودش وعده داده باشد.
  • هر vCPU روی میزبان یک رشته پردازشی است که زمان بند کرنل میزبان اجرایش را تنظیم می کند. اگر میزبان شلوغ باشد، زمانی که از ماشین مجازی گرفته شده در ستون st خروجی vmstat دیده می شود.
  • I/O دیسک و شبکه از مسیر میزبان عبور می کند و اگر سقفی برایش تعیین نشده باشد، عملاً بین ماشین ها تقسیم می شود.

در صفحه سرور مجازی هلند پیکوهاست آمده که سرورها با KVM مجازی سازی شده اند و بیشتر از ظرفیت فروخته نمی شوند. صفحه سرور مجازی ایران هم مجازی سازی KVM و منابع اختصاصی را ذکر می کند.

رم DDR4 در سرور مجازی و مقدار رم کافی

در سرور مجازی مقدار رم معمولاً بیشتر از نسل آن روی سرعت اثر دارد. نسل و فرکانس ماژول ها را میزبان تعیین می کند و شما سهمی از رم آن را می گیرید؛ اگر این سهم کم باشد، سیستم بخشی از داده ها را به swap روی دیسک می برد و حتی هارد NVMe هم از رم بسیار کندتر است.

DDR4 استانداردی از JEDEC با شناسه JESD79-4 است که در سپتامبر ۲۰۱۲ منتشر شد. در اطلاعیه انتشار استاندارد DDR4 نرخ داده هر پین از ۱٫۶ گیگاترنسفر بر ثانیه تا هدف اولیه ۳٫۲ گیگاترنسفر بر ثانیه تعیین شده است.

رم سرور معمولاً صرف این بخش ها می شود:

  • buffer pool دیتابیس، که در MySQL و MariaDB با innodb_buffer_pool_size تنظیم می شود.
  • پردازه های PHP-FPM، Python یا Node.js که هر کدام حافظه خودشان را دارند.
  • باقی رم آزاد، که لینوکس برای کش فایل ها استفاده می کند و خواندن از دیسک را کم می کند.

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

روی فایل سیستم ext4 این دستورها یک فایل swap یک گیگابایتی می سازند. قبلش با swapon --show ببینید 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

تست سرعت دیسک و رم روی سرور خودتان

تست دیسک را بلافاصله بعد از تحویل و پیش از نصب سرویس ها انجام دهید تا نتیجه مبنای مقایسه های بعدی باشد. vmstat و iostat را بعد از راه اندازی و زیر بار واقعی اجرا کنید.

رم و پردازنده با free و vmstat

free -m
vmstat 1 10

در خروجی free -m ستون available را ببینید. طبق راهنمای free این ستون تخمین حافظه ای است که برای اجرای برنامه های جدید بدون swap در دسترس است. عدد free معمولاً کوچک است، چون لینوکس رم آزاد را برای کش استفاده می کند، و این نشانه کمبود رم نیست.

در vmstat 1 10 هر ثانیه یک خط چاپ می شود. خط اول میانگین از زمان روشن شدن سیستم است، پس از خط دوم به بعد را بخوانید:

  • اگر si و so پشت سر هم صفر نیستند، سیستم در حال جابه جایی حافظه با swap است و رم کم دارید.
  • wa زمانی است که پردازنده منتظر I/O مانده و b تعداد پردازه هایی است که منتظر تمام شدن I/O هستند. اگر این دو بالا بمانند، دیسک احتمالاً گلوگاه است.
  • st زمانی است که میزبان پردازنده را از ماشین مجازی گرفته است. بالا رفتن آن در ساعت های شلوغ یعنی پردازنده میزبان زیر بار است.
  • وقتی r مدت طولانی از تعداد هسته های سرور بیشتر است، پردازه ها برای گرفتن پردازنده صف کشیده اند.

تست سرعت هارد با fio

fio را با sudo apt install fio در Debian و Ubuntu یا sudo dnf install fio در توزیع های خانواده RHEL نصب کنید. سه تست زیر روی فایل آزمایشی fio.test در پوشه فعلی کار می کنند، پس پیش از اجرا به پوشه ای روی همان دیسکی بروید که می خواهید تست کنید، مثلاً پوشه خانه، و مطمئن شوید دست کم ۳ گیگابایت فضای آزاد دارد.

هیچ وقت --filename را روی خود دستگاه دیسک یا پارتیشن، مثل /dev/vda یا /dev/vda1، نگذارید. تست نوشتن روی دستگاه، فایل سیستم و داده های روی آن را از بین می برد.

تست خواندن و نوشتن تصادفی با بلوک ۴ کیلوبایتی، نزدیک به رفتار دیتابیس و وردپرس:

fio --name=randrw --filename=fio.test --size=2G --direct=1 \
    --ioengine=libaio --rw=randrw --rwmixread=70 --bs=4k \
    --iodepth=16 --runtime=60 --time_based --group_reporting

تست نوشتن با همگام سازی بعد از هر نوشتن، نزدیک به رفتار ثبت تراکنش در دیتابیس و SQLite:

fio --name=fsync --filename=fio.test --size=512M \
    --ioengine=sync --rw=randwrite --bs=4k --fsync=1 \
    --runtime=60 --time_based

تست خواندن ترتیبی با بلوک یک مگابایتی برای throughput، و پاک کردن فایل آزمایشی در پایان:

fio --name=seqread --filename=fio.test --size=2G --direct=1 \
    --ioengine=libaio --rw=read --bs=1M --iodepth=8 \
    --runtime=60 --time_based
rm fio.test

گزینه --direct=1 کش سیستم عامل را دور می زند تا سرعت خود دیسک اندازه گرفته شود. در خروجی، خطی که با read: یا write: شروع می شود IOPS و BW (پهنای باند) میانگین را نشان می دهد. طبق راهنمای fio، slat زمان ارسال درخواست، clat زمان از ارسال تا تمام شدن و lat کل زمان از ساخته شدن درخواست در fio تا تمام شدن آن است. در تست fsync که موتور sync دارد، ردیف slat نمایش داده نمی شود.

در بخش clat percentiles به صدک های 99.00th و 99.90th نگاه کنید. دو سرور با IOPS میانگین مشابه ممکن است صدک ۹۹ خیلی متفاوتی داشته باشند و سروری که صدک پایین تری دارد معمولاً زیر بار دیتابیس یکنواخت تر رفتار می کند. هر تست را دو یا سه بار و در ساعت های مختلف تکرار کنید و نتیجه دو سرور را فقط وقتی مقایسه کنید که دقیقاً با همان پارامترها گرفته شده باشد.

چرا عدد dd گمراه کننده است

دستور dd if=/dev/zero of=dd.test bs=1M count=1024 بدون گزینه اضافه روی کش سیستم عامل می نویسد و سرعتی که گزارش می کند بیشتر به رم مربوط است. این تست فقط نوشتن ترتیبی با یک جریان را اندازه می گیرد و درباره عملیات تصادفی ۴ کیلوبایتی یا تاخیر چیزی نمی گوید. بعضی لایه های ذخیره سازی هم داده صفر را فشرده می کنند و عدد را بزرگ تر از واقعیت نشان می دهند. اگر فقط یک بررسی سریع می خواهید، دست کم با conv=fdatasync اجرا کنید تا زمان نوشتن واقعی روی دیسک هم حساب شود:

dd if=/dev/zero of=dd.test bs=1M count=1024 conv=fdatasync
rm dd.test

iostat زیر بار واقعی

iostat در بسته sysstat است:

sudo apt install sysstat
iostat -dxm 5 3

این دستور سه گزارش با فاصله پنج ثانیه چاپ می کند. گزارش اول آمار از زمان روشن شدن سیستم است، پس گزارش های بعدی را بخوانید. r_await و w_await میانگین زمان پاسخ به درخواست های خواندن و نوشتن بر حسب میلی ثانیه اند و aqu-sz میانگین طول صف است. برای SSD و NVMe به ستون %util تکیه نکنید؛ طبق راهنمای iostat، در دستگاه هایی که درخواست ها را موازی پاسخ می دهند، مثل آرایه های RAID و SSDهای امروزی، این عدد سقف کارایی را نشان نمی دهد.

sysbench برای مقایسه پردازنده و رم

sudo apt install sysbench
sysbench cpu --cpu-max-prime=20000 --threads=1 run
sysbench cpu --cpu-max-prime=20000 --threads=2 run
sysbench memory run

در تست cpu عدد events per second را ببینید. این عدد به تنها معنای مطلقی ندارد و فقط برای مقایسه دو سرور با همان نسخه sysbench و همان پارامترها مفید است. اگر نتیجه یک سرور در ساعت های مختلف روز خیلی تغییر می کند، ستون st در vmstat را هم هم زمان بررسی کنید.

اولویت منابع برای هر نوع بار کاری

برای وردپرس و چند سایت روی یک سرور معمولاً مقدار رم اولویت اول است و برای دیتابیسی که از رم بزرگ تر است، تاخیر دیسک. در ربات تلگرام با Bot API هم محل سرور از هر دو مهم تر است.

بار کاریاولویت اولاولویت دومچه چیزی را اندازه بگیرید
وردپرس یا ووکامرس کوچک و متوسطمقدار رم برای PHP و دیتابیستاخیر خواندن تصادفی دیسکfree -m و تست fio با randrw
دیتابیس MySQL یا PostgreSQL بزرگ تر از رمتاخیر دیسک و صدک ۹۹ آنرم برای buffer poolتست fio با randrw و --fsync=1، iostat زیر بار
ربات تلگرام با Bot APIمحل سرور و مسیر شبکه تا تلگرامپایداری پردازندهزمان پاسخ API با curl و ستون st
ربات با SQLite و نوشتن زیادتاخیر نوشتن با همگام سازیمقدار رمتست fio با --fsync=1
کامپایل، CI و ساخت ایمیج Dockerتعداد و سرعت هسته هاIOPS برای فایل های کوچکsysbench cpu و تست fio با randrw
دانلود فایل، بکاپ و بازگردانیthroughput دیسک و شبکهسقف ترافیک ماهانهتست fio با --rw=read --bs=1M
چند سایت یا چند ربات روی یک سرورمقدار رمپایداری دیسک در ساعت شلوغvmstat و iostat در ساعت های مختلف

چک لیست روز اول بعد از تحویل سرور

  1. systemd-detect-virt و lsblk را اجرا کنید تا نوع مجازی سازی و دیسک ها را ببینید.
  2. پیش از نصب سرویس ها سه تست fio را اجرا کنید، خروجی را در یک فایل نگه دارید و فایل fio.test را پاک کنید.
  3. با swapon --show بررسی کنید swap دارید یا نه و اگر ندارید یک فایل swap کوچک بسازید.
  4. بعد از راه اندازی سایت یا ربات، vmstat 1 10 و iostat -dxm 5 3 را یک بار در ساعت خلوت و یک بار در ساعت شلوغ اجرا کنید.
  5. اگر تاخیر دیسک یا st در ساعت های مختلف خیلی تغییر می کند، خروجی همین تست ها را همراه ساعت اجرایشان در تیکت برای پشتیبانی بفرستید.