نسخه متن‌باز Nginx نمی‌تواند یک صفحه را به‌تنهایی از کش پاک کند. این را باید قبل از راه‌اندازی nginx fastcgi cache روی وردپرس دانست. خود کش ساده است: پاسخ PHP روی دیسک می‌ماند و درخواست بعدی بدون اجرای وردپرس جواب می‌گیرد. فروشگاه چهار چیز لازم دارد: کلید درست، نقشه کوکی، راه پاکسازی و آزمون با هدر X-Cache.

خط پیکربندینسخه رایجنسخه بازبینی‌شدهچرا
کلید کش$scheme$host$request_uri$scheme$request_method$host$request_uriدرخواست HEAD بدنه خالی برای GET نسازد
خط ignore_headersfastcgi_ignore_headers Cache-Control Expires Set-Cookieحذف کامل این خطهدرهای no-cache و Set-Cookie دوباره اثر کنند
استثناهافقط کوکی ورود وردپرسپنج کوکی ووکامرس، کوکی رمز نوشته، نامک فارسی برگه‌هاسبد هیچ‌کس در کش ننشیند
صفحه منقضیبدون fastcgi_cache_use_staleحالت updating به‌همراه به‌روزرسانی پس‌زمینههجوم هم‌زمان به PHP نرسد
پاکسازیمتد PURGE در همان locationمسیر جدای /purge/ یا حذف فایلمتد PURGE کلید دیگری می‌سازد
آزمونcurl -Iدرخواست GET با -D -درخواست HEAD ورودی جدا دارد

💡 مرز کش در فروشگاه

خروجی HTML صفحه‌های عمومی، با کلیدی از نشانی و متد درخواست.
✅ درخواستی که کوکی ورود، رمز نوشته یا سبد دارد، نه از کش بخواند و نه در آن بنویسد.
✅ نتیجه‌های «سرور آزمایشی» از همین کانفیگ نهایی روی nginx 1.24.0 آمده‌اند.

کانفیگ کش معمولاً روز اول بی‌دردسر کار می‌کند. خرابی بعدتر می‌رسد و دو چهره دارد: قیمتی که بعد از ویرایش عوض نمی‌شود و صفحه‌ای شخصی که به دست غریبه می‌افتد. نقشه کوکی همان فهرستی را اجرا می‌کند که بهینه سازی ووکامرس روی سرور از کش بیرون گذاشته است.

nginx fastcgi cache، مسیر درخواست از Nginx تا PHP-FPM با برچسب‌های MISS و HIT و BYPASS

کلید کش و مسیر ذخیره را پیش از هر چیز بازبینی کنید

پایه nginx fastcgi cache دو دستور در بلوک http است: fastcgi_cache_path و fastcgi_cache_key. روی Ubuntu فایل‌های /etc/nginx/conf.d/ داخل همین بلوک خوانده می‌شوند. این سه خط را در /etc/nginx/conf.d/wp-cache.conf بگذارید.

fastcgi_cache_path /var/cache/nginx/wp levels=1:2 keys_zone=wpcache:20m
                   max_size=2g inactive=60m use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
  1. یادداشت ۱ (خط ۱): به گفته مستندات ماژول fastcgi در nginx.org هر مگابایت keys_zone حدود ۸ هزار کلید جا می‌دهد؛ ۲۰ مگابایت یعنی حدود ۱۶۰ هزار کلید.
  2. یادداشت ۲ (خط ۲): نسخه رایج سقف حجم ندارد. با max_size، مدیر کش کم‌استفاده‌ترین داده‌ها را پاک می‌کند. پیش‌فرض inactive ده دقیقه است و اینجا ۶۰ دقیقه شده.
  3. یادداشت ۳ (خط ۳): متغیر $request_method را از کلید حذف نکنید. با کلید بدون متد، سرور آزمایشی یک درخواست HEAD را ذخیره کرد و GET بعدی با برچسب HIT صفحه‌ای صفربایتی گرفت.
  4. یادداشت ۴ (خط حذف‌شده): نسخه رایج اینجا fastcgi_ignore_headers Cache-Control Expires Set-Cookie دارد؛ حذفش کنید. nginx پاسخ دارای Set-Cookie یا هدر no-cache را کش نمی‌کند و ووکامرس روی سبد، تسویه و حساب همین هدر را می‌فرستد. با این خط، بازدیدکننده دوم کوکی wp_woocommerce_session_ بازدیدکننده اول را با HIT گرفت.

ووکامرس سبد هر مشتری را از روی کوکی پیدا می‌کند. برای همین، استثناهای nginx fastcgi cache در فروشگاه اول روی کوکی بنا می‌شوند و نشانی برگه‌ها پشتیبان است. راهنمای کش در مستندات ووکامرس پنج کوکی را نام می‌برد و هر پنج در نقشه زیر هستند. دو نقشه را به انتهای همان فایل wp-cache.conf اضافه کنید، چون map فقط در بلوک http مجاز است.

⚠️ نشت داده از راه کش صفحه

اگر صفحه حساب، سبد یا نوشته رمزدار بازشده ذخیره شود، محتوای آن به بازدیدکننده بعدی می‌رسد. پاکسازی بعدی این را جبران نمی‌کند؛ صفحه دیده شده است.

map $http_cookie $skip_by_cookie {
    default 0;
    "~*wordpress_logged_in_|wp-postpass_|comment_author_" 1;
    "~*woocommerce_cart_hash|woocommerce_items_in_cart|wp_woocommerce_session_" 1;
    "~*woocommerce_recently_viewed|store_notice" 1;
}

map $request_uri $skip_by_uri {
    default 0;
    "~^/(cart|checkout|my-account|wc-api|logout|lost-password)(/|\?|$)" 1;
    "~*^/%D8%B3%D8%A8%D8%AF-%D8%AE%D8%B1%DB%8C%D8%AF(/|\?|$)" 1;
    "~*^/%D8%AA%D8%B3%D9%88%DB%8C%D9%87-%D8%AD%D8%B3%D8%A7%D8%A8(/|\?|$)" 1;
    "~*^/%D8%AD%D8%B3%D8%A7%D8%A8-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%DB%8C(/|\?|$)" 1;
    "~^/(wp-admin/|wp-login\.php|xmlrpc\.php)" 1;
}

🔸 چرا هر سه متغیر در دو دستور تکرار می‌شوند

دستور fastcgi_cache_bypass مانع خواندن از کش است و fastcgi_no_cache مانع ذخیره. هر دو با هر مقدار غیرخالی و غیرصفر فعال می‌شوند. nginx.org استفاده هم‌زمانشان را مجاز می‌داند. متغیر $is_args برای نشانی پارامتردار علامت سؤال است؛ پس ?add-to-cart= هم بیرون می‌ماند.

بلوک بعدی جای location ~ \.php$ فعلی فایل سایت را می‌گیرد؛ آن را جایگزین کنید، نه اضافه. nginx اولین location باقاعده منطبق را برمی‌دارد و بلوک دوم بی‌صدا بی‌اثر می‌ماند.

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

    fastcgi_cache wpcache;
    fastcgi_cache_valid 200 301 10m;
    fastcgi_cache_bypass $skip_by_cookie $skip_by_uri $is_args;
    fastcgi_no_cache     $skip_by_cookie $skip_by_uri $is_args;
    fastcgi_cache_use_stale error timeout updating http_500 http_503;
    fastcgi_cache_background_update on;
    fastcgi_cache_lock on;
    add_header X-Cache $upstream_cache_status always;
}
sudo nginx -t && sudo systemctl reload nginx
  1. یادداشت ۵ (نقشه اول): کوکی رمز نوشته wp-postpass_ و دو کوکی woocommerce_recently_viewed و store_notice در نسخه رایج نیستند. بهای کامل بودن فهرست چند HIT کمتر است.
  2. یادداشت ۶ (نقشه دوم): متغیر $request_uri نشانی اصلی و رمزشده است، پس /سبد-خرید/ به‌شکل %D8%B3… می‌رسد. اگر نامک شما فرق دارد، شکلش را با python3 -c 'import urllib.parse as u,sys; print(u.quote(sys.argv[1]))' /نامک/ بسازید.
  3. یادداشت ۷ (fastcgi_cache_valid): فقط کدهای ۲۰۰ و ۳۰۱ نگه داشته می‌شوند. اگر فقط زمان بنویسید، کدهای ۲۰۰ و ۳۰۱ و ۳۰۲ کش می‌شوند.

پاکسازی کش در نسخه متن‌باز Nginx چطور ممکن است؟

پاکسازی کش در نسخه متن‌باز Nginx چطور ممکن است؟

دستور fastcgi_cache_purge در مستندات nginx.org فقط بخشی از اشتراک تجاری است. در نسخه رایگان، پاکسازی nginx fastcgi cache سه راه دارد: عمر کوتاه برای صفحه، ماژول جانبی ngx_cache_purge، یا حذف مستقیم فایل کش با افزونه.

نسخه ذخیره‌شده، چاپ صبح روزنامه‌ای که تا چاپ بعد عوض نمی‌شود و صورت‌حساب بانکی هیچ خواننده‌ای در آن نیست، قیمت دیروز را تا پاکسازی بعدی نشان می‌دهد. صفحه شخصی جایی در کش ندارد.

عمر کوتاه، با سرو نسخه کهنه هنگام به‌روزرسانی

  1. یادداشت ۸ (10m): عدد fastcgi_cache_valid سقف کهنگی قیمت است؛ اگر قیمت‌ها زیاد عوض می‌شوند، کوتاه‌ترش کنید.
  2. یادداشت ۹ (use_stale updating و background_update): هنگام به‌روزرسانی، nginx نسخه کهنه را می‌دهد و از نسخه 1.11.10 صفحه را در پس‌زمینه تازه می‌کند. با عمر سه‌ثانیه‌ای روی سرور آزمایشی، اولین درخواست بعد از انقضا STALE گرفت و بعدی HIT.
  3. یادداشت ۱۰ (fastcgi_cache_lock): فقط یک درخواست ورودی تازه می‌سازد. بقیه تا fastcgi_cache_lock_timeout با پیش‌فرض پنج ثانیه صبر می‌کنند؛ بعد از آن پاسخ از PHP می‌آید و ذخیره نمی‌شود.

ماژول ngx_cache_purge و افزونه Nginx Helper

افزونه Nginx Helper در مخزن وردپرس بعد از ویرایش نوشته یا تأیید دیدگاه پاکسازی می‌کند. برای ووکامرس هم گزینه Purge product cache on updates دارد. در تنظیماتش Enable Purge را روشن و Caching Method را روی گزینه Fastcgi cache بگذارید. برای Purge Method دو انتخاب مناسب هست.

گزینه Delete local server cache files ماژولی نمی‌خواهد. شرطش وردپرس و کش روی یک سرور، levels=1:2 و همین کلید $scheme$request_method$host$request_uri است که کانفیگ بالا دارد. گزینه پیش‌فرض Using a GET request to PURGE/url به ماژول ngx_cache_purge از FRiCKLE نیاز دارد. این ماژول روی Ubuntu 24.04 با بسته نسخه 2.3 از مخزن universe نصب می‌شود:

sudo apt install libnginx-mod-http-cache-purge
location ~ ^/purge(/.*) {
    allow 127.0.0.1;
    deny all;
    fastcgi_cache_purge wpcache "$scheme$request_method$host$1";
}
  1. یادداشت ۱۱ (مسیر جدا): شکل کوتاه fastcgi_cache_purge PURGE from 127.0.0.1 روی سرور آزمایشی برای صفحه کش‌شده 404 داد، چون درخواست PURGE کلیدی با کلمه PURGE می‌سازد. درخواست GET به /purge/ همان کلید را ساخت و 200 گرفت.
  2. یادداشت ۱۲ (allow و deny): بدون آن‌ها هر کسی کش را خالی می‌کند. اگر درخواست افزونه از IP عمومی خود سرور می‌رسد، آن IP را از لاگ دسترسی به فهرست اضافه کنید.
  3. یادداشت ۱۳ (مسیر پوشه): پیش‌فرض افزونه /var/run/nginx-cache/ است؛ با ثابت RT_WP_NGINX_HELPER_CACHE_PATH در wp-config.php آن را /var/cache/nginx/wp/ کنید. برای حذف فایل و Purge All، کاربر PHP-FPM باید در این پوشه اجازه نوشتن داشته باشد. کش افزونه و مرورگر بیرون از این پوشه‌اند؛ برای آن‌ها سراغ روش‌های پاک کردن کش وردپرس بروید.

⚠️ ماژول جانبی با هر ارتقای nginx دوباره آزموده شود

ماژول ngx_cache_purge جزو کد nginx نیست و آخرین سال حق نشر مخزن اصلی آن 2014 است. بسته اوبونتو به nginx-abi-1.24.0-1 وابسته است، یعنی برای nginx همان مخزن ساخته شده. با nginx مخزن دیگر یا کامپایل‌شده، بعد از هر ارتقا nginx -t را بگیرید.

هدر X-Cache وضعیت واقعی هر درخواست را می‌گوید

هدر X-Cache وضعیت واقعی هر درخواست را می‌گوید

هدر X-Cache ساده‌ترین راه دیدن کار nginx fastcgi cache از بیرون سرور است. خط add_header در بلوک PHP مقدار $upstream_cache_status را می‌فرستد. مستندات ماژول upstream هفت مقدار برایش می‌شمارد: HIT، MISS، BYPASS، STALE، UPDATING، EXPIRED و REVALIDATED.

curl -s -o /dev/null -D - https://example.com/product/green-mug/ | grep -i x-cache
curl -s -o /dev/null -D - https://example.com/cart/ | grep -i x-cache

🔸 خروجی curl روی سرور آزمایشی

صفحه محصول، بار اول: X-Cache: MISS
همان صفحه، بار دوم: X-Cache: HIT
هر یک از هشت کوکی نقشه: X-Cache: BYPASS
برگه /cart/، نامک رمزشده /سبد-خرید/ و ?add-to-cart=12: X-Cache: BYPASS
همان صفحه کش‌شده با curl -I: X-Cache: MISS

  1. یادداشت ۱۴ (سطر آخر جعبه): گزینه -I درخواست HEAD می‌فرستد که به‌خاطر متد درون کلید، ورودی جدا دارد. آزمون را با GET و -D - بگیرید.
  2. یادداشت ۱۵ (ارث‌بری): اگر location خودش add_header داشته باشد، هدرهای سطح server به آن نمی‌رسند. هدرهای امنیتی را در همین location تکرار کنید؛ add_header_inherit از نسخه 1.29.3 آمده و در nginx 1.24 نیست.

«قیمت را صبح عوض کردم، ولی صفحه محصول هنوز عدد دیروز را نشان می‌دهد.» ویراستار فروشگاه معمولاً همین را در هفته اول کش می‌فرستد. جوابش با شما، مدیر سرور، است.

چرا قیمت تازه محصول بعد از ویرایش هنوز قدیمی دیده می‌شود؟

نسخه ذخیره‌شده تا پایان fastcgi_cache_valid یا تا پاکسازی سرو می‌شود. Nginx Helper با یکی از دو روش Purge Method بعد از ذخیره محصول آن را پاک می‌کند.

نه. کوکی wordpress_logged_in_ بای‌پس را فعال می‌کند. نسخه مهمان را در پنجره خصوصی یا با curl ببینید.

بله. گزینه Delete local server cache files در Nginx Helper فایل همان صفحه را حذف می‌کند؛ شرطش سرور مشترک و همین کلید کش است.

با $request_method در کلید، درخواست PURGE کلید دیگری می‌سازد. از مسیر /purge/ استفاده کنید؛ 404 در آن مسیر یعنی نشانی در کش نبوده است.

متغیر $host صفحه‌ها را جدا نگه می‌دارد، ولی خالی کردن پوشه مشترک کش همه را پاک می‌کند. ناحیه و پوشه جدا ساده‌تر است.

نه. جست‌وجوی وردپرس نشانی‌ای با ?s= می‌سازد و $is_args هر نشانی پارامتردار را بای‌پس می‌کند.

دستور add_header بدون always فقط روی کدهای موفق و تغییر مسیر اعمال می‌شود. با always روی 404 و 502 هم می‌آید.

جمع‌بندی؛ رأی بازبین، ادغام پس از اصلاح خط‌های مردود: کلید بدون متد، خط ignore_headers، استثنایی که فقط کوکی ورود را می‌شناسد و پاکسازی با متد PURGE. سه تای آن‌ها روی سرور آزمایشی خطای واقعی ساختند: صفحه خالی، کوکی جلسه مشتری دیگر و پاسخ 404. پیش از روشن کردن nginx fastcgi cache روی فروشگاه اصلی، این چهار خط را در کانفیگ خودتان پیدا کنید. نسخه بازبینی‌شده پنج کوکی ووکامرس و نامک فارسی برگه‌ها را بیرون نگه می‌دارد. پاکسازی را هم فقط از خود سرور می‌پذیرد. آخرین قدم آزمون دوخطی curl است: برگه سبد BYPASS، صفحه محصول در بار دوم HIT.

🚀 درخواست‌های BYPASS مستقیم به PHP می‌رسند

صفحه‌های سبد و تسویه حساب هر بار از نو ساخته می‌شوند. ظرفیت فروشگاه در ساعت پرسفارش را همین درخواست‌ها می‌سنجند.

برگه سبد خرید فروشگاهتان در آزمون curl برچسب BYPASS گرفت یا چیز دیگری؟

وب داده
وب داده

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

مقاله‌ها: 285
پاسخی بگذارید

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