
به اشتراک بگذارید

به اشتراک بگذارید
نسخه متنباز Nginx نمیتواند یک صفحه را بهتنهایی از کش پاک کند. این را باید قبل از راهاندازی nginx fastcgi cache روی وردپرس دانست. خود کش ساده است: پاسخ PHP روی دیسک میماند و درخواست بعدی بدون اجرای وردپرس جواب میگیرد. فروشگاه چهار چیز لازم دارد: کلید درست، نقشه کوکی، راه پاکسازی و آزمون با هدر X-Cache.
| خط پیکربندی | نسخه رایج | نسخه بازبینیشده | چرا |
|---|---|---|---|
| کلید کش | $scheme$host$request_uri | $scheme$request_method$host$request_uri | درخواست HEAD بدنه خالی برای GET نسازد |
| خط ignore_headers | fastcgi_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 دو دستور در بلوک 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";
keys_zone حدود ۸ هزار کلید جا میدهد؛ ۲۰ مگابایت یعنی حدود ۱۶۰ هزار کلید.max_size، مدیر کش کماستفادهترین دادهها را پاک میکند. پیشفرض inactive ده دقیقه است و اینجا ۶۰ دقیقه شده.$request_method را از کلید حذف نکنید. با کلید بدون متد، سرور آزمایشی یک درخواست HEAD را ذخیره کرد و GET بعدی با برچسب HIT صفحهای صفربایتی گرفت.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
wp-postpass_ و دو کوکی woocommerce_recently_viewed و store_notice در نسخه رایج نیستند. بهای کامل بودن فهرست چند HIT کمتر است.$request_uri نشانی اصلی و رمزشده است، پس /سبد-خرید/ بهشکل %D8%B3… میرسد. اگر نامک شما فرق دارد، شکلش را با python3 -c 'import urllib.parse as u,sys; print(u.quote(sys.argv[1]))' /نامک/ بسازید.fastcgi_cache_valid): فقط کدهای ۲۰۰ و ۳۰۱ نگه داشته میشوند. اگر فقط زمان بنویسید، کدهای ۲۰۰ و ۳۰۱ و ۳۰۲ کش میشوند.
دستور fastcgi_cache_purge در مستندات nginx.org فقط بخشی از اشتراک تجاری است. در نسخه رایگان، پاکسازی nginx fastcgi cache سه راه دارد: عمر کوتاه برای صفحه، ماژول جانبی ngx_cache_purge، یا حذف مستقیم فایل کش با افزونه.
نسخه ذخیرهشده، چاپ صبح روزنامهای که تا چاپ بعد عوض نمیشود و صورتحساب بانکی هیچ خوانندهای در آن نیست، قیمت دیروز را تا پاکسازی بعدی نشان میدهد. صفحه شخصی جایی در کش ندارد.
10m): عدد fastcgi_cache_valid سقف کهنگی قیمت است؛ اگر قیمتها زیاد عوض میشوند، کوتاهترش کنید.use_stale updating و background_update): هنگام بهروزرسانی، nginx نسخه کهنه را میدهد و از نسخه 1.11.10 صفحه را در پسزمینه تازه میکند. با عمر سهثانیهای روی سرور آزمایشی، اولین درخواست بعد از انقضا STALE گرفت و بعدی HIT.fastcgi_cache_lock): فقط یک درخواست ورودی تازه میسازد. بقیه تا fastcgi_cache_lock_timeout با پیشفرض پنج ثانیه صبر میکنند؛ بعد از آن پاسخ از PHP میآید و ذخیره نمیشود.افزونه 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";
}
fastcgi_cache_purge PURGE from 127.0.0.1 روی سرور آزمایشی برای صفحه کششده 404 داد، چون درخواست PURGE کلیدی با کلمه PURGE میسازد. درخواست GET به /purge/ همان کلید را ساخت و 200 گرفت.allow و deny): بدون آنها هر کسی کش را خالی میکند. اگر درخواست افزونه از IP عمومی خود سرور میرسد، آن IP را از لاگ دسترسی به فهرست اضافه کنید./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 سادهترین راه دیدن کار 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
-I درخواست HEAD میفرستد که بهخاطر متد درون کلید، ورودی جدا دارد. آزمون را با GET و -D - بگیرید.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 گرفت یا چیز دیگری؟