بهینه‌ سازی تنظیمات PHP-FPM

9 دی 1402 وبلاگ
بهینه‌ سازی تنظیمات PHP-FPM

آیا تا به حال ساعت‌ها صرف تنظیم PHP-FPM کرده‌اید، آن را آزمایش کرده‌اید تا زمانی که همه چیز به خوبی اجرا شود؟

تغییرات خود را وارد تولید می‌کنید و در عرض چند ساعت یا چند روز، ناگهان خراب می‌شود؟

آیا نیاز به راه اندازی مجدد دستی دارید، در حالی که در عین حال کل وب سایت خود را آفلاین می کنید؟

با این حال، مطمئناً می‌توانم شما را در جهت درست راهنمایی کنم تا آن را برای عملکرد و قابلیت اطمینان نهایی تنظیم کنید.

قبل از پرداختن به این روش، در ابتدا در مورد php-fpm شرح مختصری داده می‌شود.

php-fpm چیست؟

زمانی که مرورگر کاربر، درخواستی را به یک سرور اجرا کننده PHP ارسال می‌کند، این PHP نیست که برقرار کننده ارتباط است؛ بلکه، سرور HTTP است که عمدتاً Apache یا Nginx است.

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

این چرخه درخواست-پاسخ در تصویر زیر نشان داده شده است.

در برنامه‌های جدید PHP، بخش “find file” در تصویر بالا، همان index.php است و سرور بگونه‌ای پیکربندی شده است که کلیه درخواست‌ها را به آن واگذار کند.

چنانچه Apache را وب سرور انتخابی در نظر بگیریم، PHP یک ماژول داخل سرور خواهد بود؛ بدین صورت، هر زمان درخواستی دریافت شود، سرور فرآیند جدیدی را آغاز می‌کند

که بصورت خودکار شامل PHP است. این روش mod_php نامیده می‌شود که اختصار عبارت “php as a module” است.

این رویکرد در ابتدا دارای محدودیت‌های زیادی بود که Nginx با استفاده از php-fpm بر آن‌ها غلبه کرد.

در php-fpm، مسئولیت مدیریت PHP وابسته به فرآیندهای مربوط به برنامه PHP در سرور است. به عبارت دیگر، سرور وب (در اینجا Nginx)، اهمیتی نمی‌دهد که PHP کجاست و

چگونه بارگذاری می‌شود؛ بلکه تنها برای آن مهم است که چگونه داده‌ها را برای آن ارسال کرده و یا از آن دریافت نماید.

چنانچه تنظیمات Nginx را انجام داده باشید، به چنین چیزی برخورد خواهید کرد:

php_fpm_1

از بین کدهای بالا، خط مورد نظر ما این است:

php_fpm_2

که در آن به Nginx گفته می‌شود، از طریق سوکتی به نام php7.2-fpm.sock با فرآیند PHP ارتباط برقرار کند.
بنابراین، به ازای هر درخواست، Nginx داده‌ها را درون این فایل نوشته و با دریافت خروجی، آن را به مرورگر برمی‌گرداند.

براساس آنچه در این بخش بیان شد، می‌توان به طور خلاصه گفت:

  • PHP، درخواست‌های ارسال شده توسط مرورگرها را به طور مستقیم دریافت نمی‌کند؛ بلکه وب سرورهایی مانند Nginx ابتدا آن‌ها را دریافت می‌نمایند.
  • وب سرور می‌داند، چگونه به فرایند PHP متصل شده و تمام داده‌های درخواست را برای PHP  بفرستد.
  • هنگامی‌که PHP کار خود را انجام داد، پاسخ را به وب سرور ارسال کرده و سرور آن را برای کلاینت (در بیشتر موارد مرورگر) ارسال می‌نماید.

بخش “FPM” در کنار PHP، مخفف عبارت “Fast Process Manager” است که وظیفه ایجاد، کنترل و توقف فرایندهای PHP را به عهده دارد.

این مدیر فرآیند است که سرور وب درخواست‌ها را به آن‌ها منتقل می‌کند.

دلیل نیاز به بهینه‌سازی php-fpm

چنانچه php-fpm با تنظیمات شما خوب عمل می‌کند و شما نیز آن را برای موارد اختصاصی استفاده نمی‌کنید، بهتر است از تنظیم پیش فرض استفاده نمایید.

اما اگر می‌خواهید فراتر از حالت بازدهی عادی عمل نماید، باید آن را بهینه‌سازی کنید.

نکته دیگری که باید بدانیم این است که Nginx برای مدیریت انتقال‌های سنگین ساخته شده است. علاوه‌براین، این قابلیت را دارد که هزاران اتصال را از طریق آن همزمان انجام دهید.

با این حال، اگر بهینه‌سازی را برروی تنظیمات PHP خود اعمال نکنید، منابع خود را هدر داده‌اید؛ زیرا Nginx در هر حال باید منتظر اجرای کامل فرآیندهای PHP بماند.

در نتیجه تمام مزایایی را که Nginx برای ارائه آن‌ها ساخته شده است، از دست خواهید داد.

در بخش بعدی چگونگی بهینه‌سازی php-fpm شرح داده شده است.

 

نحوه بهینه‌سازی PHP-FPM

مسیر فایل پیکربندی php-fpm ممکن است در سرورهای مختلف متفاوت باشد. بنابراین برای یافتن آن مسیر باید مقداری جستجو کنید.

در UNIX می‌توانید از دستور find استفاده نمایید.

در اینجا، مسیر فایل بصورت etc/php/7.2/fpm/php-fpm.conf/ است که مربوط به نسخه  PHP 7.2 در اوبونتو است.

آنچه در چند سطر اول این فایل مشاهده می‌کنید، بدین صورت خواهد بود:

php_fpm_3

خط pid = /run/php/php7.2-fpm.pid می‌گوید کدام فایل شامل شناسه فرایند php-fpm است.

همچنین قابل مشاهده است که مسیر var/log/php7.2-fpm.log مکانی است که گزارش‌های php-fpm باید ذخیره شوند.

در داخل این فایل، سه متغیر دیگر به صورت زیر اضافه کنید:

 

php_fpm_4

 

دو تنظیم اول جنبه احتیاطی داشته و به فرآیند php-fpm می‌گویند که اگر ده فرآیند فرزند (child thread) طی یک دقیقه شکست خورد،

فرآیند اصلی php-fpm باید خودش مجدداً راه‌اندازی شود.

اگرچه این متغیر ممکن است غیر ضروری به نظر برسد؛ ولیکن بدین صورت نیست. چراکه PHP یک فرایند کوتاه مدت است که باعث نشت حافظه می‌شود؛

بنابراین راه‌اندازی مجدد فرآیند اصلی در موارد شکست‌های زیاد می‌تواند بسیاری از مشکلات را برطرف کند.

 

گزینه سوم یعنی process_control_timeout، به فرآیندهای فرزند می‌گوید؛ قبل از اجرای سیگنال دریافتی از فرآیند پدر، مدت زمانی را صبر کنند.

این گزینه در مواردی مفید است که فرآیندهای فرزند در وسط کار باشند و فرآیند پدر به‌عنوان‌مثال یک سیگنال KILL ارسال می‌کند.

در این صورت با گذشت ده ثانیه، آن‌ها شانس بهتری برای به پایان رساندن وظایف خود خواهند داشت.

اما این تمام چیزی نیست که برای پیکربندی php-fpm نیاز است! به این دلیل که برای ارائه درخواست‌های وب، php-fpm یک مجموعه جدید از فرآیندها ایجاد می‌کند

که پیکربندی جداگانه‌ای خواهند داشت. در اینجا، نام این مجموعه www و فایل مورد نیاز برای ویرایش etc/php/7.2/fpm/pool.d/www.conf/ است.

بیایید ببینیم این فایل به چه صورت شروع می‌شود:

php_fpm_5

با نگاهی گذرا به انتهای قطعه کد بالا، این سوال پاسخ داده می‌شود که چرا فرآیند سرور با کاربر www-data اجرا می‌شود.

اگر هنگام تنظیم وب سایت خود با مشکل مجوز فایل روبرو شدید، احتمالاً مالک یا گروه دایرکتوری را به www-data تغییر داده‌اید.

بنابراین به فرایند PHP اجازه می‌دهید تا بتواند در فایل‌های گزارش بنویسد، اسناد را بارگذاری نماید و … .

 

در انتها، به مدیریت فرآیند (PM یا همان Process Manager) می‌رسیم. به طور کلی، پیش فرض‌های این بخش را به صورت زیر مشاهده خواهید کرد:

php_fpm_6

همانطور که در مستند زیر بیان شده است، pm می‌تواند سه مقدار بگیرد که در ادامه شرح داده‌ایم:

 

php_fpm_7

static: تعداد مشخصی از فرایندهای PHP را تعیین می‌نماید که باید زنده نگه داشته شوند.

Dynamic: حداقل و حداکثر تعداد فرایندهای PHP را تعیین می‌نماید که باید در هر زمان زنده نگه داشته شوند.

Ondemand: فرایندها را براساس تقاضا ایجاد و تخریب می‌کند.

 

اکنون این سوال در ذهن ایجاد می‌شود که هر کدام از این حالت‌ها در چه زمانی باید استفاده شوند؟

به زبان ساده، اگر وب سایتی با ترافیک کم دارید، تنظیمات “dynamic” منجر به تلف شدن منابع می‌شود.

با فرض اینکه pm.min_spare_servers را روی 3 تنظیم کرده باشید، حتی زمانی که ترافیکی در وب سایت وجود نداشته باشد، سه فرآیند PHP ایجاد و نگه داری می‌شوند.

بنابراین در چنین مواردی، “ondemand” گزینه بهتری است چراکه به سیستم اجازه می‌دهد تصمیم بگیرد که چه زمانی فرایندهای جدیدی را راه‌اندازی کند.

از طرف دیگر، وب سایت‌هایی که میزان زیادی از ترافیک را کنترل می‌کنند یا باید به سرعت پاسخ دهند، “dynamic” برای آن‌ها مناسب است.

چراکه ایجاد یک فرآیند جدید PHP، منجر به سربار اضافی می‌شود که به بهترین وجه از آن جلوگیری می‌شود.

استفاده از pm = static تعداد فرایندهای فرزند را بصورت دقیق مشخص می‌کند و اجازه می‌دهد حداکثر منابع سیستم به منظور پاسخ به درخواست‌ها

نسبت به مدیریت PHP مورد استفاده قرار گیرند. اگر این روش را انتخاب کرده‌اید، مراقب باشید که دستورالعمل‌ها و مشکلات خاص خود را دارد که نیازمند تحقیقات بیشتری در این زمینه است.

با همه این‌ها، اگر نمی‌خواهید برای بهینه‌سازی سرورهای PHP خود وقت بگذارید، بهتر است از یک پلتفرم قابل اعتماد مانند Kinsta استفاده نمایید که از امنیت بهینه‌سازی عملکرد مراقبت می‌کند.