Nginx FastCGI Cache เร่งความเร็ว WordPress บน VPS
Nginx FastCGI Cache คือระบบ cache ที่ Nginx เก็บผลลัพธ์จาก PHP-FPM ไว้บน disk แล้วส่ง response ครั้งถัดไปโดยตรงโดยไม่แตะ PHP หรือ MySQL เลย สำหรับ WordPress ที่มีผู้ใช้เยอะ การเปิด FastCGI Cache ลด CPU load ได้ 60-90% และทำให้ TTFB (Time to First Byte) เหลือต่ำกว่า 10ms
หลักการทำงาน FastCGI Cache
ปกติทุก request ที่เข้ามา Nginx ส่งไปให้ PHP-FPM ประมวลผล ดึง database ใหม่ สร้าง HTML แล้วส่งกลับ — ใช้เวลา 100–500ms ต่อ request เมื่อเปิด FastCGI Cache Nginx จะ:
- ตรวจว่า request นี้มี cache อยู่ไหม
- ถ้ามี → ส่ง cached response ทันที (ข้าม PHP และ DB)
- ถ้าไม่มี หรือ expired → ส่งไปให้ PHP-FPM แล้วเก็บผล cache ไว้
ตั้งค่า FastCGI Cache ใน nginx.conf
# ใส่ใน http{} block ของ /etc/nginx/nginx.conf
fastcgi_cache_path /var/cache/nginx/fastcgi_cache
levels=1:2
keys_zone=WORDPRESS:100m
max_size=1g
inactive=60m
use_temp_path=off;
# สร้าง directory สำหรับ cache
sudo mkdir -p /var/cache/nginx/fastcgi_cache
sudo chown www-data:www-data /var/cache/nginx/fastcgi_cache
ตั้งค่า Server Block สำหรับ WordPress
# /etc/nginx/sites-available/example.com
# กำหนด cache key และ bypass rules ใน server block
set $skip_cache 0;
# ไม่ cache POST requests
if ($request_method = POST) { set $skip_cache 1; }
# ไม่ cache เมื่อมี query string (เช่น ?s= search)
if ($query_string != "") { set $skip_cache 1; }
# ไม่ cache หน้า admin และ login
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
set $skip_cache 1;
}
# ไม่ cache เมื่อ user ล็อกอินอยู่ หรือมี comment cookie
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# FastCGI Cache settings
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 60m;
fastcgi_cache_use_stale error timeout invalid_header updating http_500;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
# เพิ่ม header เพื่อ debug ว่า cache HIT หรือ MISS
add_header X-FastCGI-Cache $upstream_cache_status;
}
Purge Cache เมื่อโพสต์ใหม่หรืออัพเดท
WordPress ต้อง clear cache เมื่อมีการเผยแพร่โพสต์ใหม่ ใช้ plugin Nginx Cache (Purge Cache) ร่วมกับ ngx_cache_purge module:
# ตรวจว่ามี purge module
nginx -V 2>&1 | grep purge
# ถ้าไม่มี ติดตั้ง nginx-extras
sudo apt install nginx-extras
# เพิ่มใน server block
location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
allow 127.0.0.1;
deny all;
}
# purge cache ด้วยมือ (ล้างทั้งหมด)
sudo rm -rf /var/cache/nginx/fastcgi_cache/*
sudo systemctl reload nginx
Proxy Cache สำหรับ Node.js / Backend App
ถ้าใช้ Nginx เป็น reverse proxy ให้ backend app สามารถ cache response แบบ Proxy Cache ได้เช่นกัน:
# ใน http{} block
proxy_cache_path /var/cache/nginx/proxy_cache
levels=1:2
keys_zone=BACKEND:50m
max_size=500m
inactive=30m;
# ใน server block
location /api/ {
proxy_pass http://localhost:3000;
proxy_cache BACKEND;
proxy_cache_valid 200 5m;
proxy_cache_key "$host$request_uri";
proxy_cache_bypass $http_pragma $http_authorization;
add_header X-Proxy-Cache $upstream_cache_status;
}
curl -I https://example.com/ แล้วดู header X-FastCGI-Cache: HIT ถ้าได้ MISS หรือ BYPASS ทุกครั้งแสดงว่า cache ไม่ทำงาน ให้ตรวจสอบ $skip_cache conditions
ตรวจสอบว่า Nginx Cache ทำงานถูกต้อง
# ดู cache status จาก response header
curl -sI https://example.com/ | grep -i cache
# ทดสอบ 3 ครั้งติดกัน ครั้งแรกควรเป็น MISS ครั้งที่ 2-3 เป็น HIT
for i in 1 2 3; do curl -sI https://example.com/ | grep "X-FastCGI-Cache"; done
# ดูขนาด cache ที่เก็บไว้
du -sh /var/cache/nginx/fastcgi_cache/
# ตรวจสอบ error log ว่าไม่มีปัญหา
tail -50 /var/log/nginx/error.log | grep -i cache
ab -n 1000 -c 10 https://example.com/ (Apache Bench) ทดสอบ throughput ก่อน/หลังเปิด cache — ควรเห็น request/sec เพิ่มขึ้นอย่างน้อย 3-5 เท่า
แก้ปัญหาที่พบบ่อย
Error: "permission denied" เมื่อ Nginx เขียน cache
Nginx worker process ต้องมีสิทธิ์เขียน cache directory:
# ดู user ที่ nginx worker run ด้วย
ps aux | grep nginx
# บรรทัดที่ไม่ใช่ root คือ worker — ปกติ www-data
# แก้ permission
sudo chown -R www-data:www-data /var/cache/nginx/
sudo chmod -R 755 /var/cache/nginx/
nginx -t && systemctl reload nginx
Cache ไม่ clear เมื่อ publish โพสต์ใหม่ใน WordPress
ต้องติดตั้ง plugin ที่รองรับ Nginx FastCGI Cache purge เช่น "Nginx Helper" และตั้งค่า purge URL ให้ตรงกับ server:
# ติดตั้ง wp-cli แล้วติดตั้ง plugin ผ่าน command line
wp plugin install nginx-helper --activate
# ตรวจสอบว่า purge endpoint ทำงาน
curl -X PURGE https://example.com/
# ควรได้ HTTP 200 Successful purge
หน้าเว็บแสดงข้อมูลเก่า (stale content) หลังอัพเดท
Cache TTL ที่ตั้งไว้อาจนานเกินไป หรือ bypass conditions ไม่ครอบผู้ใช้ที่ล็อกอิน:
# ล้าง cache ทั้งหมดด้วยมือ
sudo find /var/cache/nginx/fastcgi_cache/ -type f -delete
sudo systemctl reload nginx
# ลด TTL ลงเหลือ 15 นาทีสำหรับเว็บที่อัพเดทบ่อย
fastcgi_cache_valid 200 15m;
Nginx ไม่ cache เลย ทุก request เป็น BYPASS
เกิดจาก $skip_cache มีค่าเป็น 1 ตลอด ตรวจสอบว่า cookie หรือ query string ทำให้ skip ทุก request:
# เพิ่ม debug header เพื่อดูค่า skip_cache
add_header X-Skip-Cache $skip_cache;
# ทดสอบ request แบบ clean (ไม่มี cookie)
curl -sI https://example.com/ --cookie "" | grep -i "cache\|skip"
คำถามที่พบบ่อย
FastCGI Cache ต่างจาก Redis Object Cache อย่างไร?
FastCGI Cache เก็บ HTML output ทั้งหน้า (full-page cache) บน disk — ข้าม PHP และ MySQL ทั้งหมด Redis Object Cache เก็บ database query results ใน RAM — ยังต้องผ่าน PHP แต่ลด DB load FastCGI Cache เร็วกว่ามากสำหรับ anonymous visitors ส่วน Redis เหมาะกับผู้ใช้ที่ login อยู่ที่ FastCGI bypass ไม่ได้ cache
Cache size ควรตั้งไว้เท่าไหร่?
สำหรับ WordPress ทั่วไป 1-2GB เพียงพอ ใน fastcgi_cache_path ตั้ง max_size=2g Nginx จะลบ file เก่าอัตโนมัติเมื่อใกล้เต็ม ดูขนาด disk จริงที่ใช้ด้วย du -sh /var/cache/nginx/
เว็บที่ต้องการ personalization (ตะกร้าสินค้า, ล็อกอิน) ใช้ FastCGI Cache ได้ไหม?
ได้ แต่ต้องตั้ง bypass ให้ถูกต้อง ใน WooCommerce เพิ่มการ bypass เมื่อมี cookie woocommerce_cart_hash หรือ woocommerce_items_in_cart เพื่อไม่ให้ user เห็น cart ของคนอื่น