مستند کانفیگ آپاچی برای استفاده از fastcgi و php-fpm روی اوبونتو

شرح مسئله

پی‌اچ‌پی می‌تواند از ۳ طریق روی سرور اجرا شود:

  • apache module
  • CGI application
  • FastCGI application

متد اول استفاده از ماژول آپاچی به نام mod_php هست. این روش راحت‌ترین و دم‌دستی‌ترین روش اجرای php هست و بیشتر شرکت‌های هاستینگ به طور دیفالت از این روش استفاده می‌کنند. در این روش به ازای هر چایلدپروسس آپاچی یکبار مترجم php هم اجرا می‌شود و تا وقتی که اسکریپت کامل اجرا شود استندبای می‌ماند.

یکی از دلایل اینکه آپاچی مقدار بسیار زیادی از memory سرور را اشغال می‌کند همین استفاده از mod_php هست. آپاچی به ازای هر کاربر بازدید‌کننده یک چایلد پروسس ایجاد می‌کند و به همین دلیل در سایت‌های بزرگ صدها پروسس آپاچی در حال اجراست و هر کدام مترجم مخصوص خود را دارند درحالیکه تعداد اندکی از آن‌ها، شاید کمتر از ده‌تای آن‌ها واقعا نیازی به ران کردن php دارند. بقیه ریکوعست‌ها فقط فایل‌های استاتیک را می‌خواهند. php مقدار زیادی از رم را مشغول می‌کند و این ناشی از اجرای هزاران پروسس idle پی‌اچ‌پی درحال اجرا هست.

راه فرار از این overhead استفاده از fastcgi به جای mod_php هست. fast_cgi یک پروسس داخلی جداگانه روی daemon درحال اجرا هست و فقط زمانی به آن مراجعه می‌شود که وب‌سرور نیازی به اجرای php داشته باشد. در نتیجه لازم نیست برای تمام ریکوعست‌ها سرور php را اجرا کند.

همین امکان برای وب‌سرور ngnix هم وجود دارد ولی در این مستند ما برای apache 2.4 و ubuntu 14.04 و php5 بررسی کردیم. اگر از سیستم‌عامل دبیان استفاده می‌کنید، مستند کانفیگ آپاچی برای استفاده از fastcgi و php-fpm روی دبیان را بخوانید. در این مستند می‌خواهیم برای افزایش پرفرمنس وب‌سرور، PHP-FPM را با apache اینتگریت کنیم. PHP-FPM درواقع یک آلترناتیو برای FastCGI است که یک سری امکانات اضافی برای سایت‌هایی که با PHP طراحی می‌شوند دارد. درواقع امکان استفاده از خود fastcgi برای افرادی که سایت‌هایشان php نیست هم وجود دارد ولی وقتی apache را با php-fpm اجرا می‌کنید بهبود performance سایت‌های phpتان محسوس خواهد بود. البته ماژول‌های دیگری هم برای بهبود پرفرمنس CGI وجود دارند مثل fcgid که درواقع یک آلترناتیو برای FastCGI است. ولی در موارد بسیار نادری استفاده می‌شوند و در بیشتر مواقع از FastCGI استفاده می‌شود و ما هم در این مستند FastCGI را همراه امکانات اضافه PHP-FPM استفاده می‌کنیم.

نصب

اولین گام اینست که آپاچی را همراه با ماژول fastcgi نصب کنید. برای این منظور ۲ تا آپشن پیش رو دارید. یکی نصب پکیج apache2-mpm-worker دیگری نصب پکیج apache2-mpm-event هست. این‌ها در عمل تفاوت‌هایی با هم دارند. در اینجا ما اولی را نصب کردیم:

sudo apt-get install apache2-mpm-worker

ماژول FPM در مخازن رسمی کانونیکال نیست. پس باید فایل مخازن را باز کنید و موارد لازم را به آن اضافه کنید:

sudo nano /etc/apt/sources.list

خط‌های زیر را در فایل آنکامنت کنید:

deb http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ trusty multiverse
deb-src http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ trusty multiverse
deb http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ trusty-updates multiverse
deb-src http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ trusty-updates multiverse

گام بعد نصب PHP همراه پشتیبانی از PHP5-FPM است:

sudo apt-get update && sudo apt-get install libapache2-mod-fastcgi php5-fpm php5

لود کردن ماژول‌ها

اگر قبلا لمپ را به صورت معمولی نصب کردید لازم است یک سری ماژول‌هایی که به آن‌ها نیازی نداریم را غیرفعال کنید:

sudo a2dismod php5 mpm_prefork

گام بعد فعال کردن ماژول php5-fpm هست. برای این منظور باید ۳ تا ماژول fastcgi و alias و action را فعال کنیم:

sudo a2enmod actions fastcgi alias mpm_worker

یک فایل خالی در مسیر زیر ایجاد کنید:

sudo touch /usr/lib/cgi-bin/php5-fcgi

به آپاچی پرمیژن نوشتن در این دایرکتوری را بدهید:

sudo chown -R www-data:www-data /usr/lib/cgi-bin

در خروجی این دستور قبل از فعال‌سازی mpm_worker اخطار می‌دهد که با یه تعداد از ماژول‌ها امکان کانفیلیکت پیدا کردن دارد. از بین این ماژول‌ها mpm_prefork ممکن است فعال بوده باشد که آن را برای همین از قبل غیرفعال کردیم. برای اعمال تنظیمات انجام شده و ماژول‌های فعال‌شده در اجرای بعدی آپاچی آن را ریست کنید:

sudo service apache2 restart

کانفیگ ویرچوال‌هاست‌ها

در اینجا باید بلاک کد کانفیگ PHP5-FPM که به آپاچی می‌گوید با FPM کار کند را به تنظیمات وب‌سرورمان اضافه کنیم. برای این منظور دو راه وجود دارد یکی اینکه به تنظیمات تمام ویرچوال‌هاست‌ها یکی‌یکی اضافه کنیم. راه دوم اینست که تنظیمات فوق را جایی بنویسیم که در تمام ویرچوال‌هاست‌ها اعمال شود. برای راه اول به فایل تنظیمات vhost در /etc/apache2/site-available این بلاک را اضافه کنید:

<IfModule mod_fastcgi.c>
    AddHandler php5-fcgi .php
    Action php5-fcgi /php5-fcgi
    Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi
    FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization
    <Directory /usr/lib/cgi-bin>
      Require all granted
    </Directory>
</IfModule>

اگر از نسخه‌های قدیمی‌تر apache مثل apache 2.2 استفاده می‌کنید باید بلاک <Directory /usr/lib/cgi-bin> را از کد بالا حذف کنید. با دستور زیر ورژن آپاچی را چک کنید:

apache2 -v

دقت کنید /usr/lib/cgi-bin/php5-fcgi فقط یکبار می‌تواند تعریف شود پس اگر این تنظیمات را به تمام ویرچوال‌هاست‌ها اضافه کنید موقع ریست کردن آپاچی این ارور را مشاهده می‌کنید:

FastCgiExternalServer: redefinition of previously defined class "/usr/lib/cgi-bin/php5-fcgi"

نتیجه‌گیری اینکه اگر چند تا ویرچوال‌هاست دارید و روی تمام آن‌ها می‌خواهید این ماژول را فعال کنید از روش دوم که کانفیگ گلوبال ماژول هست بروید. برای این منظور باید یک فایل به نام php5-fpm.conf در دایرکتوری /etc/apache2/conf-available ایجاد کنیم و تنظیمات ماژول که در بالا به ویرچوال‌هاست اضافه کردیم را در آن وارد کنیم:

sudo nano /etc/apache2/conf-available/php5-fpm.conf

سپس یک symolic link به آن در /etc/apache2/conf-enabled ایجاد کنیم:

sudo a2enconf php5-fpm

و آپاچی را ریست کنیم:

sudo service apache2 restart

اطمینان از اعمال درست تنظیمات

گام آخر اینست که مطمئن شویم تنظیمات به درستی اعمال شده و کار می‌کند. برای این منظور یک فایل به نام info.php در شاخه‌ها روت ویرچوال‌هاست‌ها ایجاد کنید و این کد را درون آن‌ها قرار دهید:

<?php
phpinfo();
?>

این فایل را با مرورگرتان باز کنید. در اینجا تنظیمات آپاچی و php را مشاهده می‌کنید. در قسمت Server API به صورت دیفالت Apache 2.0 Handler را مشاهده می‌کنید. اما اگر تنظیمات به درستی انجام شده باشد ماژول fastCGI را مشاهده کنید و سیستم گزارش می‌کند که php5 از طریق این ماژول اجرا شده است. همچنین در بخش Loaded Modules اسم ماژول را می‌بینید. با بررسی خروجی این دستور هم می‌توانید از اعمال درست تنظمیات مطمئن شوید:

lynx -dump http://localhost/info.php | grep 'Server API'

نکته درباره کاهش سربار TCP

در بعضی موارد ممکن است PHP-FPM به صورت دیفالت روی پورت ۹۰۰۰ لیسن کند. برای جلوی‌گیری از overhead تی‌سی‌پی باید طوری تنظیم شود که به جای پورت ۹۰۰۰ از سوکت یونیکس استفاده کند. برای این منظور در فایل تنظیمات ماژول در بلاک <IfModule mod_fastcgi.c> به جای این:

FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -host 127.0.0.1:9000 -pass-header Authorization

نوشتیم:

FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /tmp/php5-fpm.sock -pass-header Authorization