เร่งความเร็ว WordPress บน VPS ด้วย PHP-FPM, OPcache และ Redis
WordPress บน VPS ที่ตั้งค่าดีสามารถโหลดได้ภายใน 200–500ms แต่ถ้าตั้งค่าผิดหรือไม่ได้ตั้งค่าเลยอาจใช้เวลา 3–5 วินาที บทความนี้ครอบคลุมทุก layer ที่ควรปรับ
Layer 1: PHP-FPM แทน mod_php
ถ้ายังใช้ Apache กับ mod_php ให้เปลี่ยนมาใช้ PHP-FPM แทน PHP-FPM รัน PHP เป็น pool แยกออกจาก Apache ลด memory footprint และรองรับ concurrent request ได้ดีกว่า
apt install php8.3-fpm
# ใน Apache เปิด module
a2enmod proxy_fcgi setenvif
a2enconf php8.3-fpm
systemctl restart apache2
Layer 2: OPcache ลดการ compile PHP ซ้ำ
ทุกครั้งที่ PHP รัน script มันต้อง parse และ compile ก่อน OPcache เก็บผลลัพธ์ไว้ใน RAM ทำให้ไม่ต้อง compile ซ้ำในทุก request
เพิ่มใน /etc/php/8.3/fpm/php.ini:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=0
opcache.validate_timestamps=0 ; ปิดเพื่อ performance สูงสุด (ต้อง clear cache เมื่อ deploy)
Layer 3: Redis Object Cache
WordPress query database ทุก request แม้ข้อมูลนั้นไม่เปลี่ยน Redis ช่วย cache ผลลัพธ์ database ใน RAM
apt install redis-server php-redis
systemctl enable redis-server
ติดตั้ง plugin Redis Object Cache แล้วเพิ่มใน wp-config.php:
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_CACHE', true);
Layer 4: Nginx FastCGI Cache
สำหรับ visitor ที่ไม่ได้ login Nginx สามารถ serve HTML ที่ cache ไว้โดยตรง ไม่ต้องผ่าน PHP เลย เร็วที่สุด
เพิ่มใน nginx.conf:
fastcgi_cache_path /tmp/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
ใน server block:
location ~ \.php$ {
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-Cache $upstream_cache_status;
# ... ส่วน fastcgi_pass ปกติ
}
Layer 5: ปรับ PHP-FPM Pool
ใน /etc/php/8.3/fpm/pool.d/www.conf:
pm = dynamic
pm.max_children = 20 ; RAM / 30MB ต่อ process
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500 ; restart process ทุก 500 request ป้องกัน memory leak
สิ่งที่ช่วยได้น้อยกว่าที่คิด
- Plugin cache เช่น WP Super Cache ช่วยได้ แต่น้อยกว่า Nginx-level cache
- CDN ช่วยเรื่อง static file แต่ไม่ช่วย TTFB ของ PHP
- ลด plugin ช่วยได้ แต่ผลน้อยถ้า core PHP ยังช้า
ตรวจสอบว่า Cache ทำงานจริง
# ดู OPcache status
php -r "print_r(opcache_get_status());" | grep hits
# ตรวจ Redis ว่า hit rate ดีไหม
redis-cli info stats | grep "keyspace_hits\|keyspace_misses"
# ตรวจ Nginx FastCGI cache header
curl -I https://example.com/ | grep X-Cache
# ควรเห็น X-Cache: HIT หลังจาก request ที่ 2 เป็นต้นไป
$skip_cache variable ใน Nginx config เพื่อ bypass FastCGI cache สำหรับ request ที่มี WordPress login cookie หรือ ?nocache=1 parameterFastCGI Cache Skip Rules สำหรับ WordPress
เพิ่มใน Nginx config ก่อน server block เพื่อ bypass cache เมื่อ user login หรืออยู่ใน admin:
map $http_cookie $skip_cache {
default 0;
"~*wordpress_logged_in" 1;
"~*wp-postpass_" 1;
"~*comment_author_" 1;
}
map $request_method $skip_cache_method {
POST 1;
default 0;
}
# ใน server block
set $skip_cache 0;
if ($request_method = POST) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
แก้ปัญหาที่พบบ่อย
WordPress แสดง 500 Error หลังเปิด OPcache
มักเกิดจาก validate_timestamps=0 ทำให้ WordPress ไม่เห็นไฟล์ที่เพิ่งแก้ไข ให้ clear cache ก่อน:
# Clear OPcache ด้วย PHP script
php -r "opcache_reset();"
# หรือ restart PHP-FPM
systemctl restart php8.3-fpm
Redis Object Cache Plugin บอก "Object cache could not be connected"
# ตรวจสอบ Redis รันอยู่
systemctl status redis-server
redis-cli ping # ควรได้ PONG
# ตรวจสอบ PHP มี redis extension
php -m | grep redis
# ถ้าไม่มี ติดตั้ง
apt install php8.3-redis
systemctl restart php8.3-fpm
Nginx FastCGI Cache ทำงาน แต่ WordPress admin พังหรือ content เก่า
ตรวจสอบว่า $skip_cache rules ทำงานถูกต้อง:
# เพิ่ม header ชั่วคราวเพื่อ debug
add_header X-Cache-Skip $skip_cache always;
# แล้ว curl ดู
curl -I -b "wordpress_logged_in_xxx=yyy" https://example.com/ | grep X-Cache
PHP-FPM ใช้ RAM มากเกินไป ขยายตัวไม่หยุด
ตั้ง pm.max_requests เพื่อให้ restart worker process หลัง handle requests ครบจำนวน ป้องกัน memory leak สะสม:
pm.max_requests = 500
# worker จะ restart ทุก 500 request โดยอัตโนมัติ
OPcache hit rate ต่ำกว่า 90%
เพิ่ม opcache.max_accelerated_files ให้ครอบคลุมจำนวนไฟล์ PHP ทั้งหมดใน project:
# นับจำนวนไฟล์ PHP
find /var/www/html -name "*.php" | wc -l
# แล้วตั้ง max_accelerated_files ให้มากกว่าค่านั้น
opcache.max_accelerated_files=20000
คำถามที่พบบ่อย
OPcache กับ Redis Object Cache ต่างกันอย่างไร?
OPcache เก็บ PHP bytecode ที่ compile แล้ว ลดเวลา parse/compile PHP ทุก request ส่วน Redis Object Cache เก็บผลลัพธ์ database query ลดจำนวนครั้งที่ WordPress ต้องคุย MySQL ทั้งคู่ทำงานคนละ layer และใช้ร่วมกันได้ ควรเปิดทั้งสองพร้อมกัน
WordPress บน VPS 2 GB RAM ควร set php-fpm pm.max_children เท่าไร?
ใช้สูตร: RAM ที่เหลือหลังระบบ ÷ RAM ต่อ PHP worker (เฉลี่ย 25–35 MB) สำหรับ 2 GB RAM ที่ MySQL ใช้ไปประมาณ 512 MB เหลือ ~1.5 GB สำหรับ PHP → max_children = 40–50 ตรวจสอบ memory ต่อ worker จริงด้วย ps aux | grep php-fpm | awk '{print $6}'
Nginx FastCGI Cache กับ WordPress admin จะมีปัญหาไหม?
ไม่มีปัญหาถ้าตั้ง skip_cache rules ถูกต้อง request ที่มี WordPress login cookie จะ bypass cache เสมอ ทำให้ admin เห็น content จริงไม่ใช่ cache เก่า อย่าลืมตั้ง rule สำหรับ WooCommerce cart และ checkout ด้วยถ้าใช้
วัดความเร็ว WordPress ได้ที่ไหนฟรี?
ใช้ Google PageSpeed Insights (pagespeed.web.dev) ดู Core Web Vitals จริง, GTmetrix สำหรับ waterfall chart เห็น resource ที่ช้า, หรือ WebPageTest.org สำหรับ test จาก location ต่าง ๆ เน้น TTFB (Time to First Byte) ซึ่งควรต่ำกว่า 200ms หลังตั้งค่า cache ครบ
สรุป
ลำดับที่ให้ผลมากที่สุดคือ OPcache ก่อน → Redis Object Cache → Nginx FastCGI Cache ลงทุนเวลาแค่ชั่วโมงเดียวกับขั้นตอนเหล่านี้สามารถลด server response time ได้ถึง 80–90% ตรวจสอบผลด้วย X-Cache header และ TTFB ก่อน/หลังเสมอ