اگر از یک وب سرور با PHP-FPM استفاده می کنید، به احتمال زیاد باید تنظیمات اولیه ی مربوط به PHP-FPM را بر اساس نیازمندی ها و وضعیت سرور خود تغییر دهید. ما در این مقاله می خواهیم به شما روشی را معرفی کنیم که بهترین کانفیگ PHP-FPM را برای خود بدست آورید.
آنچه گذشت ...
اینکه PHP-FPM دقیقا چیست و چه کمکی به ما می کند و چه تنظیماتی می تواند داشته باشد را در چند مقالهی قبل به صورت کامل توضیح دادیم که اگر خواستید از ابتدای بحث با ما همراه شوید، بهتر است لینک های زیر را دنبال کنید:
- در مقاله ی پردازش موازی در آپاچی با انواع ماژول های آپاچی برای پردازش موازی و در انتها با FastCGI و مدیر پردازش های آن یعنی PHP-FPM آشنا شدیم.
- سپس درباره ی اینکه مسیر رسیدن به PHP-FPM چه بوده و چگونه به PHP-FPM رسیدیم؟ صحبت شد.
- سپس راه اندازی PHP-FPM روی وب سرور آپاچی را به همراه مثال کاربردی داشتیم.
- و در آخر با روش کار PHP-FPM و مهمترین تنظیمات آن آشنا شدیم.
و اما درباره ی موضوع این مقاله ...
کشف یک هشدار جدید در لاگ های FPM
ممکن است در حین بررسی لاگ های PHP-FPM به خطا یا هشداری مشابه زیر برخورد کرده باشید:
[26-Mar-2018 10:10:04] WARNING: [pool www] server reached pm.max_children setting (35), consider raising it
[26-Mar-2018 12:04:52] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)
این خطا یعنی اینکه شما پردازشگرهای کافی برای php-fpm در دسترس ندارید و به احتمال زیاد باید سری به تنظیمات FPM بزنید.
در قسمت بررسی لاگ FPM در مقاله ی قبل دیدیم که چگونه لاگ، از وضعیت سرور و شلوغی و محدودیت هایش به ما خبر می دهد و هر کدام چه معنایی دارد.
دلایل احتمالی زیادی وجود دارد که PHP-FPM شما به max_children برسد:
- تعداد زیادی بازدید کننده همزمان سایت
- اجرای آهسته اسکریپت های PHP به دلیل منابع سرور یا اسکریپت های دارای اشکال
- در نظر گرفتن عدد بسیار پایین برای max_children در کانفیگ php-fpm
تعیین تعداد صحیح پردازش ها برای PHP-FPM
بر اساس دیتایی که از لاگ ها به صورت realtime به دست می آید، تعیین تنظیمات مناسب برای پیکربندی php-fpm در سرور شما کار راحت تری است.
با بررسی لاگ ها و در کنار آن اطلاع داشتن از حافظه و پردازشگر سرور خودمان می توانیم به عدد های دقیق تری از تنظیمات برسیم.
بر اساس مقالهی قبلی کانفیگ های زیر، اصلی ترین مواردی هستند که در فایل etc/php7.3/fpm/pool.d/www.conf/ قرار گرفتند و برای این موضوع باید تنظیم شوند:
pm.max_children = 25
pm.start_servers = 8
pm.min_spare_servers = 6
pm.max_spare_servers = 10
برای یافتن مقادیر صحیح، باید اندازه گیری کنید که یک فرآیند چقدر حافظه مصرف می کند. توجه داشته باشید، این فقط در سروری امکان پذیر است که وب سایت، دارای حافظه پایدار در هر فرآیند باشد، به عبارت دیگر برای یک محیط هاست اشتراکی با وب سایت های مختلف و کدهای توسعه یافته ی متفاوت روی آن، میزان استفاده از حافظه در هر فرآیند به طور جدی دچار نوسان می شود!
خط زیر را با کاربر root در کنسول سرور خود اجرا کنید. خروجی ارزشمندی را به شما می دهد:
ps -ylC php-fpm7.3 --sort:rss
نام php-fpm با نام فرآیند شما مطابقت دارد. ممکن است نام دیگری روی سرور شما داشته باشد که بستگی به PHP مورد استفاده در سرور شما دارد.
در خروجی این دستور، ستون RSS حاوی میانگین مصرف حافظه بر حسب کیلوبایت در هر فرآیند است.
S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD
S 0 24439 1 0 80 0 6364 57236 - ? 00:00:00 php-fpm7.3
S 33 24701 24439 2 80 0 61588 63335 - ? 00:04:07 php-fpm7.3
S 33 25319 24439 2 80 0 61620 63314 - ? 00:02:35 php-fpm7.3
در این مثال 61588 کیلوبایت یا حدود 60 مگابایت در هر فرآیند استفاده می شود.
روش دیگر، دریافت میانگین فرآیند php-fpm است که با دستور زیر آن را برای شما محاسبه می کند:
ps --no-headers -o "rss,cmd" -C php-fpm7.3 | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"Mb") }'
مقدار صحیح برای pm.max_children
برای به دست آوردن مقدار صحیح برای تعداد pm.max_children، باید بررسی کنیم که سرور ما چه مقدار حافظه می تواند برای فرآیند php-fpm استفاده کند و کل آن را بر میانگین اندازه فرآیند تقسیم کنیم.
به عنوان مثال: اگر سرور ما 4 گیگابایت رم دارد و یک سرویس پایگاه داده MariaDB نیز در حال اجرا است که حداقل 1 گیگابایت مصرف می کند و سایر پردازش ها را نیز نیم گیگ در نظر بگیریم، بهترین هدف ما این است که 2.5 گیگابایت یا 2560 مگابایت رم برای کل فرآیند های FPM در نظر بگیریم.
pm.max_children : 2560 Mb / 60 Mb = 42 max_children
مقدار صحیح برای تعداد Spare Children
در بررسی لاگی که در مقاله ی قبل داشتیم اشاره شد که در مواقعی ممکن است سرور به یکباره درگیر و مشغول شود و بخواهد تعداد پردازشگر ها را افزایش دهد و چون ساختن و از بین بردن یک پردازش سربار دارد همیشه تعدادی پردازش آماده ی کار نگه می دارد.
اگر در لاگ ها با چنین هشداری به مراتب برخوردید، پس بدانید تعداد min و max ها برای spare را باید افزایش دهید:
WARNING: pid 32638, fpm_pctl_perform_idle_server_maintenance(), line 399: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children
درباره ی اینکه این اعداد را چگونه محاسبه کنیم، به موارد مختلفی بستگی دارد که یکی از آنها عدد max_children می باشد. برای مثال وقتی که max_children را 40 در نظر گرفتیم دیگر تعداد min_spare_servers عدد خیلی کمی نباید باشد.
یکی از پیشنهادهایی که برای این موضوع شده است این است که عدد این موارد، ضریبی از تعداد هسته های پردازشگر سرور شما باشد.
pm dynamic
pm.max_children (total RAM - (DB , etc) / process size)
pm.start_servers (cpu cores * 4)
pm.min_spare_servers (cpu cores * 2)
pm.max_spare_servers (cpu cores * 4)
که برای مثال بالایی که زدیم و با تعداد 4 هسته CPU به صورت زیر می شود:
pm dynamic
pm.max_children 40
pm.start_servers 16
pm.min_spare_servers 8
pm.max_spare_servers 16
جمع بندی
با توجه به روش هایی که گفته شد می توانیم به عدد ایده آلی برای تنظیمات PHP-FPM نزدیک شویم ولی در هر صورت از بررسی لاگ FPM غافل نشوید زیرا اطلاعات خوبی از رفتار سرور شما می دهد که می توانید از آنها در بهبود تنظیمات استفاده کنید.
منابع:
https://community.webcore.cloud/tutorials/how_to_solve_php_fpm_server_reached_max_children/