504 Gateway Timeout: หมายถึงอะไรและแก้อย่างไร
· อ่าน 2 นาที
ข้อผิดพลาดนี้หมายถึงอะไร
504 คือเว็บเซิร์ฟเวอร์ด้านหน้า (nginx, Apache, load balancer, CDN) ยอมแพ้ต่อแอปพลิเคชันด้านหลัง คำขอถูกส่งต่อ แบ็กเอนด์เริ่มทำงาน และตัวจับเวลาของด้านหน้าหมดก่อนที่คำตอบจะกลับมา ความต่างจาก 502 Bad Gateway คือเข้าถึงแบ็กเอนด์ได้ แต่ช้าเกินไป ตัวจับเวลาโดยทั่วไปคือ 60 วินาทีใน nginx (fastcgi_read_timeout, proxy_read_timeout) 60 วินาทีใน Apache (ProxyTimeout) และ 100 วินาทีที่ Cloudflare ซึ่งคุณเปลี่ยนไม่ได้ในแพ็กเกจฟรี
การเพิ่ม timeout แทบไม่ใช่วิธีแก้ มีบางอย่างที่ใช้เวลานานเกินไป และสิ่งนั้นคือสิ่งที่คุณต้องหาให้เจอ
สาเหตุที่พบบ่อย
- คำสั่งฐานข้อมูลที่ช้า ปลั๊กอิน WordPress ที่นับแถวในตารางขนาดใหญ่ทุกครั้งที่โหลดหน้า index ที่หายไป ตาราง
wp_optionsที่เต็มไปด้วย transient ที่หมดอายุ ทุกคำขอต้องรอ และเมื่อโหลดหนักเวลารอสะสม - การเรียกภายนอกที่ค้าง แอปพลิเคชันติดต่อผู้ให้บริการชำระเงิน บริการอีเมล API สภาพอากาศ หรือเซิร์ฟเวอร์ไลเซนส์ และบริการนั้นช้าหรือล่ม หากการเรียกนั้นไม่มี timeout หน้าของคุณจะรอมัน
- worker น้อยเกินไป worker ของ PHP-FPM ทั้งหมดยุ่งกับคำขอที่ช้า คำขอใหม่ต่อคิวจนกว่าด้านหน้าจะยอมแพ้ จากภายนอกดูเหมือน timeout แม้แต่ละคำขอจะเร็วก็ตาม
- cron หรือการสำรองข้อมูลที่รันเบื้องหน้า ปลั๊กอินสำรองข้อมูล การนำเข้า sitemap 50,000 URL: สร้างภายในคำขอเว็บ จึงเกิน timeout ใด ๆ
- Disk I/O หรือ swap เซิร์ฟเวอร์หน่วยความจำหมดและใช้ swap ทุกอย่างช้าลงสิบเท่า เห็นเป็นโหลดสูงแต่การใช้ CPU ต่ำ
- เครือข่ายระหว่างด้านหน้าและด้านหลัง load balancer ในดาต้าเซ็นเตอร์หนึ่ง แบ็กเอนด์ในอีกแห่ง ไฟร์วอลล์ทิ้งแพ็กเก็ตเงียบ ๆ พบได้ยาก แต่ 504 ทุกคำขอขณะที่แบ็กเอนด์ว่างชี้มาที่นี่
หากคุณเป็นผู้เข้าชม
โหลดใหม่หลังผ่านไปหนึ่งนาที หากเว็บไซต์ช้ามากกว่าจะล่ม ลองหน้าอื่น timeout อาจผูกกับหน้าหนักหน้าเดียว
หากเป็นเว็บไซต์ของคุณ: ตรวจสอบก่อน
รันเครื่องมือตรวจว่าเว็บไซต์ล่มหรือไม่: รายงานรหัสสถานะและเวลาตอบสนองจากภายนอก เว็บไซต์ที่ตอบใน 30 วินาทีวันนี้คือเว็บไซต์ที่จะแสดง 504 เมื่อโหลดหนักพรุ่งนี้
บนเซิร์ฟเวอร์ของคุณเอง ดูว่าเวลาหายไปที่ไหน:
# worker กำลังสะสมอยู่ไหม
sudo tail -n 30 /var/log/nginx/error.log | grep -E 'timed out|timeout'
# ตอนนี้ PHP กำลังทำอะไร (ต้องมี pm.status_path ใน pool)
curl -s 'http://127.0.0.1/fpm-status?full' | grep -E 'state|request URI|duration' | head -40
# MySQL/MariaDB: คำสั่งใดกำลังรันและนานแค่ไหน
sudo mysql -e 'SHOW FULL PROCESSLIST;'
# หน่วยความจำและ swap
free -m
vmstat 1 5
รายการโพรเซสที่เต็มไปด้วยคำสั่งเดียวกัน หรือคอลัมน์ si/so ใน vmstat ที่ไม่เป็นศูนย์ บอกสาเหตุได้
วิธีแก้บนเซิร์ฟเวอร์ของคุณเอง
1. เปิด slow query log และแก้คำสั่ง
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
หลังผ่านไปไม่กี่นาที sudo mysqldumpslow -s t /var/log/mysql/slow.log | head แสดงรายการคำสั่งที่แย่ที่สุด เพิ่ม index ที่หายไป หรือหาปลั๊กอินที่รันคำสั่งนั้นและแทนที่ ใน WordPress ตาราง options ที่บวมเป็นกรณีคลาสสิก:
wp transient delete --all
wp db query "SELECT option_name, LENGTH(option_value) AS size FROM wp_options WHERE autoload='yes' ORDER BY size DESC LIMIT 20;"
อะไรก็ตามที่ขนาดหลายร้อยกิโลไบต์และโหลดอัตโนมัติทุกคำขอเป็นตัวเลือกที่ควรลบ
2. ตั้ง timeout ให้การเรียกภายนอก
ทุกการเรียก HTTP ที่แอปพลิเคชันของคุณทำต้องมี timeout ของตัวเอง สั้นกว่าของเว็บเซิร์ฟเวอร์ ใน PHP กับ cURL: CURLOPT_CONNECTTIMEOUT 5 และ CURLOPT_TIMEOUT 10 ใน WordPress wp_remote_get() รับอาร์กิวเมนต์ timeout หลายปลั๊กอินปล่อยเป็นค่าเริ่มต้นและรอไม่สิ้นสุด หากบริการของบุคคลที่สามล่ม หน้าควรลดระดับการทำงาน (แสดงฟอร์มโดยไม่มีค่าจัดส่งแบบสด) ไม่ใช่ตาย
3. ย้ายงานยาวออกจากคำขอ
การสำรองข้อมูล การนำเข้า การส่งออก sitemap ขนาดใหญ่ และการส่งอีเมลควรอยู่ใน cron job หรือคิว ไม่ใช่ในการดูหน้า สำหรับ WordPress ปิด pseudo-cron และรันตัวจริง:
// wp-config.php
define('DISABLE_WP_CRON', true);
# crontab -e
*/5 * * * * cd /var/www/example.com && wp cron event run --due-now >/dev/null 2>&1
4. ปรับ timeout อย่างระมัดระวัง
หากหน้าเดียวต้องการเวลานานกว่าอย่างชอบธรรม (การส่งออกในหน้าแอดมิน รายงาน) ให้เพิ่ม timeout เฉพาะ location นั้น ไม่ใช่ทั้งระบบ:
location = /wp-admin/export.php {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_read_timeout 300;
}
Apache กับ PHP-FPM: ProxyTimeout 300 ภายใน <Location> block PHP เองมี max_execution_time ตั้งให้เท่ากัน ไม่เช่นนั้น PHP หยุดก่อนและคุณจะได้ 500 แทน จากนั้น sudo nginx -t && sudo systemctl reload nginx
5. หยุดการใช้ swap
ps aux --sort=-%mem | head
หาก worker ของ PHP-FPM แต่ละตัวใช้ 150 MB และคุณรัน 30 ตัวบนเซิร์ฟเวอร์ 4 GB ตัวเลขไม่ลงตัว ลด pm.max_children เพิ่มหน่วยความจำ หรือแก้ปลั๊กอินที่ใช้หน่วยความจำ เซิร์ฟเวอร์ที่ไม่ใช้ swap คือเซิร์ฟเวอร์ที่ 504 ส่วนใหญ่หายไป
6. แคช
แคชทั้งหน้า (nginx FastCGI cache, ปลั๊กอินแคชของ WordPress, Varnish) ให้บริการผู้เข้าชมซ้ำโดยไม่แตะ PHP หรือฐานข้อมูล 504 ส่วนใหญ่ภายใต้โหลดหนักหายไปเมื่อหน้าแรกและหน้ายอดนิยมมาจากแคช
เมื่อเป็นปัญหาของผู้ให้บริการโฮสติ้ง
บน shared hosting คุณแก้คำสั่งช้าและปลั๊กอินได้ แต่แก้ timeout ของเซิร์ฟเวอร์หรือโหลดของเพื่อนบ้านไม่ได้ ส่งข้อความนี้ให้ผู้ให้บริการโฮสติ้ง:
สวัสดี เว็บไซต์ของฉัน example.com ส่งคืน “504 Gateway Timeout” ตั้งแต่ประมาณ 16:00 UTC หน้าที่เคยโหลดในไม่ถึงสองวินาทีตอนนี้หมดเวลา ฉันไม่ได้เปลี่ยนแปลงอะไร กรุณาตรวจสอบว่าเซิร์ฟเวอร์ฐานข้อมูลหรือ PHP pool ของบัญชีฉันโหลดเกินหรือไม่ หรือบัญชีอื่นบนเซิร์ฟเวอร์ทำให้โหลดสูง และแจ้งสิ่งที่พบ
ป้องกันครั้งต่อไป
504 คือเว็บไซต์ที่ช้าและช้าลงอีก และเวลาตอบสนองวัดได้นานก่อน timeout การตรวจสอบเว็บไซต์บันทึกเวลาตอบสนองของทุกการตรวจสอบ ตั้งการแจ้งเตือนไว้ แล้วคุณจะเห็นแนวโน้มหลายสัปดาห์ก่อนที่ผู้เข้าชมจะเห็นข้อผิดพลาด เซิร์ฟเวอร์เอเจนต์เพิ่มโหลด หน่วยความจำ และ swap จากภายใน บนเซิร์ฟเวอร์ของคุณเอง Deep Fix หาคำสั่งช้าหรือการเรียกที่ค้างและแก้ให้ คิดเป็นช่วงละ 15 นาที เห็นราคาก่อนสั่งซื้อ
ขั้นต่อไป
ตรวจจากภายนอก
เว็บไซต์ล่มสำหรับทุกคนหรือเฉพาะคุณ และเซิร์ฟเวอร์ตอบกลับอย่างไร ฟรี ไม่ต้องสมัคร
เครื่องมือตรวจว่าเว็บไซต์ล่มหรือไม่ล่มใช่ไหม เราเข้าไปจัดการ
บนเซิร์ฟเวอร์ของคุณเองหรือเว็บสเปซที่มี SSH: Quick Fix ในราคาคงที่สำหรับสาเหตุที่พบบ่อย Deep Fix คิดเป็นช่วงละ 15 นาทีสำหรับส่วนที่เหลือ ตลอด 24 ชั่วโมง เห็นราคาก่อนสั่งซื้อ
ให้เราซ่อมแซมคู่มืออื่น ๆ
- เว็บไซต์ของคุณล่ม นี่คือสิ่งที่ต้องทำใน 15 นาทีแรก
- เซิร์ฟเวอร์ล่ม: ต้องตรวจอะไรก่อน และตามลำดับไหน
- 502 Bad Gateway: สาเหตุและวิธีแก้
- 503 Service Unavailable: โหลดเกินหรืออยู่ในโหมดบำรุงรักษา
- DNS_PROBE_FINISHED_NXDOMAIN: สาเหตุและวิธีแก้
- ERR_CONNECTION_REFUSED: สาเหตุและวิธีแก้
- “การเชื่อมต่อของคุณไม่เป็นส่วนตัว”: คำเตือนใบรับรอง SSL