وبلاگ نت‌آرامآموزش، تجربه و راهکارهای زیرساخت

چرا برنامه کند است ولی CPU سرور آزاد است؟ تشخیص محدودیت cgroup

آموزش خواندن cpu.max و cpu.stat، تشخیص محدودیت والد و تغییر حساب‌شده سهم CPU سرویس systemd در VPS لینوکسی.

انتشار:
توسط تیم فنی نت‌آرام
۷ دقیقه زمان مطالعه
۰ دیدگاه
محتوای تخصصی، ساده و کاربردی
هماهنگ با هویت حرفه‌ای نت‌آرام
بازگشت به لیست مقالات
تصویر شاخص مقاله چرا برنامه کند است ولی CPU سرور آزاد است؟ تشخیص محدودیت cgroup در وبلاگ نت‌آرام
محتوای آموزشی وبلاگ نت‌آرام
سایت یا برنامه کند شده، اما نمودار پردازنده سرور فقط ۳۰ درصد مصرف نشان می‌دهد. ممکن است خود برنامه در یک گروه محدود قرار گرفته باشد و همان سهم کوچک را کامل مصرف کند. لینوکس این گروه‌ها را با cgroup مدیریت می‌کند؛ هر سرویس یا کانتینر می‌تواند سقف جداگانه‌ای برای زمان پردازنده داشته باشد. بنابراین خالی‌بودن بخشی از CPU کل سرور، همیشه به معنی آزادبودن سهم برنامه نیست.
این راهنما برای مدیری است که به SSH و دسترسی sudo روی سرور مجازی ایران یا سرور اختصاصی ایران دسترسی دارد. مثال اصلی یک سرویس systemd به نام myapp.service است؛ آن را با نام واقعی برنامه خود جایگزین کنید. ابتدا فقط وضعیت را می‌خوانیم و اگر شواهد، محدودیت را تأیید کرد، یک تغییر محدود و قابل بازگشت را توضیح می‌دهیم.

۱. میانگین کل سرور را با سهم برنامه اشتباه نگیرید

فرض کنید سرور چهار پردازنده مجازی دارد، اما سقف سرویس روی نیم هسته تنظیم شده است. اگر همان سرویس به زمان پردازنده بیشتری نیاز داشته باشد، پس از مصرف سهمش ممکن است تا دوره بعدی منتظر بماند؛ در عین حال سه هسته و نیم سرور می‌توانند ظاهراً آزاد باشند. این انتظار را معمولاً throttling می‌نامند.
برای دیدن تعداد CPUهای قابل مشاهده و وضعیت کلی، این دستورها را در ترمینال سرور اجرا کنید:
کد / دستورnproc uptime top
در top با کلید q خارج شوید. این گزارش‌ها به تشخیص فشار کلی کمک می‌کنند، ولی به‌تنهایی سهم cgroup سرویس را ثابت نمی‌کنند. بار سیستم ممکن است به دیسک یا انتظارهای دیگر نیز مربوط باشد. زمان کندی و مدت پاسخ یک درخواست مشخص را یادداشت کنید تا بعداً همان شرایط را مقایسه کنید.

۲. نسخه cgroup و گروه سرویس را پیدا کنید

کد / دستورstat -fc %T /sys/fs/cgroup
خروجی cgroup2fs نشان می‌دهد مسیر اصلی از cgroup نسخه ۲ استفاده می‌کند و مثال‌های فایل این مقاله برای آن نوشته شده‌اند. اگر خروجی چیز دیگری است یا ساختار ترکیبی دارید، مسیرها و نام فایل‌ها ممکن است فرق کنند؛ برای نسخه ۱ باید تنظیمات و مستندات همان توزیع را بررسی کنید و مسیرهای زیر را عیناً کپی نکنید.
نام و محل گروه سرویس را ببینید:
کد / دستورsystemctl status myapp.service --no-pager systemctl show myapp.service -p ControlGroup -p Slice -p CPUQuotaPerSecUSec
اگر سرویس در حال اجرا باشد، ControlGroup ممکن است چیزی شبیه /system.slice/myapp.service باشد. اگر خالی است، اول نام سرویس و فعال‌بودن آن را بررسی کنید. دستور بعدی تعریف اصلی و فایل‌های تکمیلی سرویس را نشان می‌دهد:
کد / دستورsystemctl cat myapp.service
دنبال CPUQuota= و تنظیمات مرتبط بگردید. تنظیم ممکن است در فایل تکمیلی یا در slice والد باشد. اگر خود برنامه در کانتینر اجرا می‌شود، باید گروه همان کانتینر را روی میزبان پیدا کنید؛ گروه docker.service معمولاً گروه برنامه شما نیست. همچنین در محیط دارای cgroup namespace ممکن است بخشی از محدودیت‌های میزبان از داخل کانتینر دیده نشود.

۳. سقف را بخوانید و معنی آن را بفهمید

اگر خروجی واقعی شما همان مسیر نمونه /system.slice/myapp.service بود، دو فایل زیر را بخوانید. در غیر این صورت مسیر واقعی ControlGroup را بعد از /sys/fs/cgroup قرار دهید:
کد / دستورcat /sys/fs/cgroup/system.slice/myapp.service/cpu.max cat /sys/fs/cgroup/system.slice/myapp.service/cpu.stat
برای نمونه، خروجی 50000 100000 در cpu.max یعنی گروه در هر دوره ۱۰۰ هزار میکروثانیه، حداکثر ۵۰ هزار میکروثانیه زمان CPU دارد؛ تقریباً برابر با نصف یک هسته در میانگین آن دوره. مقدار 150000 100000 معادل یک و نیم هسته است. اگر مقدار اول max باشد، برای خود آن گروه سقف عددی تعیین نشده است؛ با این حال گروه والد می‌تواند محدودیت داشته باشد.
در cpu.stat مقدارهای nr_periods، nr_throttled و throttled_usec را پیدا کنید. مقدار دوم تعداد دوره‌هایی است که گروه محدود شده و مقدار سوم زمان ثبت‌شده محدودیت بر حسب میکروثانیه است. این شمارنده‌ها از قبل جمع شده‌اند: عدد بزرگ به‌تنهایی ثابت نمی‌کند علت کندی همین لحظه است.

۴. زمان کندی را با افزایش شمارنده مقایسه کنید

هنگام بار معمول و بدون ایجاد فشار مصنوعی روی سایت، خروجی cpu.stat و ساعت را ثبت کنید. حدود یک دقیقه بعد، در همان شرایط، دوباره همین دو دستور را اجرا کنید:
کد / دستورdate cat /sys/fs/cgroup/system.slice/myapp.service/cpu.stat
اگر nr_throttled و throttled_usec در فاصله‌ای که درخواست‌ها کند شده‌اند رشد می‌کنند و cpu.max هم سقف پایینی دارد، محدودیت CPU سرنخ مهمی است. رشد شمارنده به‌تنهایی اندازه تأخیر هر درخواست یا علت قطعی تمام کندی‌ها را نشان نمی‌دهد. مدت پاسخ، بار واقعی و سایر منابع را نیز با همان بازه بسنجید.
اگر مقدار اول cpu.max برابر max است یا تغییر سهم خود سرویس نتیجه‌ای ندارد، والد را هم بخوانید. برای مسیر نمونه بالا، والد مستقیم system.slice است:
کد / دستورcat /sys/fs/cgroup/system.slice/cpu.max cat /sys/fs/cgroup/system.slice/cpu.stat
در ساختار شما والد ممکن است نام دیگری داشته باشد و چند سطح محدودیت وجود داشته باشد. محدودیت والد میان فرزندانش مشترک است؛ بالا بردن سقف یک فرزند سقف والد را دور نمی‌زند. اگر فایل موجود نیست، اول نسخه cgroup، فعال‌بودن کنترل‌کننده و مسیر را بررسی کنید. تغییر مستقیم فایل‌های cgroup می‌تواند توسط مدیر سرویس بازنویسی شود؛ تنظیم را در ابزاری که آن گروه را مدیریت می‌کند اصلاح کنید.

۵. اصلاح یک سقف اشتباه در سرویس systemd

ابتدا دلیل وجود سقف را مشخص کنید: شاید برای محافظت از سایت‌های دیگر گذاشته شده باشد. تعداد هسته‌های در دسترس، مصرف سرویس‌های دیگر و زمان اوج را نیز بسنجید. اگر واقعاً سقف خود myapp.service عامل محدودیت است و ظرفیت کافی دارید، می‌توانید در یک بازه کنترل‌شده سقف را موقتاً افزایش دهید. برای مثالی که سقف فعلی آن ۵۰ درصد و سقف جدید توافق‌شده ۱۵۰ درصد است:
کد / دستورsudo systemctl set-property --runtime myapp.service CPUQuota=150%
طبق مستندات systemctl، تنظیم قابل پشتیبانی در زمان اجرا اعمال می‌شود و گزینه --runtime آن را برای بوت بعدی نگه نمی‌دارد. این دستور بلافاصله سهم رقابت سرویس را تغییر می‌دهد؛ روی سرور شلوغ به سرویس‌های دیگر هم توجه کنید. سپس cpu.max، شمارنده‌ها و مدت پاسخ را دوباره بخوانید. ممکن است محدودیت والد یا تعداد CPUهای مجاز هنوز مانع استفاده از سهم جدید باشد.
اگر نتیجه بدتر شد و سهم قبلی واقعاً ۵۰ درصد بود، در همین مثال می‌توانید همان را برگردانید:
کد / دستورsudo systemctl set-property --runtime myapp.service CPUQuota=50%
برای سرور واقعی، مقدار قبلی ثبت‌شده خودتان را جایگزین کنید؛ ۵۰ درصد یک نسخه عمومی نیست. این بازگردانی یک تنظیم runtime باقی می‌گذارد تا بوت بعدی. اگر از ابتدا سقف نامحدود، سیاست خودکار یا تنظیم runtime دیگری داشتید، پیش از تغییر روش بازگشت دقیق آن سیستم را مشخص کنید. از systemctl revert برای این کار استفاده نکنید، چون می‌تواند تنظیمات دیگری از همان واحد را نیز برگرداند.
اگر تغییر مؤثر بود، برای ماندگارکردن آن ابتدا محل تنظیم اصلی و سیاست مدیریت سرور را مشخص کنید و تنظیم تأییدشده را در همان روش استقرار ثبت کنید. فقط پس از تأیید پایداری و تناسب با دیگر سرویس‌ها، تغییر پایدار بدهید. مستند CPUQuota در systemd معنی درصد را نسبت به یک CPU توضیح می‌دهد.

۶. اگر سقف CPU علت اصلی نبود

اگر شمارنده محدودیت در زمان کندی افزایش نمی‌یابد، دنبال دلیل دیگر بروید. مصرف یک هسته توسط یک پردازش تک‌ریسمانی می‌تواند میانگین کل را پایین نشان دهد؛ در top کلید 1 را برای تفکیک CPUها بزنید. همچنین فشار حافظه، دیسک کند، انتظار شبکه یا قفل پایگاه داده می‌تواند پاسخ را طولانی کند. پیام‌های خروج غیرمنتظره را با راهنمای تشخیص OOM در لینوکس مقایسه کنید.
پس از هر تغییر فقط همان درخواست یا کار قبلی را دوباره بسنجید و مدت پاسخ، رشد nr_throttled و وضعیت سرویس‌های دیگر را کنار هم بگذارید. هدف این نیست که همه محدودیت‌ها را حذف کنید؛ هدف این است که برنامه سهم کافی داشته باشد و بقیه سرویس‌ها نیز پایدار بمانند. تعریف فایل‌ها و شمارنده‌ها در مستندات cgroup نسخه ۲ آمده است.
اشتراک‌گذاری:
لینکدینتلگرامایکس
مقاله قبلی
مقاله قبلی وجود ندارد.

دیدگاه‌ها (۰)

دیدگاه‌های تاییدشده و پاسخ‌های تیم نت‌آرام