PHP-FPM Worker Pool การปรับแต่ง VPS

ปรับ PHP-FPM ให้เร็ว: Worker, Pool และ OPcache บน VPS

มิถุนายน 2026 · อ่าน 8 นาที

PHP-FPM (FastCGI Process Manager) คือ Implementation ของ PHP ที่ออกแบบมาเพื่อ Performance สูง ใช้คู่กับ Nginx (หรือ Apache กับ mod_proxy_fcgi) ข้อดีของ PHP-FPM คือสามารถปรับจำนวน Worker Process ได้ตามปริมาณงาน ทำให้ตอบสนอง Request ได้มากกว่า mod_php ที่ผูกกับ Apache Process ต่อ Request การ Tune PHP-FPM อย่างถูกต้องอาจทำให้เว็บ WordPress ที่ใช้อยู่เร็วขึ้น 2-3 เท่าโดยไม่ต้องเพิ่ม RAM

ทำความเข้าใจ pm.max_children

ตัวแปรที่สำคัญที่สุดใน PHP-FPM คือ pm.max_children ซึ่งกำหนดจำนวน PHP Worker สูงสุดที่ทำงานพร้อมกันได้ ถ้าตั้งสูงเกินไปจะ OOM Killer เพราะ RAM หมด ถ้าต่ำเกินไป Request จะเข้าคิวรอจนเกิด Timeout

สูตรคำนวณเบื้องต้น:

# ดูว่า PHP-FPM Process แต่ละตัวใช้ RAM เฉลี่ยเท่าไหร่ (หน่วย MB)
ps aux | grep "php-fpm" | awk '{sum+=$6; count++} END {print sum/count/1024 " MB average"}'

# ตัวอย่าง: VPS RAM 2GB, ใช้โดย OS+Nginx ~300MB, เหลือ ~1700MB
# PHP Worker ใช้เฉลี่ย 50MB → max_children = 1700/50 = 34
RAM VPSpm.max_children (แนะนำ)หมายเหตุ
1 GB8–12เหมาะเว็บเล็ก traffic ต่ำ
2 GB20–30WordPress 1-3 เว็บ
4 GB40–60WordPress หลายเว็บหรือ WooCommerce
8 GB80–120เว็บ traffic สูงหรือ PHP API

ตำแหน่งไฟล์ Config PHP-FPM

# Ubuntu/Debian (PHP 8.2)
/etc/php/8.2/fpm/pool.d/www.conf

# AlmaLinux/Rocky Linux (PHP 8.2)
/etc/php-fpm.d/www.conf

# เปิดแก้ไข
nano /etc/php/8.2/fpm/pool.d/www.conf

ค่า Pool ที่แนะนำสำหรับ VPS 2 GB

[www]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data

; Process Manager แบบ dynamic (ปรับ Worker ตาม Load)
pm = dynamic
pm.max_children = 25
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 500        ; restart Worker หลัง 500 request (ป้องกัน memory leak)

; Timeout
request_terminate_timeout = 60s
request_slowlog_timeout = 10s
slowlog = /var/log/php/slow.log

เลือก pm Mode ให้เหมาะกับงาน

ตั้งค่า OPcache — เพิ่มความเร็วสูงสุด

OPcache คือ Bytecode Cache ที่แปลง PHP Script เป็น Bytecode ครั้งเดียวแล้ว Cache ไว้ใน Memory ทำให้ไม่ต้อง parse ไฟล์ PHP ซ้ำทุก Request WordPress เร็วขึ้นได้ 40-70% เพียงแค่เปิด OPcache

# แก้ไข /etc/php/8.2/fpm/conf.d/10-opcache.ini หรือ /etc/php/8.2/mods-available/opcache.ini

[opcache]
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256       ; RAM สำหรับ Bytecode Cache (MB)
opcache.interned_strings_buffer=16   ; Buffer สำหรับ String cache (MB)
opcache.max_accelerated_files=10000  ; จำนวนไฟล์ PHP ที่ Cache ได้
opcache.revalidate_freq=2            ; ตรวจสอบไฟล์เปลี่ยนแปลงทุก 2 วินาที
opcache.fast_shutdown=1
opcache.validate_timestamps=1        ; เปิดไว้ระหว่าง development
; opcache.validate_timestamps=0     ; เปิดบน Production เพื่อเร็วสูงสุด (ต้อง reload php-fpm เมื่อ deploy)
Production tip: ตั้ง opcache.validate_timestamps=0 บน Production Server เพื่อข้ามการตรวจสอบไฟล์ทุก Request แต่ต้องทำ systemctl reload php8.2-fpm ทุกครั้งหลัง deploy โค้ดใหม่

ตั้งค่า realpath_cache — เร็วขึ้นอีกระดับ

# /etc/php/8.2/fpm/php.ini
[PHP]
realpath_cache_size = 4096K   ; Cache path resolution ของไฟล์ PHP (WordPress มีไฟล์เยอะมาก)
realpath_cache_ttl = 600      ; Cache นาน 10 นาที

สร้าง Pool แยกต่างหากสำหรับแต่ละเว็บ

ถ้ามีหลายเว็บบน VPS เดียวกัน ควรสร้าง Pool แยกสำหรับแต่ละเว็บ เพื่อให้ไม่แย่ง Worker กันและตรวจสอบ performance ได้แม่นยำกว่า:

# สร้างไฟล์ใหม่
cp /etc/php/8.2/fpm/pool.d/www.conf /etc/php/8.2/fpm/pool.d/mysite.conf

# แก้ไขใน mysite.conf
[mysite]                                    ; ชื่อ pool
user = mysite
group = mysite
listen = /run/php/php8.2-mysite.sock       ; socket แยก
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 5
# แก้ Nginx ให้ใช้ socket ของ pool นี้
fastcgi_pass unix:/run/php/php8.2-mysite.sock;

Reload และตรวจสอบ

# ทดสอบ config ก่อน reload
php-fpm8.2 -t

# Reload PHP-FPM (ไม่ kill process ที่กำลังทำงาน)
systemctl reload php8.2-fpm

# ดูสถานะ
systemctl status php8.2-fpm

# ดูการใช้ resource แบบ real-time
watch -n 1 "ps aux | grep php-fpm | grep -v grep | wc -l"

ตรวจสอบ Performance ด้วย Status Page

# เพิ่มใน pool config เพื่อเปิด Status Page
pm.status_path = /fpm-status
ping.path = /fpm-ping

# เพิ่มใน Nginx config (เข้าได้เฉพาะ localhost)
location /fpm-status {
    allow 127.0.0.1;
    deny all;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

# ดู Status
curl http://localhost/fpm-status?full

การปรับ PHP-FPM ที่ถูกต้องเป็นหนึ่งในวิธีที่คุ้มค่าที่สุดในการเพิ่มความเร็วเว็บโดยไม่ต้องเพิ่ม Hardware ถ้าคุณกำลังมองหา VPS ที่มี Performance ดีตั้งแต่ต้น VPS ไทยของ asiagb มีแผนหลายขนาดพร้อม NVMe SSD ที่ช่วยให้ PHP-FPM ทำงานได้เต็มประสิทธิภาพ

ตรวจสอบว่า PHP-FPM ทำงานถูกต้อง

# ตรวจสอบ config syntax
php-fpm8.2 -t
# ผลที่ต้องการ: NOTICE: configuration file /etc/php/8.2/fpm/php-fpm.conf test is successful

# ดูสถานะ service
systemctl status php8.2-fpm

# ดูจำนวน worker ที่รันอยู่แบบ real-time
watch -n 1 "ps aux | grep php-fpm | grep -v grep | wc -l"

# ตรวจสอบ OPcache via PHP
php -r "var_dump(opcache_get_status()['opcache_enabled']);"
# ต้องเป็น: bool(true)
Tip: เปิด pm.status_path = /fpm-status ใน pool config แล้ว curl http://localhost/fpm-status จะแสดง active connections, idle workers, slow requests แบบ real-time — มีประโยชน์มากเมื่อ traffic พุ่ง

แก้ปัญหาที่พบบ่อย

Error: "502 Bad Gateway" จาก Nginx

มักเกิดจาก socket path ใน Nginx config ไม่ตรงกับที่ PHP-FPM ใช้จริง:

# ตรวจ socket path ที่ PHP-FPM สร้าง
ls /run/php/
# ควรเห็น php8.2-fpm.sock

# ตรวจ Nginx config ว่าชี้ตรงไหม
grep fastcgi_pass /etc/nginx/sites-enabled/*.conf
# ต้องตรงกัน: unix:/run/php/php8.2-fpm.sock

# ตรวจ permission ของ socket
ls -la /run/php/php8.2-fpm.sock
# ต้องเขียนได้โดย www-data

Error: "WARNING: [pool www] seems busy (pid X, fpm_got_signal)" และ request หนาแน่น

pm.max_children ต่ำเกินไปสำหรับ traffic ที่ได้รับ — PHP worker หมด request ต้องรอ:

# ดูว่า worker ใช้เต็มไหม
curl http://localhost/fpm-status
# ดูค่า active processes เทียบกับ max children

# เพิ่ม max_children ใน pool config
nano /etc/php/8.2/fpm/pool.d/www.conf
# เพิ่ม pm.max_children

systemctl reload php8.2-fpm

Error: PHP-FPM start ไม่ขึ้น — "WARNING: Nothing matches the include pattern '/etc/php/8.2/fpm/pool.d/*.conf'"

ไฟล์ pool config อาจถูกลบหรือ directory ว่างอยู่ ต้องสร้าง pool ใหม่:

# ตรวจ directory pool
ls /etc/php/8.2/fpm/pool.d/
# ต้องมีไฟล์ .conf อย่างน้อย 1 ไฟล์

# ถ้าว่าง สร้าง www.conf พื้นฐาน
cp /etc/php/8.2/fpm/pool.d/www.conf.default /etc/php/8.2/fpm/pool.d/www.conf
# หรือ install ใหม่: apt install --reinstall php8.2-fpm

Error: WordPress ยัง slow อยู่แม้ตั้ง OPcache แล้ว

ตรวจสอบว่า OPcache โหลด bytecode ครบหรือยัง และ validate_timestamps ไม่ทำให้ต้อง recheck ทุก request:

# ดู OPcache stats
php -r "print_r(opcache_get_status());"
# ดู opcache_statistics: hits vs misses

# ตรวจ memory ที่ใช้
php -r "print_r(opcache_get_status()['memory_usage']);"
# ถ้า used_memory ใกล้ full ให้เพิ่ม opcache.memory_consumption

Error: pm.max_requests ทำให้ worker restart บ่อย แต่ช้าลง

pm.max_requests = 500 หมายถึง worker จะ restart ทุก 500 request เพื่อป้องกัน memory leak ถ้า restart บ่อยเกินให้เพิ่มค่า หรือหา memory leak ใน code แทน:

# ดูขนาด memory ของแต่ละ worker
ps aux | grep php-fpm | awk '{print $6/1024 " MB " $11}' | head

# ถ้า memory ไม่ leak ให้เพิ่ม max_requests เป็น 2000-5000
# pm.max_requests = 2000

คำถามที่พบบ่อย

จะเปลี่ยน PHP version บน server ยังไงโดยไม่ให้เว็บ down?

ติดตั้ง PHP version ใหม่คู่ขนานกับเวอร์ชันปัจจุบัน จากนั้นสร้าง pool ใหม่สำหรับ PHP version ใหม่ เปลี่ยน Nginx ของเว็บที่ต้องการให้ชี้ socket ใหม่ ทดสอบเว็บนั้นก่อน ค่อยย้ายเว็บอื่นทีละตัว — PHP version เก่าและใหม่รันพร้อมกันได้บน Ubuntu

ทุกเว็บต้องใช้ PHP-FPM pool แยกไหม?

ไม่บังคับ แต่แนะนำถ้ามีหลายเว็บบน VPS เดียวกัน pool แยกให้แต่ละเว็บมี worker ของตัวเอง ถ้าเว็บหนึ่งมี traffic พุ่งจะไม่กระทบเว็บอื่น และยัง run แต่ละ pool ด้วย user ที่ต่างกัน ช่วยด้าน security ด้วย

pm = dynamic กับ ondemand ต่างกันอย่างไร?

dynamic รัก worker ขั้นต่ำไว้ตลอดเวลา (pm.start_servers) ทำให้ตอบ request แรกได้เร็ว เหมาะ traffic สม่ำเสมอ ส่วน ondemand สร้าง worker เมื่อมี request เข้า แล้ว idle worker จะหายไป เหมาะ VPS RAM น้อยหรือ traffic ไม่สม่ำเสมอ แต่ request แรกหลัง idle จะช้ากว่าเล็กน้อย