ปัญหามักเกิดจาก เมื่อเราใช้ mod-php ก็ต้องใช้ apache ที่ใช้ mpm-prefork ด้วย นั่นคือเมื่อมี connection เข้ามา apache ต้อง fork process เพื่อให้บริการ connection นั้นเป็นรายๆ ไป ปัญหาคือว่า mod-php ทำให้แต่ละ process มีขนาดใหญ่มาก ยิ่งเว็บแอ็พที่ใช้มีขนาดใหญ่ ยิ่งทำให้แต่ละ process ใหญ่เข้าไปอีก ปัญหาจะหนักขึ้น เมื่อต้องให้บริการดาวน์โหลดไฟล์ หรือมีรูปภาพจำนวนมากบนเว็บไซต์ด้วย เพราะแม้ว่าพวกนี้จะไม่ต้องการซีพียูในการประมวลผลมากนัก แต่การที่ apache ต้อง fork process มาเพื่อให้บริการไฟล์พวกนี้ ก็ทำให้ต้องเสีย memory มากขึ้นไปอีก ยิ่งเน็ตเวิร์คของไคลเอนต์ช้า ยิ่งทำให้ต้องใช้เวลาดาวน์โหลดนาน จะพบว่า จำนวน connection มีมากขึ้นเรื่อยๆ
ปัญหาจะถึงจุดวิกฤติเมื่อ memory หมดเกลี้ยง ลินุกซ์จะเริ่ม swap หน่วยความจำบางส่วนลงดิสก์ และเมื่อ memory ที่กำลัง active มีมากกว่า memory จริงๆ การ swap จะเกิดขึ้นแบบไม่รู้จบ ถึงตอนนี้ท่านก็จะพบว่า แม้กระทั่งการ ssh เข้ามาที่เซิร์ฟเวอร์ ก็เป็นเรื่องยาก แม้เมื่อล็อกอินที่หน้าเครื่อง ก็อาจจะทำไม่ได้ด้วยซ้ำ ทางหนึ่งที่แอดมินชอบทำก็คือ กด ctrl-alt-del เพื่อรีบูตเซิร์ฟเวอร์ หลังจากรีบูตก็จะใช้งานได้สักพัก แล้วก็จะเกิดวิกฤติอีกครั้ง ส่วนการเพิ่ม memory ก็แก้ปัญหาได้ในระยะสั้น และไม่สามารถรองรับผู้ใช้เพิ่มได้อีกมากนัก
ที่จริงแล้ว apache2 ยังมี mpm แบบอื่นๆ ที่ทำงานแบบ thread เช่น mpm-worker ซึ่งจะใช้ memory น้อยลงมาก เพราะไม่ต้อง fork process เป็นหลายๆ process เพื่อรองรับ connection แต่ว่า mpm-worker ไม่สามารถใช้กับ mod-php ได้ ทางหนึ่งที่จะทำได้คือ รัน php แบบ cgi ซึ่งไม่ใช่ทางเลือกที่ดีนัก เพราะจำเป็นต้องเริ่ม process php-cgi ใหม่ทุกครั้งที่เปิดหน้า php 1 หน้า ทางออกที่ดีที่สุดคือใช้ mod-fcgid หรือ mod-fastcgi ก็ได้ แต่ fcgid ดูจะเร็วกว่านิดหน่อย โดยหลักการจะเหมือนกันคือ php-cgi จะคอมไพล์ให้รองรับ fastcgi ไว้อยู่แล้ว คือ จะรัน script ที่ส่งเข้ามาให้จนเสร็จ แต่จะไม่ kill process แต่จะยังคงรอรับ script อื่นมาประมวลผลต่อไป ทำให้ได้ข้อดีของการทำงานแบบ mod หรือ embeded คือไม่ต้อง fork process บ่อยๆ ในขณะที่มีข้อดีแบบ cgi คือ ถ้าไม่จำเป็นต้องประมวลผล php ก็ไม่ต้องเรียกขึ้นมาใช้งาน ทำให้รับ connection ได้มากขึ้น และใช้หน่วยความจำน้อยลง และทำงานได้ไวขึ้นกว่าเดิม
ขั้นตอนบน Debian Etch มีดังนี้ โดยสมมติว่าเรามีระบบที่ให้บริการเว็บตามปกติอยู่แล้ว แต่เป็น apache2-mpm-prefork
- สร้าง directory /var/www/fcgi-bin
mkdir /var/www/fcgi-bin
- สร้างแฟ้ม /var/www/fcgi-bin/php5.fcgi ให้มีเนื้อหาดังนี้
#!/bin/sh
PHPRC="/etc/php5/cgi"
export PHPRC
PHP_FCGI_CHILDREN=4
export PHP_FCGI_CHILDREN
PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS
exec /usr/bin/php5-cgi - เปลี่ยน mode ให้ execute ได้
chmod +x /var/www/fcgi-bin/php5.fcgi
- สร้างแฟ้ม /etc/apache2/conf.d/php5-fcgid ให้มีเนื้อหาดังนี้
ScriptAlias /fcgi-bin/ /var/www/fcgi-bin/
AllowOverride None
Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
Action application/x-httpd-php /fcgi-bin/php5.fcgi
AddHandler application/x-httpd-php .php .phtml - ลบ mod-php5 แล้วติดตั้ง php5-cgi
apt-get remove libapache2-mod-php5
apt-get install php5-cgi - ติดตั้ง libapache2-mod-fcgid และเปิดใช้งาน
apt-get install libapache2-mod-fcgid
a2enmod fcgid - ถอดถอน apache2-mpm-prefork แล้วติดตั้ง apache2-mpm-worker
apt-get remove apache2-mpm-prefork
apt-get install apache2-mpm-worker
จากนั้นมันจะ start apache ตัวใหม่ให้โดยอัตโนมัติ ให้ลองทดสอบ เว็บไซต์ดูว่ายังรันได้ปกติดีหรือไม่
ถ้าใน php.ini เดิมนั้น ได้มีการปรับค่าต่างๆ ไว้ เช่น memory_limit ก็ให้ปรับในแฟ้ม /etc/php5/cgi/php.ini ตามด้วย
ทีนี้จะพบว่า จะมี process แบ่งเป็น 2 ชื่อ คือ apache2 และ php5-cgi โดย apache2 จะมีจำนวน process ไม่มากนัก และมีขนาดเล็ก ส่วน php5-cgi จะมีการ fork ไว้จำนวนหนึ่ง ซึ่งไม่ได้ทำงานตลอดเวลา คือจะทำงานเมื่อมีการเรียกแฟ้ม .php ขึ้นมาทำงานเท่านั้น ผลโดยรวมคือ ระบบเร็วขึ้นอย่างเห็นได้ชัด คราวนี้ปัญหาไปอยู่ที่ mysql server แทนละ แต่โดยรวมยังถือว่ารับมือไหว
ตอนนี้ผมมีปัญหานี้อยู่พอดี แต่ที่ใช้งานนี้อยู่บน RS6000 นะครับ
ตอบลบผู้ใข้งาน ไม่เกิน 200 คน
เดี๋ยวลองดูก่อน
ขอบคุณสำหรับวิธีการดี ๆ ครับ
ขอบคุณมากครับ กำลังมีปัญหาเรื่องนี้อยู่พอดี
ตอบลบสำหรับระบบอื่นๆ คงใช้หลักการเดียวกันแหละครับ พอดีผมอ้างอิงระบบที่ผมใช้คือ Debian เลยไม่ได้อธิบายยาวนัก
ตอบลบตอนนี้ผมใช้บนเซิร์ฟเวอร์ 2 ตัวละ ใช้ได้ดีทีเดียว
อ่อ มีปัญหาเรื่องหนึ่งคือ เนื่องจากไม่ใช่ mod_php ทำให้ไม่สามารถใช้ directive php_value php_flag หรือ php_admin_flag ใน config ของ apache หรือใน .htaccess ได้ ซึ่งถ้ามีปรากฎอยู่ จะทำให้รัน apache ไม่ได้ หรือ ถ้าอยู่ใน .htaccess จะทำให้เปิดเว็บภายใต้ directory นั้นไม่ได้ ก็ต้องเอาออก แล้วเอาไปใส่ใน php.ini แทนครับ
แล้วถ้าเป็น freeBSD 6.2 ละครับจะต้องทำอย่างไรบ้างครับ
ตอบลบอยากจะขอคำแนะนำครับ
เพราะหัวหน้าสั้งทำ web+steaming VDO + ระบบสืบค้นหนังสือด้วยนะครับ (ทำเสร็จแล้ว อยู่คนละเครื่อง)
ตอนนี้กำลังลงเครื่องที่จะเป็น web อยู่ กำลังติดตั้ง freeBSD+apache+mysql+php+phpmyadmin ครับ
ขอคำแนะนำบน freeBSD ด้วยนะครับ
ผมลองแล้ว เอาไปใช้ใน ubuntu gutsy ช่วยได้เยอะเลยครับ
ตอบลบแต่ตอนนี้กลับมีปัญหาแปลกๆมาแทน อย่างเช่น ช่วงเวลาหนึ่ง (ประมาณ 1-2 วัน) ตัว php5-cgi อยู่ๆก็โหลดขึ้นมาเพียบเลย (จากที่มี process อยู่แค่ไม่กี่ตัว) ทำให้ใช้ Memory เยอะมาก จนไปใช้ในส่วน Swap Memory สุดท้าย เครื่องก็ช้าลงจนใช้การไม่ได้ ถ้าเครื่องยังไม่ช้าเกินไป ผมยังเข้าไป Killall ได้ แต่ถ้ามันช้าจนรับไม่ได้ ผมก็ต้อง hard reboot ไปเลย ที่แปลกก็คือ พอboot กลับเข้ามาแล้ว อาการก็เกิดขึ้นอีก ต้อง reboot อยู่หลายครั้ง อาการก็หายไปเอง
ผมสงสัยว่า มีวิธีการสร้าง process ให้ php5-cgi หรือเปล่าครับ (สร้างใน /etc/init.d จะสั่ง start/stop ได้) เพราะถ้าทำได้ ผมก็ยังใช้โปรแกรมอื่นตรวจว่ามันวิ่งมากไปไหม ถ้าใช่ก็ให้ kill ทิ้งได้เลย ไม่งั้น ผมก็ต้องมานั่งตามเช็คตลอด
หรือถ้ามีวิธีแก้เลย ก็จะดีมากครับ
ขอบคุณมากครับ
ผมว่าผมลืมบอกไปสองคำสั่งนะนี่
ตอบลบ<code># apt-get install libapache2-mod-fcgid
# a2enmod fcgid</code>
เดี๋ยวอัพเดทบล็อกก่อน
มีปัญหาว่า หลังจากเปลี่ยนมาใช้ fcgid แทน mod_php แล้ว upload ไฟล์ขนาด มากกว่า 2M ไม่ได้ครับ
ตอบลบน่าจะเป็นเพราะเดิมตอนใช้ mod_php นั้น มันจะอ่าน config จาก /etc/php5/apache2/php.ini แต่เมื่อเปลี่ยนเป็น fcgid แล้ว มันจะรัน php ด้วย php-cgi ซึ่งจะอ่าน config จาก /etc/php5/cgi/php.ini แทน
ตอบลบวิธีแก้ ให้คัดลอก php.ini เดิมจาก /etc/php5/apache2/ ไปใส่ไว้ที่ /etc/php5/cgi/ แล้วรีสตาร์ต apache2 ใหม่ ก็น่าจะใช้ได้แล้วครับ
ตอนนี้ใช้อย่างนี้แหล่ะครับ host เว็บกว่าร้อยโดเมน เริ่มมีปัญหา internal server error (500)
ตอบลบกำลังจะลองทดสอบ apache2 itk mpm อยู่ครับ