⚙️
Hosting

บนอินเทอร์เน็ตสมัยใหม่ เซิร์ฟเวอร์เว็บของคุณต้องจัดการคำขอ HTTP หลายพันครั้งต่อวินาที พฤติกรรมการทำงานของ PHP engine นั้นส่งผลต่อความเร็ว ปริมาณหน่วยความจำที่ใช้ และโดยรวมประสิทธิภาพของเว็บไซต์ ในบทความนี้เราจะอธิบาย PHP-FPM (FastCGI Process Manager) ว่าคืออะไร วิธีการทำงาน เหตุใดจึงเป็นทางเลือกมาตรฐานของการโฮสต์สมัยใหม่ และวิธีการ tuning เพื่อให้ประสิทธิภาพสูงสุด

สรุปสั้น: PHP-FPM คือ process manager ที่รักษา pool ของ PHP worker processes ให้ทำงานอยู่เสมอ แล้วนำเสนอคำขอมายังตัวจัดการ แทนที่จะสร้าง PHP process ใหม่สำหรับทุกคำขอเหมือน CGI เก่า วิธีนี้ประหยัดทรัพยากร ลดเวลาแฝง และเพิ่มปริมาณงานที่จัดการได้ต่อวินาที เพื่อปรับปรุง pm.max_children และพารามิเตอร์อื่นๆ ให้เหมาะกับ RAM ของเซิร์ฟเวอร์ ลูกค้า AsiaGB สามารถใช้ DirectAdmin PHP Selector หรือติดต่อฝ่ายสนับสนุน

PHP-FPM คืออะไร

PHP-FPM ย่อมาจาก FastCGI Process Manager เป็นเทคโนโลยีสมัยใหม่ในการจัดการ PHP processes บนเซิร์ฟเวอร์เว็บ แนวคิดมีดังนี้ แทนที่จะรอจนกว่า HTTP request มาถึง แล้วจึงสร้าง PHP process ใหม่จากศูนย์ (ซึ่งใช้เวลานาน) PHP-FPM จะสร้างและรักษา "pool" ของ PHP worker processes ไว้ก่อนเสมอ เมื่อ request เข้ามา ตัวจัดการ (master process) จะมอบหมายคำขอไปยัง worker process ที่ว่างทันที วิธีนี้เหมือนกับการมี "พนักงาน" หลายคนนั่งอยู่ใต้หลังคา รอคำสั่งทำงาน แทนที่จะเช่าพนักงานเต็มเวลาใหม่สำหรับแต่ละลูกค้า

PHP-FPM vs Mod_PHP vs PHP-CGI

PHP-CGI (เก่า): ทุกครั้งที่ web server ได้รับ request สำหรับไฟล์ PHP จะสร้าง PHP process ใหม่ ประมวลผลไฟล์ แล้วปิด process นั้นทิ้ง วิธีนี้ใช้ CPU มาก ใช้เวลา (startup overhead) และ server ที่มี traffic สูงจะสร้าง processes หลายพันตัว ทำให้เครื่องช้าหรือหยุดชะงัก

Mod_PHP: ฝัง PHP engine โดยตรงเข้าใน Apache process จะไม่ต้องเรียก external process แต่ปัญหาคือ memory ใช้มากมายเพราะแต่ละ Apache worker process บรรจุ PHP runtime สมบูรณ์ ซึ่งหมายความว่า Apache ที่มี 300 worker processes จะต้องโหลด PHP library 300 ครั้ง แบบนี้เซิร์ฟเวอร์ 4GB RAM จะ swap ไฟล์และหยุด

PHP-FPM (สมัยใหม่): process manager สร้าง pool ของ PHP workers (ทั่วไป 5–50 processes) นั่งพร้อมตลอด เมื่อ web server (Nginx หรือ Apache) ได้รับ request จะส่งมายัง FPM master process ผ่าน Unix socket หรือ TCP connection master process นั้นหยิบ worker ที่เหว ส่ง request ไป ถ้าไม่มี worker ว่าง request จะรอในคิว วิธีนี้ประหยัด memory (ไม่ต้องใช้ 300 PHP processes ตลอดเวลา) และ request ได้รับการจัดการเร็ว

ระดับ PHP-CGI Mod_PHP PHP-FPM
สร้าง Process ใหม่ทุกครั้ง ฝังใน Apache Pool ที่สร้างไว้
Memory ต่อ request สูง (startup) สูงมาก (300 procs) เล็ก (5–50 procs)
Latency ช้า (startup) เร็ว เร็วมาก
Scalability ต่ำ กลาง สูง
Web Server ทั้งหมด Apache เท่านั้น Nginx, Apache

Pool Configuration Parameters

ความสำคัญของ PHP-FPM คือความสามารถในการปรับแต่ง "pool" ได้ การตั้งค่า pool จะอยู่ในไฟล์ config เช่น /etc/php/8.1/fpm/pool.d/www.conf (Linux) หรือผ่าน DirectAdmin control panel โดยทั่วไป ลูกค้า AsiaGB สามารถใช้ DirectAdmin > PHP Selector เพื่อเลือก PHP version และปรับปรุง pool settings ได้

pm (Process Manager mode): ตั้งว่า pool จะสร้าง process อย่างไร

pm.max_children: จำนวน worker processes สูงสุดที่จะมีในเวลาเดียวกัน หากทั้งหมด "ยุ่ง" request จะต้องรอคิว ตั้งค่าสูงเกินไป server เรียน OOM (Out of Memory) ตั้งต่ำเกินไป traffic สูงจะ 502 Bad Gateway

pm.start_servers, pm.min_spare_servers, pm.max_spare_servers: ใช้ใน pm = dynamic เท่านั้น คุณบอก FPM ว่า "ตอนเริ่มต้นให้สร้าง X processes, ให้มี Y processes ว่างเสมอ และเก็บอย่างน้อย Z processes ว่างไว้" ตัวอย่าง pm.start_servers = 10, pm.min_spare_servers = 5, pm.max_spare_servers = 20 หมายความว่า FPM เริ่มต้นด้วย 10 processes แล้วถ้า idle processes ลดต่ำกว่า 5 จะสร้างเพิ่ม ถ้ามากกว่า 20 จะปิดส่วนเกิน

pm.max_requests: จำนวน requests ที่ PHP process เดียวจะจัดการก่อนรีเซ็ต ใช้เพื่อป้องกัน memory leak ตั้งค่านี้บังคับให้ process เก่าปิดและสร้างใหม่เป็นระยะ ป้องกัน process ใช้ memory มากมายจาก bug ในเว็บแอปพลิเคชัน ตัวอย่าง pm.max_requests = 1000 หมายความว่า process เดียวจัดการ 1000 requests แล้วปิด

request_terminate_timeout: เวลาสูงสุด (วินาที) ที่ PHP script สามารถทำงานได้ ตั้งค่า 30 วินาทีเป็นค่าเริ่มต้น หากมี script ที่ใช้เวลานาน (เช่น batch processing) ตั้งค่า 300 วินาที web server อาจมี timeout แยกต่างหาก ให้คำนึงถึง

วิธีตรวจสอบ PHP Handler ปัจจุบันของคุณ

หากคุณไม่แน่ใจว่าเซิร์ฟเวอร์ใช้ PHP-FPM, Mod_PHP หรือ CGI ลองตรวจสอบดังนี้:

ในหน้า phpinfo(): สร้างไฟล์ PHP ที่มีแค่ <?php phpinfo(); ?> อัพโหลด และดูที่ "Server API" หาก "FPM/FastCGI" = PHP-FPM, "Apache 2.0 Handler" = Mod_PHP, "CGI" = PHP-CGI

บน Linux shell (ถ้าคุณมี SSH access):

ps aux | grep php

หากเห็น php-fpm: pool www หลายบรรทัด = PHP-FPM สถาปนา หากไม่เห็น php process = Mod_PHP (ซ่อนภายใน Apache)

ปัญหาทั่วไป: 502 Bad Gateway

ข้อควรระวัง: ปัญหา 502 Bad Gateway บ่อยครั้งเกิดจากการตั้งค่า pm.max_children ต่ำเกินไป เมื่อ traffic สูง worker processes ทั้งหมดทำงาน คำขอใหม่ไม่มี process ว่าง FPM บอก Nginx/Apache "ไม่สามารถเชื่อมต่อกับ PHP" หรือ timeout ถ้า request_terminate_timeout หมดเวลา ลูกค้าจะเห็น 502 error ตัวแก้คือเพิ่ม pm.max_children หรือปรับปรุง request_terminate_timeout สำหรับ request ที่ยาวนาน

ตรวจสอบสถานะ PHP-FPM ด้วย Status Page

เคล็ดลับ: PHP-FPM มี status page ซ่อนที่แสดงข้อมูล realtime เช่น จำนวน processes ว่าง, accepted connections, slow requests ฯลฯ การเปิดใช้งาน ให้แก้ /etc/php/8.1/fpm/pool.d/www.conf (หรือผ่าน DirectAdmin) และตั้ง pm.status_path = /fpm-status แล้ว systemctl restart php8.1-fpm หลังจากนั้น curl ไปยัง http://localhost/fpm-status (จาก shell บน server) หรือใช้ SSH forwarding คุณจะเห็นสถิติเช่น "idle processes: 3" "total processes: 10" "slow requests: 2" ซึ่งบอกว่า pool ของคุณทำงานเพียงพอหรือไม่

วิธีการปรับปรุงประสิทธิภาพ

วิธีหลักในการปรับปรุง PHP-FPM ให้เหมาะกับเซิร์ฟเวอร์ของคุณ คือการคำนวณ pm.max_children ให้ถูกต้อง:

สูตรคร่าวๆ:

pm.max_children = (Available RAM - OS Overhead) / Average PHP Process Memory

ตัวอย่าง: VPS ที่มี 4GB RAM, OS ใช้ ~500MB, PHP processes โดยเฉลี่ยใช้ 30–50MB แต่ละ process

pm.max_children = (4096 - 500) / 45 ≈ 80 processes

อย่างไรก็ตาม ไม่ใช่ว่าตั้งให้สูงสุดเสมอ ตั้งค่า 80 processes ที่จำนวน requests ต่อ request ช้า (3–5 วินาที) อาจจบ CPU cores ก่อน memory จงตัดสินใจตามการสังเกตการณ์

ขั้นตอนการปรับปรุง:

  1. เช็คปัจจุบัน memory ที่ PHP processes ใช้ด้วย top หรือ status page
  2. คำนวณ pm.max_children โดยใช้สูตร
  3. ทดลองตั้งค่าใหม่ บันทึก config และ restart FPM
  4. ตรวจสอบ status page และดู logs หลัง restart
  5. ทำการทดสอบ load (เช่น artillery หรือ ab tool) เพื่อดู 502 หรือ lag
  6. หากยังมี 502 ให้เพิ่ม pm.max_children เพิ่มเติม
  7. หากเห็น OOM (Out of Memory) killer ล็อก ลดลง

การแก้ไข Shared Hosting (Dynamic pool): หากใช้ pm = dynamic ให้ปรับ pm.max_spare_servers ลดลง (เช่น 10 แทน 35) เพื่อลดการใช้ idle memory และ pm.min_spare_servers ให้เพียงพอสำหรับการตอบสนองเร็ว (เช่น 5)

หลาย Pool สำหรับหลายเว็บไซต์บนเซิร์ฟเวอร์เดียว

เมื่อเซิร์ฟเวอร์หนึ่งเครื่องรันหลายเว็บไซต์พร้อมกัน (multi-site hosting) การใช้ pool เดียวร่วมกันทุกเว็บอาจไม่เหมาะสม เพราะเว็บที่มี traffic สูงจะแย่งชิง worker processes จากเว็บอื่นที่ traffic น้อยกว่า วิธีแก้คือสร้าง pool แยกสำหรับแต่ละเว็บไซต์ โดยสร้างไฟล์ config ใหม่ในโฟลเดอร์ pool.d/ เช่น site-a.conf และ site-b.conf แต่ละไฟล์กำหนด [site-a] เป็นชื่อ pool, ตั้ง listen เป็น socket แยก เช่น /run/php/site-a.sock และปรับ pm.max_children ตามสัดส่วน traffic ของแต่ละเว็บ วิธีนี้ทำให้เว็บหนึ่งที่มีปัญหา (เช่น script วนลูปไม่จบ) ไม่กระทบเว็บอื่นบนเซิร์ฟเวอร์เดียวกัน เพราะแต่ละ pool มี worker และ memory limit ของตัวเองแยกขาดจากกัน

สำหรับผู้ดูแลระบบที่ต้องรองรับลูกค้าหลายราย การแยก pool ต่อโดเมนยังช่วยเรื่องความปลอดภัยด้วย เพราะสามารถกำหนด user และ group ของแต่ละ pool ให้ต่างกันได้ (คล้ายกับ PHP Selector ที่ DirectAdmin ใช้แยกสิทธิ์ของแต่ละบัญชี) ทำให้ไฟล์ของเว็บไซต์หนึ่งไม่สามารถถูกอ่านหรือเขียนโดย process ของอีกเว็บไซต์หนึ่งได้ แม้จะอยู่บนเซิร์ฟเวอร์เดียวกัน ซึ่งเป็นแนวทางความปลอดภัยที่ shared hosting provider มักใช้เพื่อแยก (isolate) บัญชีลูกค้าแต่ละราย

Nginx กับ PHP-FPM: การเชื่อมต่อผ่าน Unix Socket vs TCP

เมื่อ Nginx ส่ง request มายัง PHP-FPM มีสองวิธีในการเชื่อมต่อ คือผ่าน Unix socket (ไฟล์บนดิสก์ เช่น /run/php/php8.1-fpm.sock) หรือผ่าน TCP (เช่น 127.0.0.1:9000) Unix socket มักเร็วกว่าเล็กน้อยเพราะไม่ต้องผ่าน network stack ของระบบปฏิบัติการ เหมาะสำหรับกรณีที่ Nginx และ PHP-FPM อยู่บนเซิร์ฟเวอร์เดียวกัน ส่วน TCP จำเป็นเมื่อ PHP-FPM รันอยู่คนละเครื่องกับ Nginx เช่น สถาปัตยกรรมที่แยก web server กับ application server ออกจากกันเพื่อ scale ระบบ ในไฟล์ config ของ Nginx จะเห็นบรรทัด fastcgi_pass unix:/run/php/php8.1-fpm.sock; สำหรับ socket หรือ fastcgi_pass 127.0.0.1:9000; สำหรับ TCP ทั้งสองวิธีนี้ต้องตรงกับค่า listen ที่ตั้งไว้ในไฟล์ pool config ของ PHP-FPM ด้วย ไม่เช่นนั้นจะเกิด error "No such file or directory" หรือ "Connection refused"

สรุป

PHP-FPM คือเครื่องมือสำคัญในการให้บริการเว็บไซต์แบบบูรณาการ process manager ที่อัจฉริยะ รักษา pool processes พร้อมทั้งจัดการ requests ให้ได้ประสิทธิภาพสูงสุด การปรับปรุง pm.max_children, pm mode, และ request timeouts ตามการใช้งานแท้จริงของเซิร์ฟเวอร์ของคุณจะหลีกเลี่ยง 502 errors และเปลี่ยน latency ให้ต่ำลง หากคุณใช้ DirectAdmin ลองเข้า PHP Selector ดูการตั้งค่าปัจจุบัน หรือติดต่อฝ่ายสนับสนุน AsiaGB เพื่อปรึกษาการแนะนำสำหรับเซิร์ฟเวอร์ของคุณ

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

PHP-FPM ทำให้เว็บไซต์เร็วขึ้นจริงๆหรือ

ใช่ PHP-FPM ใช้ processes pool ที่สร้างไว้ล่วงหน้า แทนการสร้าง process ใหม่ทุกครั้ง วิธีนี้ลดเวลา startup และจัดการ requests ได้พร้อมกันมากขึ้น เว็บไซต์ที่มี traffic สูง จะได้อนุภูติความเร็วที่เห็นได้ชัด

pm.max_children ควรตั้งเท่าไหร่

ขึ้นอยู่กับ RAM และ PHP memory per process ใช้สูตร (Available RAM - OS) / Avg Process Memory ตัวอย่าง 4GB VPS ที่ process ใช้ 50MB ควร 80 processes ความถูกต้องถือจากการทดสอบ load และดู monitoring

502 Bad Gateway อะไรสาเหตุ

บ่อยครั้ง pm.max_children ต่ำเกินไป ดังนั้นตอน traffic สูง ทุก workers ทำงานจบ request ใหม่ไม่มี process ว่าง เพิ่ม pm.max_children หรือปรับ request_terminate_timeout

ต้อง SSH access ถึงการ restart PHP-FPM ใช่ไหม

ลูกค้า AsiaGB โดยทั่วไปสามารถใช้ DirectAdmin > PHP Selector ปรับตั้งค่า pool ได้ หากบริการไม่พร้อม ติดต่อฝ่ายสนับสนุน AsiaGB เพื่อช่วย restart FPM

เริ่มต้นใช้งาน Hosting AsiaGB วันนี้

AsiaGB Hosting ใช้ SSD Storage ควบคุมผ่าน DirectAdmin ที่ใช้งานง่าย รองรับ PHP หลายเวอร์ชัน พร้อม Uptime 99% เริ่มต้นราคาย่อมเยาพร้อมทีมซัพพอร์ตภาษาไทย

ดูแพ็กเกจ Hosting