آموزش جامع کانفیگ Nginx و PHP-FPM برای وب‌سایت‌های پرترافیک

در وب‌سایت‌های پرترافیک، انتخاب وب‌سرور مناسب و تنظیم صحیح لایه اجرای PHP تأثیر مستقیمی بر سرعت، پایداری، مصرف منابع و تجربه کاربری دارد. ترکیب Nginx و PHP-FPM یکی از محبوب‌ترین معماری‌ها برای میزبانی سایت‌های وردپرسی، فروشگاه‌های اینترنتی، پنل‌های سازمانی و اپلیکیشن‌های PHP است.

در این راهنما، از مفاهیم پایه تا تنظیمات پیشرفته Nginx و PHP-FPM را بررسی می‌کنیم؛ از نصب و ساختار فایل‌های کانفیگ گرفته تا مدیریت پردازش‌ها، کش، فشرده‌سازی، امنیت، مانیتورینگ و بهینه‌سازی برای ترافیک بالا.

چرا Nginx و PHP-FPM برای سایت‌های پرترافیک مناسب هستند؟

Nginx یک وب‌سرور سبک و رویدادمحور است که می‌تواند تعداد زیادی اتصال هم‌زمان را با مصرف حافظه پایین مدیریت کند. این وب‌سرور فایل‌های استاتیک مانند تصاویر، فایل‌های CSS و JavaScript را با سرعت بالا ارائه می‌دهد و درخواست‌های PHP را به PHP-FPM ارسال می‌کند.

PHP-FPM یا PHP FastCGI Process Manager وظیفه اجرای کدهای PHP را بر عهده دارد. برخلاف اجرای سنتی PHP، پردازش‌های PHP-FPM به‌صورت مدیریت‌شده و دائمی اجرا می‌شوند؛ بنابراین سربار ایجاد پردازش جدید برای هر درخواست کاهش پیدا می‌کند.

  • مصرف حافظه کمتر نسبت به بسیاری از معماری‌های سنتی
  • توانایی مدیریت تعداد زیادی اتصال هم‌زمان
  • امکان تنظیم دقیق تعداد Workerها
  • پشتیبانی از کش FastCGI و کش مرورگر
  • امنیت و انعطاف‌پذیری بالا
  • مناسب برای وردپرس، لاراول، مجنتو و سایر فریم‌ورک‌های PHP

معماری پیشنهادی برای وب‌سایت پرترافیک

در یک معماری استاندارد، درخواست کاربر ابتدا به Nginx می‌رسد. Nginx فایل‌های استاتیک را مستقیماً پاسخ می‌دهد و درخواست‌های مربوط به PHP را از طریق FastCGI به PHP-FPM ارسال می‌کند.

کاربر
  ↓
DNS / CDN / Load Balancer
  ↓
Nginx
  ├── فایل‌های استاتیک
  └── PHP-FPM
        ↓
      PHP Application
        ↓
      MySQL / Redis / External Services

در سایت‌های بسیار بزرگ، می‌توان Nginx را در چند سرور اجرا کرد و PHP-FPM، دیتابیس، Redis و سرویس‌های ذخیره‌سازی را روی سرورهای جداگانه قرار داد.

پیش‌نیازهای نصب و بهینه‌سازی

نمونه دستورات این مقاله بر پایه توزیع‌های Debian و Ubuntu نوشته شده است. برای دریافت بهترین نتیجه، استفاده از نسخه پشتیبانی‌شده سیستم‌عامل و نسخه پایدار PHP توصیه می‌شود.

حداقل مشخصات پیشنهادی سرور

  • سیستم‌عامل ۶۴ بیتی و به‌روز
  • حداقل ۲ هسته پردازنده برای سایت متوسط
  • حداقل ۴ گیگابایت RAM برای اجرای PHP و سرویس‌های جانبی
  • دیسک SSD یا NVMe
  • فعال بودن HTTPS با گواهی معتبر
  • دسترسی SSH با کاربر دارای دسترسی sudo

مقدار واقعی منابع باید بر اساس تعداد درخواست در ثانیه، زمان اجرای اسکریپت‌های PHP، حجم داده، نوع کوئری‌های دیتابیس و تعداد کاربران هم‌زمان تعیین شود.

نصب Nginx و PHP-FPM

به‌روزرسانی سیستم

sudo apt update
sudo apt upgrade -y

نصب Nginx

sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx

نصب PHP-FPM و افزونه‌های ضروری

sudo apt install php-fpm php-cli php-mysql php-curl php-gd php-mbstring php-xml php-zip php-opcache php-intl -y

پس از نصب، نسخه PHP-FPM را بررسی کنید:

php -v
systemctl status php8.2-fpm

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

ساختار فایل‌های کانفیگ Nginx

فایل اصلی Nginx معمولاً در مسیر زیر قرار دارد:

/etc/nginx/nginx.conf

فایل‌های مربوط به سایت‌ها معمولاً در مسیرهای زیر قرار می‌گیرند:

/etc/nginx/sites-available/
/etc/nginx/sites-enabled/

روش پیشنهادی این است که برای هر وب‌سایت یک فایل جداگانه در sites-available بسازید و سپس با ایجاد لینک نمادین، آن را فعال کنید.

ساخت Virtual Host

sudo nano /etc/nginx/sites-available/example.com

نمونه کانفیگ پایه:

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    root /var/www/example.com/public;
    index index.php index.html;

    access_log /var/log/nginx/example-access.log;
    error_log  /var/log/nginx/example-error.log warn;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

برای فعال‌سازی سایت:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo nginx -t
sudo systemctl reload nginx

دستور nginx -t قبل از هر Reload باید اجرا شود. این دستور صحت ساختار فایل‌های کانفیگ را بررسی می‌کند و از قطع شدن سرویس به دلیل خطای دستوری جلوگیری می‌کند.

تنظیمات اصلی Nginx برای ترافیک بالا

فایل اصلی Nginx را باز کنید:

sudo nano /etc/nginx/nginx.conf

یک تنظیم پایه و مناسب برای اکثر سرورها به شکل زیر است:

user www-data;
worker_processes auto;
worker_rlimit_nofile 200000;

events {
    worker_connections 8192;
    multi_accept on;
    use epoll;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 15;
    keepalive_requests 1000;

    server_tokens off;

    client_max_body_size 64M;
    client_header_timeout 15s;
    client_body_timeout 30s;
    send_timeout 30s;

    open_file_cache max=100000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

توضیح تنظیمات مهم

  • worker_processes auto: تعداد Workerها را بر اساس تعداد هسته‌های پردازنده تنظیم می‌کند.
  • worker_connections: حداکثر تعداد اتصال‌هایی است که هر Worker مدیریت می‌کند.
  • worker_rlimit_nofile: سقف فایل‌ها و اتصال‌های باز را افزایش می‌دهد.
  • sendfile: انتقال فایل‌ها را با استفاده بهینه‌تر از سیستم‌عامل انجام می‌دهد.
  • tcp_nopush: ارسال هدر و داده را برای فایل‌های بزرگ بهینه می‌کند.
  • keepalive_timeout: مدت نگه‌داری اتصال‌های پایدار را مشخص می‌کند.
  • open_file_cache: اطلاعات فایل‌ها و توصیف‌گرهای فایل را در حافظه نگه می‌دارد.
  • client_max_body_size: حداکثر حجم درخواست، به‌خصوص آپلود فایل، را تعیین می‌کند.

افزایش بیش از حد worker_connections یا worker_rlimit_nofile بدون بررسی منابع سیستم می‌تواند باعث مصرف بالای حافظه یا عبور از محدودیت‌های سیستم‌عامل شود.

تنظیم PHP-FPM برای سایت‌های پرترافیک

تنظیم PHP-FPM مهم‌ترین بخش بهینه‌سازی اجرای PHP است. اگر تعداد پردازش‌ها کم باشد، درخواست‌ها در صف باقی می‌مانند؛ اگر تعداد پردازش‌ها بیش از ظرفیت سرور باشد، RAM و CPU به‌سرعت اشباع می‌شوند.

فایل Pool مربوط به PHP-FPM

فایل تنظیمات معمولاً در مسیر زیر قرار دارد:

/etc/php/8.2/fpm/pool.d/www.conf

بخش مهمی از تنظیمات پیشنهادی:

[www]

user = www-data
group = www-data

listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 20
pm.max_requests = 500

request_terminate_timeout = 120s
request_slowlog_timeout = 5s
slowlog = /var/log/php8.2-fpm/www-slow.log

catch_workers_output = yes

انتخاب مقدار مناسب pm.max_children

پارامتر pm.max_children حداکثر تعداد پردازش‌های هم‌زمان PHP-FPM را تعیین می‌کند. برای محاسبه تقریبی، ابتدا مقدار حافظه‌ای را که هر پردازش PHP مصرف می‌کند به دست آورید.

pm.max_children = حافظه اختصاص‌یافته به PHP-FPM ÷ میانگین مصرف هر پردازش PHP

برای مثال، اگر ۲ گیگابایت RAM به PHP-FPM اختصاص داده شده باشد و هر Worker به‌طور میانگین ۵۰ مگابایت مصرف کند:

2048 ÷ 50 ≈ 40

در عمل باید فضایی برای سیستم‌عامل، Nginx، دیتابیس، Redis و سرویس‌های دیگر باقی بگذارید. بنابراین عدد محاسبه‌شده سقف نظری است و لزوماً بهترین مقدار عملی نیست.

حالت‌های مدیریت پردازش PHP-FPM

  • static: تعداد مشخصی پردازش همیشه فعال است و برای بار ثابت و سنگین مناسب است.
  • dynamic: تعداد پردازش‌ها بر اساس بار کاری افزایش یا کاهش پیدا می‌کند.
  • ondemand: پردازش‌ها فقط هنگام دریافت درخواست ساخته می‌شوند و برای سایت‌های کم‌ترافیک مناسب‌تر هستند.

برای بیشتر وب‌سایت‌های پرترافیک، حالت dynamic انتخاب متعادلی است. در سایت‌هایی با ترافیک ثابت و قابل پیش‌بینی، حالت static نیز می‌تواند عملکرد پایدار و قابل پیش‌بینی‌تری ارائه دهد.

مزیت pm.max_requests

پارامتر pm.max_requests پس از پردازش تعداد مشخصی درخواست، Worker را بازنشسته و دوباره ایجاد می‌کند. این قابلیت می‌تواند اثر نشت حافظه در برخی افزونه‌ها یا کتابخانه‌های PHP را کاهش دهد.

مقدار مناسب به نوع برنامه بستگی دارد، اما مقادیر بین ۳۰۰ تا ۱۰۰۰ معمولاً نقطه شروع قابل قبولی هستند.

فعال‌سازی و بهینه‌سازی OPcache

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

فایل تنظیمات OPcache را پیدا کنید:

php --ini

نمونه تنظیمات:

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=50000
opcache.revalidate_freq=2
opcache.validate_timestamps=1
opcache.save_comments=1
opcache.fast_shutdown=1

در محیط Production، اگر فرآیند انتشار نسخه به‌صورت کنترل‌شده انجام می‌شود، می‌توانید اعتبارسنجی زمان فایل‌ها را غیرفعال کنید:

opcache.validate_timestamps=0

در این حالت پس از هر انتشار نسخه جدید باید PHP-FPM را Reload یا Restart کنید؛ در غیر این صورت نسخه قدیمی کد ممکن است در حافظه باقی بماند.

sudo systemctl reload php8.2-fpm

اتصال Nginx به PHP-FPM با سوکت یا TCP

استفاده از Unix Socket

fastcgi_pass unix:/run/php/php8.2-fpm.sock;

سوکت Unix معمولاً روی یک سرور واحد، سربار کمتری نسبت به TCP دارد و گزینه مناسبی برای ارتباط Nginx و PHP-FPM روی همان ماشین است.

استفاده از TCP

fastcgi_pass 127.0.0.1:9000;

TCP زمانی کاربردی است که PHP-FPM روی سرور جداگانه اجرا شود یا بخواهید معماری سرویس‌ها را از یکدیگر جدا کنید. در این حالت باید فایروال و کنترل دسترسی به پورت PHP-FPM به‌درستی تنظیم شود.

کانفیگ کامل FastCGI در Nginx

نمونه کانفیگ دقیق‌تر برای ارسال درخواست‌های PHP:

location ~ \.php$ {
    try_files $uri =404;

    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS $https if_not_empty;

    fastcgi_pass unix:/run/php/php8.2-fpm.sock;

    fastcgi_connect_timeout 10s;
    fastcgi_send_timeout 60s;
    fastcgi_read_timeout 60s;

    fastcgi_buffer_size 32k;
    fastcgi_buffers 16 16k;
    fastcgi_busy_buffers_size 64k;
}

دستور try_files $uri =404 از ارسال مسیرهای نامعتبر به PHP جلوگیری می‌کند و یک لایه امنیتی مهم محسوب می‌شود.

فعال‌سازی FastCGI Cache

کش FastCGI می‌تواند پاسخ صفحات PHP را برای مدت مشخصی ذخیره کند و فشار روی PHP-FPM و دیتابیس را کاهش دهد. این قابلیت برای صفحات عمومی و قابل کش مناسب است.

تعریف ناحیه کش

در بخش http فایل nginx.conf قرار دهید:

fastcgi_cache_path /var/cache/nginx/fastcgi
    levels=1:2
    keys_zone=PHP_CACHE:100m
    inactive=60m
    max_size=2g
    use_temp_path=off;

استفاده از کش در Virtual Host

map $request_method $skip_method {
    default 1;
    GET 0;
    HEAD 0;
}

map $request_uri $skip_uri {
    default 0;
    ~*^/wp-admin/ 1;
    ~*^/wp-login.php 1;
    ~*^/cart/ 1;
    ~*^/checkout/ 1;
    ~*^/my-account/ 1;
}

map $http_cookie $skip_cookie {
    default 0;
    ~*wordpress_logged_in 1;
    ~*comment_author 1;
    ~*woocommerce_items_in_cart 1;
}

server {
    ...

    location ~ \.php$ {
        try_files $uri =404;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;

        fastcgi_cache PHP_CACHE;
        fastcgi_cache_methods GET HEAD;
        fastcgi_cache_valid 200 301 302 10m;
        fastcgi_cache_valid 404 1m;

        fastcgi_cache_bypass $skip_method $skip_uri $skip_cookie;
        fastcgi_no_cache $skip_method $skip_uri $skip_cookie;

        add_header X-FastCGI-Cache $upstream_cache_status;
    }
}

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

کش فایل‌های استاتیک و فشرده‌سازی

تنظیم کش مرورگر

location ~* \.(css|js|jpg|jpeg|png|gif|svg|webp|ico|woff|woff2|ttf)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
}

استفاده از immutable زمانی مناسب است که نام فایل‌ها پس از هر تغییر با Hash نسخه‌گذاری شود؛ مانند app.abc123.js.

فعال‌سازی Gzip

gzip on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_vary on;
gzip_proxied any;
gzip_types
    text/plain
    text/css
    text/xml
    application/json
    application/javascript
    application/xml
    application/xml+rss
    image/svg+xml;

فشرده‌سازی Gzip برای فایل‌های متنی مفید است. برای تصاویر و ویدئوهایی که از قبل فشرده شده‌اند، معمولاً تأثیر قابل‌توجهی ندارد.

استفاده از Brotli

در صورت پشتیبانی نسخه Nginx یا استفاده از ماژول مناسب، Brotli می‌تواند برای فایل‌های متنی فشرده‌سازی بهتری نسبت به Gzip ارائه دهد.

brotli on;
brotli_comp_level 5;
brotli_types text/plain text/css application/json application/javascript application/xml image/svg+xml;

راه‌اندازی HTTPS و HTTP/2

HTTPS علاوه بر امنیت، برای قابلیت‌هایی مانند HTTP/2، کوکی‌های امن و بسیاری از امکانات مدرن مرورگر ضروری است.

دریافت گواهی رایگان با Certbot

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com

پس از نصب گواهی، تمدید خودکار را بررسی کنید:

sudo systemctl status certbot.timer
sudo certbot renew --dry-run

نمونه تنظیمات HTTPS

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 10m;

    add_header Strict-Transport-Security "max-age=31536000" always;

    root /var/www/example.com/public;
    index index.php index.html;
}

هدر HSTS را فقط زمانی فعال کنید که تمام زیردامنه‌ها و مسیرهای سایت به‌طور کامل از HTTPS پشتیبانی کنند.

امن‌سازی Nginx و PHP-FPM

جلوگیری از نمایش نسخه سرویس

server_tokens off;

مسدود کردن فایل‌های حساس

location ~ /\.(?!well-known).* {
    deny all;
    access_log off;
    log_not_found off;
}

location ~* \.(env|ini|log|conf|sql|bak|swp)$ {
    deny all;
}

محدود کردن دسترسی به PHP-FPM

اگر از Unix Socket استفاده می‌کنید، سطح دسترسی سوکت را محدود نگه دارید:

listen.owner = www-data
listen.group = www-data
listen.mode = 0660

در صورت استفاده از TCP، پورت PHP-FPM را فقط به IPهای مورد نیاز محدود کنید و آن را به‌صورت عمومی روی اینترنت باز نگذارید.

غیرفعال کردن قابلیت‌های غیرضروری PHP

در فایل php.ini، در صورت نیاز می‌توانید برخی توابع پرخطر یا غیرضروری را غیرفعال کنید:

disable_functions = exec,passthru,shell_exec,system,proc_open,popen

این فهرست باید بر اساس نیاز واقعی نرم‌افزار تنظیم شود؛ زیرا غیرفعال کردن برخی توابع ممکن است باعث اختلال در CMS یا فریم‌ورک شود.

تنظیمات PHP برای محیط Production

expose_php = Off
display_errors = Off
log_errors = On
error_log = /var/log/php/php-error.log
memory_limit = 256M
max_execution_time = 120
max_input_time = 120
post_max_size = 64M
upload_max_filesize = 64M
session.cookie_httponly = 1
session.cookie_secure = 1

نمایش خطاهای PHP در محیط Production باید غیرفعال باشد؛ زیرا ممکن است مسیر فایل‌ها، اطلاعات دیتابیس یا جزئیات داخلی برنامه را افشا کند.

مدیریت Timeoutها

Timeoutهای بیش از حد کوتاه باعث قطع درخواست‌های سالم و Timeoutهای بیش از حد بلند باعث اشغال شدن Workerها می‌شوند.

  • client_header_timeout: زمان دریافت هدر درخواست از کاربر
  • client_body_timeout: زمان دریافت بدنه درخواست و فایل آپلودی
  • fastcgi_connect_timeout: زمان برقراری ارتباط با PHP-FPM
  • fastcgi_read_timeout: زمان انتظار برای پاسخ PHP-FPM
  • request_terminate_timeout: حداکثر زمان اجرای درخواست در PHP-FPM

اگر یک اسکریپت دائماً به زمان اجرای بالایی نیاز دارد، افزایش Timeout تنها راه‌حل نیست. بهتر است منطق برنامه، کوئری‌های دیتابیس و پردازش‌های سنگین بازبینی و کارهای طولانی به صف‌هایی مانند Redis Queue منتقل شوند.

بهینه‌سازی سیستم‌عامل و محدودیت فایل‌ها

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

ulimit -n

برای افزایش محدودیت، فایل زیر را ویرایش کنید:

sudo nano /etc/security/limits.conf
www-data soft nofile 200000
www-data hard nofile 200000

برای سرویس‌های systemd نیز می‌توان محدودیت را در Override سرویس تنظیم کرد:

sudo systemctl edit nginx
[Service]
LimitNOFILE=200000

پس از تغییر تنظیمات:

sudo systemctl daemon-reload
sudo systemctl restart nginx

استفاده از Redis برای کاهش فشار روی PHP و دیتابیس

Redis می‌تواند برای Object Cache، Session Storage، صف پردازش و داده‌های موقت استفاده شود. در سایت‌های وردپرسی و فروشگاه‌های پرترافیک، فعال‌سازی Object Cache معمولاً فشار روی دیتابیس را کاهش می‌دهد.

با این حال، Redis جایگزین طراحی صحیح دیتابیس نیست. ایندکس‌گذاری مناسب، کاهش کوئری‌های غیرضروری و استفاده از Connection Pooling همچنان اهمیت زیادی دارد.

تنظیمات مخصوص وردپرس

برای وردپرس، مسیرهای مدیریتی و فایل‌های خاص باید به‌درستی مدیریت شوند:

location / {
    try_files $uri $uri/ /index.php?$args;
}

location = /xmlrpc.php {
    deny all;
}

location ~* /wp-content/uploads/.*\.php$ {
    deny all;
}

location ~* ^/wp-admin/ {
    try_files $uri $uri/ /index.php?$args;
}

مسدود کردن xmlrpc.php فقط زمانی انجام شود که سایت یا افزونه‌های شما به آن نیاز نداشته باشند. همچنین اجرای PHP در مسیر آپلودها باید تقریباً همیشه ممنوع باشد.

استفاده از Upstream و Load Balancing

در معماری چندسروره می‌توان درخواست‌ها را بین چند Backend تقسیم کرد:

upstream php_backend {
    least_conn;

    server 10.0.0.11:9000 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:9000 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;
    server_name example.com;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass php_backend;
    }
}

برای اجرای موفق این معماری، Sessionها، فایل‌های آپلودی و کش باید در تمام سرورها هماهنگ باشند. استفاده از Redis و فضای ذخیره‌سازی مشترک یا Object Storage در این سناریو اهمیت زیادی دارد.

لاگ‌ها و مانیتورینگ

مشاهده لاگ Nginx

sudo tail -f /var/log/nginx/example-error.log
sudo tail -f /var/log/nginx/example-access.log

مشاهده لاگ PHP-FPM

sudo journalctl -u php8.2-fpm -f
sudo tail -f /var/log/php8.2-fpm.log

شاخص‌های مهم برای بررسی

  • تعداد درخواست در ثانیه
  • میانگین زمان پاسخ‌گویی
  • درصد خطاهای HTTP 4xx و 5xx
  • تعداد Workerهای فعال و Idle در PHP-FPM
  • مصرف CPU و RAM
  • تعداد پردازش‌های در صف
  • زمان اجرای کوئری‌های دیتابیس
  • نرخ Cache Hit و Cache Miss
  • میزان استفاده از دیسک و I/O

ابزارهایی مانند htop، vmstat، iostat، ss، Prometheus، Grafana و سرویس‌های مانیتورینگ ابری می‌توانند دید مناسبی از وضعیت سرور ارائه دهند.

فعال‌سازی Status برای PHP-FPM

برای بررسی وضعیت Pool می‌توانید یک مسیر داخلی برای Status تعریف کنید:

location = /fpm-status {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;

    allow 127.0.0.1;
    deny all;
}

در فایل Pool نیز مقدار زیر را اضافه کنید:

pm.status_path = /fpm-status

این مسیر را به‌صورت عمومی در اینترنت منتشر نکنید؛ زیرا اطلاعاتی درباره وضعیت پردازش‌های PHP-FPM ارائه می‌دهد.

تست فشار و ارزیابی عملکرد

بعد از اعمال تغییرات، عملکرد سایت باید با داده واقعی و تست کنترل‌شده بررسی شود. ابزارهایی مانند ab، wrk، k6 و Apache JMeter برای این کار کاربرد دارند.

نمونه تست با wrk

wrk -t4 -c100 -d30s https://example.com/
  • -t4: تعداد Threadهای تست
  • -c100: تعداد اتصال‌های هم‌زمان
  • -d30s: مدت اجرای تست

تست فشار را روی سایت Production و در ساعات پرترافیک بدون برنامه‌ریزی انجام ندهید. بهتر است ابتدا روی محیط Staging یا سرور جداگانه اجرا شود.

خطاهای رایج در کانفیگ Nginx و PHP-FPM

خطای 502 Bad Gateway

این خطا معمولاً به یکی از دلایل زیر ایجاد می‌شود:

  • PHP-FPM اجرا نشده است.
  • مسیر سوکت در Nginx اشتباه است.
  • دسترسی Nginx به سوکت PHP-FPM وجود ندارد.
  • تمام Workerهای PHP-FPM مشغول هستند.
  • PHP-FPM به دلیل مصرف زیاد حافظه متوقف شده است.
sudo systemctl status php8.2-fpm
ls -l /run/php/
sudo nginx -t
sudo journalctl -u php8.2-fpm -n 100

خطای 504 Gateway Timeout

این خطا معمولاً نشان‌دهنده اجرای طولانی کد PHP، کندی دیتابیس، سرویس خارجی یا Timeout نامناسب است. افزایش Timeout باید آخرین مرحله باشد؛ ابتدا علت کندی را با لاگ و ابزارهای Profiling پیدا کنید.

نمایش متن کد PHP در مرورگر

این مشکل بسیار خطرناک است و معمولاً از کانفیگ ناقص بخش PHP یا نصب نبودن PHP-FPM ناشی می‌شود. مطمئن شوید فایل‌های PHP با Location مناسب به PHP-FPM ارسال می‌شوند و Nginx آن‌ها را به‌عنوان فایل استاتیک ارائه نمی‌کند.

چک‌لیست نهایی بهینه‌سازی

  • استفاده از نسخه به‌روز Nginx، PHP و سیستم‌عامل
  • تنظیم صحیح worker_processes و worker_connections
  • محاسبه اصولی pm.max_children بر اساس RAM واقعی
  • فعال‌سازی OPcache
  • استفاده از Unix Socket در سرورهای تک‌ماشینه
  • فعال‌سازی کش استاتیک و در صورت امکان FastCGI Cache
  • استفاده از Redis برای Object Cache و Sessionها
  • فعال‌سازی HTTPS و HTTP/2
  • مسدود کردن فایل‌های حساس و PHP در مسیر Upload
  • غیرفعال کردن نمایش خطاهای PHP در Production
  • تنظیم مناسب Timeoutها
  • بررسی منظم لاگ‌های Nginx و PHP-FPM
  • تست فشار پس از هر تغییر مهم
  • تهیه نسخه پشتیبان و امکان بازگشت سریع تنظیمات

جمع‌بندی

بهینه‌سازی Nginx و PHP-FPM برای وب‌سایت‌های پرترافیک تنها با افزایش چند عدد در فایل کانفیگ انجام نمی‌شود. عملکرد واقعی به ترکیبی از تنظیمات وب‌سرور، تعداد Workerهای PHP، کیفیت کد، سرعت دیتابیس، استفاده از کش، منابع سخت‌افزاری و مانیتورینگ مداوم بستگی دارد.

بهترین روش این است که تغییرات را مرحله‌به‌مرحله اعمال کنید، پس از هر تغییر با ابزارهای مانیتورینگ و Load Test نتیجه را بسنجید و مقادیر را بر اساس رفتار واقعی سایت تنظیم کنید. یک کانفیگ متعادل و قابل‌اندازه‌گیری، معمولاً بسیار بهتر از تنظیمات تهاجمی و بدون بررسی است.