بهینه سازی Nginx: gzip، HTTP/2 و کش

برای بهینه سازی Nginx چند تنظیم کم‌ریسک بیشترین اثر را دارند: فشرده‌سازی gzip برای متن، فعال کردن HTTP/2، کش مرورگر برای فایل‌های ایستا، تنظیم تعداد Worker و اتصال‌ها و باز نگه‌داشتن اتصال‌ها با keepalive. بعد از هر تغییر، با nginx -t تنظیم را بررسی و با reload اعمال کنید و اثر را با curl یا ابزار سرعت اندازه بگیرید؛ بهینه‌سازی بدون اندازه‌گیری حدس است.

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

مرحله اول: اندازه‌گیری پیش از بهینه‌سازی Nginx

پیش از تغییر، اعداد پایه را ثبت کنید تا بعداً مقایسه کنید:

curl -s -o /dev/null -w "ttfb=%{time_starttransfer}s total=%{time_total}s size=%{size_download}\n" https://example.com/
curl -sI -H "Accept-Encoding: gzip" https://example.com/ | grep -i content-encoding
nginx -V 2>&1 | head -2

ttfb زمان رسیدن اولین بایت است. اگر content-encoding: gzip نمی‌بینید، فشرده‌سازی خاموش است. نسخه Nginx را هم یادداشت کنید، چون سینتکس HTTP/2 به آن بستگی دارد.

مرحله دوم: Worker و اتصال‌ها

در /etc/nginx/nginx.conf:

worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    multi_accept on;
}

مقدار auto تعداد Worker را برابر هسته‌های CPU می‌گذارد که پیش‌فرض خوبی است. هر Worker می‌تواند تا worker_connections اتصال هم‌زمان باز نگه دارد. حداکثر اتصال تقریبی برابر ضرب این دو عدد است. محدودیت فایل باز سیستم را هم بررسی کنید: ulimit -n.

مرحله سوم: فشرده‌سازی gzip

در بخش http:

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

نکته‌ها:

  • gzip_comp_level 5 تعادل خوبی بین نسبت فشرده‌سازی و CPU است. عددهای بالاتر سود کم و هزینه بیشتر دارند.
  • تصاویر JPEG، PNG و WebP و فایل‌های ZIP را فشرده نکنید؛ از قبل فشرده‌اند.
  • text/html همیشه فشرده می‌شود و نیازی به ذکر در gzip_types نیست.

بعد از اعمال، دوباره curl -sI -H "Accept-Encoding: gzip" را اجرا کنید و content-encoding: gzip ببینید. Brotli فشرده‌سازی بهتری دارد ولی ماژول جداگانه می‌خواهد و در بسته پیش‌فرض Nginx نیست.

مرحله چهارم: فعال کردن HTTP/2

HTTP/2 چند درخواست را روی یک اتصال انجام می‌دهد و برای صفحه‌های پر از فایل سریع‌تر است. سینتکس به نسخه بستگی دارد:

# Nginx 1.25.1 و جدیدتر
server {
    listen 443 ssl;
    http2 on;
}

# نسخه‌های قدیمی‌تر
server {
    listen 443 ssl http2;
}

HTTP/2 در مرورگرها فقط روی HTTPS استفاده می‌شود، پس گواهی SSL لازم است؛ نصب آن در نصب SSL رایگان آمده است. برای بررسی، curl -sI --http2 https://example.com/ | head -1 باید HTTP/2 200 نشان دهد.

مرحله پنجم: کش مرورگر برای فایل‌های ایستا

فایل‌هایی که کم تغییر می‌کنند (تصویر، CSS، JS، فونت) را برای مدت طولانی کش کنید:

location ~* \.(?:css|js|jpg|jpeg|png|gif|webp|svg|woff2|ico)$ {
    expires 30d;
    add_header Cache-Control "public, max-age=2592000, immutable";
    access_log off;
    try_files $uri =404;
}

اگر نام فایل‌ها با تغییر محتوا عوض می‌شود (مثل app.3f2a1.js)، می‌توانید مدت را یک سال بگذارید. برای فایل‌هایی با نام ثابت، مدت کوتاه‌تر انتخاب کنید تا تغییرات دیر نرسند. صفحه HTML را طولانی کش نکنید، مگر اینکه کش سرور را برای آن مدیریت کنید.

مرحله ششم: بهینه‌سازی Nginx با keepalive و بافرها

keepalive_timeout 30s;
keepalive_requests 1000;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
client_max_body_size 64m;
server_tokens off;

معنی‌ها:

  • keepalive_timeout: مدت باز نگه‌داشتن اتصال بیکار. عدد بسیار بالا اتصال‌ها را بی‌دلیل نگه می‌دارد.
  • sendfile و tcp_nopush: ارسال فایل ایستا را کارآمدتر می‌کنند.
  • client_max_body_size: حداکثر اندازه آپلود. با نیاز سایت (مثلاً رسانه وردپرس) هماهنگ باشد.
  • server_tokens off: نسخه Nginx را در هدر و صفحه خطا پنهان می‌کند.

مرحله هفتم: کش FastCGI برای صفحه‌های پویا

برای وردپرس و PHP، کش صفحه در Nginx بار PHP را به‌شدت کم می‌کند:

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=PHPCACHE:100m inactive=60m;

server {
    set $skip_cache 0;
    if ($request_method = POST) { set $skip_cache 1; }
    if ($http_cookie ~* "wordpress_logged_in") { set $skip_cache 1; }

    location ~ \.php$ {
        fastcgi_cache PHPCACHE;
        fastcgi_cache_valid 200 10m;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        add_header X-Cache $upstream_cache_status;
    }
}

این فقط الگوی ساده است. صفحه‌های کاربر وارد‌شده، سبد خرید و فرم‌ها نباید کش شوند؛ قاعده‌ها را برای سایت خودتان با دقت بسنجید. سرصفحه X-Cache نشان می‌دهد پاسخ از کش بوده (HIT) یا نه (MISS). اگر کش را هنگام کار با Cloudflare هم دارید، تعامل دو لایه را بررسی کنید.

اعمال و آزمایش

sudo nginx -t
sudo systemctl reload nginx
curl -s -o /dev/null -w "ttfb=%{time_starttransfer}s total=%{time_total}s\n" https://example.com/

دوباره همان اندازه‌گیری مرحله اول را انجام دهید. اگر چیزی خراب شد، تغییر را برگردانید. نسخه پشتیبان از nginx.conf بگیرید: sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.

خطاهای رایج

نشانهعلت و راه حل
nginx -t خطا می‌دهدخطای نگارشی یا دستور در بخش اشتباه؛ پیام شماره خط را نشان می‌دهد
gzip کار نمی‌کندgzip_types نوع محتوا را شامل نمی‌شود یا فایل کوچک‌تر از gzip_min_length است
http2 on را نمی‌شناسدنسخه Nginx قدیمی است؛ از listen 443 ssl http2 استفاده کنید
تغییر CSS دیده نمی‌شودکش طولانی مرورگر؛ نام فایل را نسخه‌دار کنید
کاربر وارد‌شده صفحه دیگری را می‌بیندقانون کش FastCGI کوکی ورود را کنار نمی‌گذارد
آپلود فایل بزرگ خطای 413 می‌دهدclient_max_body_size کم است

سوالات متداول

آیا باید همه تنظیم‌ها را کپی کنم؟

نه. اول اندازه بگیرید و تنظیم‌ها را یکی‌یکی اعمال کنید تا بدانید کدام اثر داشته. بیشتر سایت‌ها با gzip، HTTP/2 و کش ایستا به بخش بزرگ سود می‌رسند.

فرق کش مرورگر و کش FastCGI چیست؟

کش مرورگر فایل را سمت کاربر نگه می‌دارد. کش FastCGI پاسخ PHP را روی سرور نگه می‌دارد تا PHP هر بار اجرا نشود.

آیا HTTP/3 هم لازم است؟

HTTP/3 (QUIC) در نسخه‌های جدید Nginx پشتیبانی می‌شود ولی فعال‌سازی آن به پورت UDP و تنظیمات بیشتر نیاز دارد. برای اغلب سایت‌ها HTTP/2 کافی است.

چطور بدانم کدام تنظیم اثر داشت؟

ttfb و زمان کل را قبل و بعد با curl اندازه بگیرید، و برای صفحه کامل از ابزار سنجش سرعت یا ابزارهای مرورگر استفاده کنید.

منابع

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *