早上起來打開網站,白頁上寫著幾個斗大的字:502 Bad Gateway。這大概是每個用 VPS 架站的人最熟悉也最頭痛的景象——尤其 WordPress、WooCommerce 一類的網站,流量一上來、外掛一多,502 就像老朋友一樣不請自來。
先給結論:502 不是一種錯誤,而是一類「反向代理收不到上游有效回應」的統稱。在 Nginx + PHP-FPM 的常見架構裡,超過 80% 的 502 根源是 PHP-FPM 沒在跑、監聽路徑不一致,或 PHP 進程數/記憶體不夠,而不是 Nginx 本身壞了。所以別只重啟 Nginx——那只能解一時之渴,幾分鐘後 502 就會再回來。照著本文的 6 步排查,由近到遠、由快到慢,10 分鐘內就能把真正的原因揪出來。
本文從「錯誤頁面長什麼樣子」開始判讀,教你看懂 Nginx error.log 裡最常見的關鍵字,再拆解 PHP-FPM、Node.js、Apache 三種後端各自容易踩的坑,最後補上 CDN/Cloudflare、資料庫與外站 API 等上層原因。文中指令輸出為示範格式,IP 採用文件專用保留位址(RFC 5737 的 192.0.2.0/24 與 203.0.113.0/24),實際數值請以你的 VPS 環境為準。如果你剛開始架站還不太熟悉,建議搭配〈SSH 連不上怎麼辦?7 步完整排查指南〉與〈2026 用 VPS 架設 WordPress 完整教學〉一起閱讀。
為什麼會 502?先理解請求鏈路
想快速定位 502,一定要先知道「一個 HTTP 請求從你瀏覽器送出,到網頁回來」這中間經過了哪些節點。任何一個節點掛掉,都可能回你一頁 502。
以最常見的「Cloudflare + Nginx + PHP-FPM + MySQL」WordPress 架構為例,一個請求會依序經過:
- 使用者瀏覽器:送出 HTTP 請求。
- CDN / WAF(如 Cloudflare):快取與防護層,異常時會先吐自己的 502 頁。
- Nginx / Apache(反向代理):真正對外接 request 的那一個,也是 502 頁面最常見的署名者。
- 後端應用:PHP-FPM、Node.js(PM2)、Gunicorn(Python)、Tomcat(Java)……它是真正跑程式的地方。
- 資料庫與快取:MySQL、MariaDB、PostgreSQL、Redis。
- 外部服務:金流、簡訊、社群登入外掛、第三方 API。
關鍵觀念:Nginx 本身只是「收發員」——它收到請求後,要轉交給後端(PHP-FPM 等)處理。502 就是 Nginx 對你說:「我要交給後端,但後端那邊連不上/馬上掛斷/回了個看不懂的東西」。所以絕大多數時候,問題不在 Nginx,而在它背後。
502、503、504 怎麼分?錯誤頁面一看就懂
同樣是「網站打不開」,500、502、503、504 代表的問題完全不同,藥方也不一樣。先看錯誤頁面上的署名與關鍵字,可以直接縮小一半排查範圍。
| 錯誤頁面長相 | 代表含義 | 第一個要查的地方 |
|---|---|---|
| 白色頁面、中央寫著「502 Bad Gateway」、小字標 nginx | Nginx 連不上上游(最經典的 502) | PHP-FPM 是否啟動、fastcgi_pass 路徑 |
| 帶有 Cloudflare 商標、Ray ID 的 502 頁 | Cloudflare 回源失敗 | 先暫停 Cloudflare 代理(灰雲)直連源站測試 |
| 「502 Bad Gateway」+ Apache/2.4.x 署名 | Apache mod_proxy 連不上後端 | 後端服務、ProxyPass 設定 |
| 「504 Gateway Timeout」 | 連上了但等太久才回應 | 慢查詢、外站 API 逾時、timeout 設定 |
| 「503 Service Unavailable」 | 服務暫時不可用(過載/維護) | 連線數是否滿、是否啟用維護頁 |
| 「500 Internal Server Error」+ PHP 報錯 | 程式碼或設定語法錯誤 | PHP/網站程式本身的 log |
小提醒:Nginx 預設的 502 頁面是乾淨的白色畫面;如果你看到的是主機商的客製頁、CDN 的錯誤頁,或是 WordPress 外掛的錯誤頁,先用瀏覽器無痕模式、或用 curl 直接打主機 IP,才能看到最原始的錯誤署名:
curl -I https://你的網域/
# 或直接打主機 IP 略過 CDN
curl -I -H "Host: 你的網域" http://203.0.113.10/
60 秒快速排查:3 件事先做
如果你現在網站正 502、使用者在罵、老闆在催,先做這 3 件事,八成能在一分鐘內讓網站先活回來:
- 強制刷新(Ctrl+F5)或開無痕視窗測試——排除瀏覽器快取、擋廣告外掛干擾,避免被舊快取誤導。
- SSH 進去重啟 PHP-FPM(而不是 Nginx):
WordPress 網站超過一半的 502,重啟 PHP-FPM 就會先恢復。如果重啟完立刻又 502,代表進程被持續打掛,再往下查。# Ubuntu / Debian,依你的 PHP 版本替換 8.3 sudo systemctl restart php8.3-fpm sudo systemctl status php8.3-fpm - 看 Nginx 錯誤日誌最後 20 行:
看到sudo tail -n 20 /var/log/nginx/error.logConnection refused=後端沒跑;Connection reset by peer=後端 crash;upstream timed out=其實是 504 而非 502。
做完這三步,如果網站已經恢復,可以回頭看本文後面的「預防措施」章節讓它不再復發;如果還是 502,就照下面的 6 步完整流程走。
6 步完整排查流程(附指令)
下面的流程刻意由近到遠、由快到慢排列:每一步都能在 1-2 分鐘內完成,並把問題範圍砍掉一半。
步驟 1:刷新 + 無痕模式,排除本機與 CDN 快取
先用 Ctrl+Shift+N(Chrome)或 Cmd+Shift+N 開無痕視窗,直接造訪你的網站。若無痕正常、一般視窗不正常,那就是瀏覽器快取或擋廣告外掛造成的假象。也可以用手機切 4G/5G 連線測試,排除來源 IP 或公司網路的問題。
步驟 2:讀 Nginx error.log —— 一條訊息定生死
所有 502 的關鍵證據都在 /var/log/nginx/error.log。打開這檔案前,先做一次「重現 502」的動作(用瀏覽器重整一次),日誌裡最新那幾行就是直接證據。
常用指令:
# 即時監看錯誤日誌(重整一次網站就會看到新訊息)
sudo tail -f /var/log/nginx/error.log
# 只看上週和 upstream 有關的錯誤
sudo grep -i "upstream" /var/log/nginx/error.log | tail -n 50
# 同時看 access.log 確認請求是否真的進來
sudo tail -f /var/log/nginx/access.log
以下是你最常看到的幾行關鍵字與它們的含義:
connect() failed (111: Connection refused) while connecting to upstream—— 最最常見。Nginx 要連後端,但那個 port/socket 根本沒人在聽。原因幾乎是 PHP-FPM 沒啟動、或 Nginx 和 PHP-FPM 設定的監聽路徑不一致。recv() failed (104: Connection reset by peer)—— 後端進程處理到一半被強制中斷。常見於 PHP 程式 fatal error、PHP-FPM 進程數被打滿,或記憶體不足被 OOM kill。upstream sent invalid header—— 後端回傳了壞掉的 HTTP header,多半是 PHP 程式 crash、某個外掛亂輸出東西。no live upstreams—— 負載均衡場景所有後端都掛了(多台應用伺服器時才會看到)。upstream prematurely closed connection—— 後端主動把連線關了,常見於 PHP 執行逾時、程式 exit/die 太早。upstream timed out (110: Connection timed out)—— 注意!這其實是 504 不是 502,表示連上了但回應太慢,要往慢查詢、外站 API 方向查。SSL_do_handshake() failed—— CDN 回源的 SSL 握手失敗(多半是 Cloudflare SSL 模式設成「Full」但源站沒憑證、或憑證過期)。
步驟 3:檢查後端服務是否真的在跑
確認 log 裡是 Connection refused 之後,第一件事就是查你後端服務的狀態。不同後端指令不同:
PHP-FPM(WordPress/Laravel 最常見)
# 查狀態(請替換成你的 PHP 版本,可 ls /etc/php/ 看有哪些版本)
sudo systemctl status php8.3-fpm
# 如果是 inactive / failed,重啟它
sudo systemctl restart php8.3-fpm
sudo systemctl enable php8.3-fpm # 順手設成開機自啟,避免重開機後又 502
Node.js(PM2 管理)
pm2 status
pm2 logs --lines 50
pm2 restart all
Python(Gunicorn/uWSGI)
sudo systemctl status gunicorn
sudo journalctl -u gunicorn -n 50 --no-pager
Apache 同時當後端時
sudo systemctl status apache2 # Debian/Ubuntu
sudo systemctl status httpd # CentOS/Rocky
常見踩坑:一台 VPS 上同時裝了 PHP 8.1 與 8.3,你重啟的是 php8.1-fpm,但 Nginx 設定裡 fastcgi_pass 指的是 php8.3-fpm.sock——結果你以為重啟了,其實重錯版本。先用 ls /etc/php/ 與 ls /run/php/ 確認實際在跑的版本。
步驟 4:確認 Socket/Port 兩邊對得上
這是網管圈最有名的「明明都在跑為什麼還是 502」的原因:Nginx 設定裡的 fastcgi_pass(或 proxy_pass),和 PHP-FPM pool 設定裡的 listen,根本不是同一條路。
請比對這兩個設定:
# 1) 看 Nginx 站台設定裡的 fastcgi_pass
sudo grep -R "fastcgi_pass" /etc/nginx/sites-enabled/ /etc/nginx/conf.d/
# 常見會看到兩種:
# fastcgi_pass unix:/run/php/php8.3-fpm.sock; ← Unix Socket
# fastcgi_pass 127.0.0.1:9000; ← TCP Port
# 2) 看 PHP-FPM pool 的 listen
sudo grep -R "^listen" /etc/php/8.3/fpm/pool.d/
# 輸出例如:listen = /run/php/php8.3-fpm.sock
兩邊必須完全一致:如果 Nginx 用 unix:/run/php/php8.3-fpm.sock,PHP-FPM 的 listen 就必須是同一個路徑;如果一邊走 socket、一邊走 127.0.0.1:9000,永遠都會是 Connection refused。修改完記得兩邊都重啟:
sudo systemctl restart php8.3-fpm
sudo systemctl reload nginx
Socket 檔案常見的另外兩個雷:
- 權限不對:socket 檔案必須讓 Nginx 的執行使用者(www-data 或 nginx)可以讀寫。可在 pool 設定中加
listen.owner = www-data、listen.group = www-data、listen.mode = 0660。 - 檔案不存在:如果
/run/php/php8.3-fpm.sock根本沒有這個檔,多半是 PHP-FPM 啟動失敗,回去看systemctl status php8.3-fpm的錯誤訊息。
步驟 5:檢查系統資源——是不是被 OOM 殺了
如果你發現「重啟後好個幾分鐘又 502」,幾乎可以肯定是資源爆了。PHP-FPM 的 worker 吃到記憶體用盡、CPU 被某個 cron 打滿、硬碟滿到寫不進 session,都會讓後端進程反覆 crash。
快速檢查指令:
# CPU 與記憶體即時狀態(按 q 離開)
top
# 記憶體與 swap
free -h
# 硬碟用量(如果 / 分區 100%,MySQL 與 PHP 都會崩)
df -h
# 查是不是被 OOM Killer 砍了(有輸出就是中獎)
dmesg -T | grep -i "killed process\|out of memory"
# 磁碟 I/O 等待(需安裝 sysstat)
sudo apt install -y sysstat && iostat 1 5
WordPress 常見元兇:記憶體不足時,Linux 會啟動 OOM Killer 直接把「最胖」的進程殺掉——而最胖的通常就是 PHP-FPM worker。你可以從 dmesg 看到 Killed process XXXX (php-fpm8.3) 字樣。解法:升級記憶體、或降低 pm.max_children 避免同時跑太多 worker;硬灌 swap 只能治標。
步驟 6:往上層與旁支查——CDN、資料庫、外站 API
前面 5 步都正常但依然 502?問題可能不在這台機器本身,而在請求鏈路的更上游或下游:
- Cloudflare 或其他 CDN:先把雲朵切成「灰色雲朵(僅 DNS)」直連源站,若直連正常=CDN 問題;常見原因是 SSL 模式(要設 Full/Strict)、WAF 規則擋了回源 IP、或 Cloudflare 自己的節點故障。
- 資料庫連不上:MySQL/MariaDB 掛掉或連線數打滿,PHP 會等待直到逾時或丟擲例外。檢查
sudo systemctl status mysql,並看 PHP 外掛是否有設定正確的 DB 主機位址(不要寫 localhost 卻強制走 TCP socket)。 - Redis/快取服務:物件快取外掛若連不上 Redis,某些設定會直接導致整個 WordPress 卡住在連線階段。
- 外站 API 逾時/阻擋:某些金流、統計、爬蟲外掛會同步呼叫外部 API,對方掛掉或被牆時,整個請求就卡死,最後被 Nginx 切斷,看起來就像 502/504。
判斷是不是外站 API 的問題最簡單的方法:用 WP Debug 或暫時停用所有外掛,看網站是否恢復;若停用就好,再一個個打開找出元凶外掛。
不同後端的常見雷點(PHP-FPM/Node/Apache)
如果你不是跑 WordPress,而是其他技術棧,下面幾個雷點特別常見:
PHP-FPM(WordPress/Laravel)
- pm.max_children 過小:流量尖峰時 request 被直接拒絕,Nginx 收到 reset,網誌會出現
server reached pm.max_children setting。建議值=可用記憶體 ÷ 每個 worker 平均記憶體(可用ps -ylC php-fpm8.3 --sort:rss估算,一般抓 30–60MB/worker)。 - request_terminate_timeout 太長:導致慢請求霸佔 worker,久了整池被卡死。WordPress 網站建議設在 60–120 秒。
- opcache 滿了:升級程式後若出現隨機 502,可重啟 PHP-FPM 清 opcode 快取。
Node.js(Next.js/Nuxt/Express,常用 PM2 管理)
- Nginx 裡
proxy_pass要指向 Node 真正監聽的埠(例如http://127.0.0.1:3000),埠號錯了就是 Connection refused。 - Node 程式例外未補獲(unhandledException)會讓整個進程退出,建議以
pm2 start app.js --name mysite啟用自動重啟。 - Node 是單執行緒,一個同步阻塞就能把所有請求卡死,Nginx 會等到逾時後回 504;建議用 cluster 模式或 PM2 的 instances=max。
Apache 當前端、或 Nginx+Apache 組合
- 如果你看到署名是 Apache 的 502,多半是
mod_proxy反代到後端時連不上 Tomcat/Node 等服務,請查/var/log/apache2/error.log。 - 有些主機面板(如 cPanel、寶塔)是 Nginx 反代 Apache(80→8080),Apache 掛了一樣 502,要
systemctl status apache2兩邊都確認。
上層原因:CDN、Cloudflare、資料庫與外站 API
當 VPS 本身一切正常,但外面看仍是 502,問題就在「VPS 之外」。這一層級的 502 最容易被誤判成自己機器的問題。
Cloudflare 502 的典型處理
- 到 Cloudflare 後台,把該網域的雲朵切為 僅 DNS(灰色),直接用主機 IP 造訪;
- 直連正常=Cloudflare 端問題,檢查 SSL/TLS 加密模式是否設為 Full 或 Full (Strict)(不要用 Flexible,那會讓回源走 80,但源站強制跳 443,造成回源失敗);
- 到「安全性 > 事件」看是不是 WAF 規則封鎖了某個請求;
- 若 Ray ID 開頭錯誤頁是 「Error 502: Bad Gateway(Ray ID: xxxxx)」並附 cloudflare,多半是 Cloudflare 到你源站的連線被中斷,確認源站 IP 是否正確、10分鐘內是否換過機房。
資料庫與 Redis
資料庫掛掉通常造成的是 500/504 居多,但如果 WordPress 設定了錯誤的 DB host(例如把 DB_HOST 設成一個不存在的 socket 路徑),PHP 在連線階段就會直接退出,Nginx 端看到的也會是 502。快速檢查:
sudo systemctl status mysql
mysql -u root -p -e "SHOW PROCESSLIST;"
# WordPress 的話,確認 wp-config.php 內 DB_HOST 是 'localhost' 還是 '127.0.0.1',
# 一個走 unix socket、一個走 TCP,選錯會連不上
外站 API 與外掛
這是 WordPress 網站非常常見的間歇性 502 元兇:統計外掛、SEO 外掛、金流外掛會在頁面載入時同步呼叫外部 API,對方主機偶發逾時或被 GFW 干擾,就會把整個 PHP 程序卡死超過執行時限,最後被 Nginx 切斷。
解法:在 wp-config.php 暫時加上 define('WP_DEBUG', true); 看錯誤;或用 WP-CLI 批次停用外掛逐一比對:
cd /var/www/你的網站
wp plugin deactivate --all
wp plugin activate 外掛名稱 # 一個個打開比對
如何讓 502 不再找上門
502 最大的特點是「治好了但還會復發」,因為大多數人只重啟服務、不處理根因。以下幾個設定做好,可以把 502 的機率壓到極低:
- PHP-FPM 合理調參:依照 VPS 記憶體大小設定
pm.max_children(1GB 主機別開到 50,20 個左右就差不多),開啟pm.status_path觀察實際用量。 - 設定程序監控與自動重啟:
# 系統層級自動重啟(PHP-FPM 預設通常已啟用,可確認) sudo systemctl edit php8.3-fpm # 在 [Service] 段加上: # Restart=on-failure # RestartSec=2 # 或安裝更進階的監控(如 monit / supervisord),可在進程掛掉 5 秒內自動拉起 - 加 swap 與 OOM 保護:1GB 記憶體的入門 VPS 一定要加 1–2GB swap,避免瞬間記憶體峰值直接把 PHP-FPM 砍掉(但 swap 只是緩衝,記憶體長期不夠還是要升級方案)。
- Nginx 層級做限流與降載:設定
limit_req_zone與合理的client_max_body_size,避免突然的流量高峰或惡意掃描把 PHP-FPM 打滿。 - 定期更新與重啟:套件升級後(尤其是 PHP/Nginx 大版本升級),務必確認 PHP-FPM 與 Nginx 都活著,許多人跑了 apt upgrade 就以為沒事,結果套件升級把 PHP-FPM 停了卻沒拉起來。
- 外掛最小化原則:WordPress 網站外掛越少越穩,每多一個外掛就多一個 crash、多一個外部 HTTP 請求的風險。建議用不到的外掛直接停用移除,不要放著。
- 監控告警:安裝 Uptime Kuma 之類的簡單監控,網站 502 立刻通知,別等使用者告訴你。
如果你是用 LuckVM 的 VPS,我們建議入門建站至少選 2GB 記憶體以上的方案;1GB 方案跑 WordPress + WooCommerce + 幾個外掛,在尖峰時段很容易因記憶體不足出現隨機 502。可參考全系列 VPS 方案與香港 VPS 低延遲方案,或日本 IIJ+SoftBank 雙線 VPS(台港延遲 30ms 起)。
什麼情況該聯繫 LuckVM 客服
502 大多是站長自己的應用層問題(PHP-FPM、程式碼、外掛),主機商幫不上忙;但以下幾種情況可能是底層或網路問題,應立即聯繫我們的 24h 客服:
- 你連 SSH 都進不去,也無法從 VNC/控制台緊急控制台登入(可能是底層 Hypervisor、硬碟或網路問題);
- 主機 IP 在台灣/香港本地被大規模封鎖(如 tracert 在骨幹節點之後全部不通);
- 你確認 VPS 內所有服務都正常,但多個不同地區的朋友都打不開,且沒有 Cloudflare 這類中間層;
- dmesg 出現硬碟 I/O error、filesystem corruption、記憶體 ECC error 等硬體層訊息;
- 重開機後 VNC 畫面卡在開機流程、無法進入系統。
聯繫客服時,請準備好以下資訊可以大幅加快處理速度:
- VPS 的公網 IP 與開通時間;
- 錯誤頁面截圖(含 Ray ID 若有 Cloudflare);
/var/log/nginx/error.log最後 30–50 行;systemctl status php8.x-fpm與free -h的輸出;- 「什麼時間開始 502」、「發生之前你做了什麼操作(升級套件、改設定、安裝外掛等)」。
你可以透過網站右下角客服按鈕、聯絡我們 頁面,或官方 Line 客服/Telegram 客服(連結同官網頁尾)隨時聯繫,我們全年無休。
常見問題 FAQ
| 為什麼重新整理有時候好、有時候 502? | 間歇性 502 幾乎都是後端進程不穩定:PHP-FPM 的 pm.max_children 太小、記憶體不足導致 worker 被 OOM kill 後又被 pm 拉起、或資料庫慢查詢造成部分請求逾時。可從 Nginx 與 PHP-FPM 日誌中觀察是否同時出現 recv() failed 或 server reached pm.max_children。 |
|---|---|
| 502 跟 504 到底差在哪裡? | 502 Bad Gateway 代表反向代理(如 Nginx)連不上上游、或上游立刻把連線切斷,屬於「連不上/被拒絕」;504 Gateway Timeout 代表連上了上游,但上游太久沒回應,屬於「等不到」。修法完全不同:502 要查後端服務是否活著、Socket 路徑是否對;504 要查程式執行時間、資料庫查詢或 Nginx 的 proxy_read_timeout。 |
| 重啟 Nginx 就能暫時恢復,但幾分鐘後又 502,為什麼? | 這表示問題不在 Nginx 本身,而在它背後的 PHP-FPM 或其他後端服務。單獨重啟 Nginx 相當於清掉舊連線,但後端崩潰或記憶體外洩的根因仍在。應當查看 dmesg 是否有 OOM Killer 紀錄、PHP-FPM 日誌是否有 max_children 警告,並檢查 free -h 的記憶體使用量。 |
| 網站掛了 Cloudflare,502 是 Cloudflare 的問題還是源站的問題? | 看到 Cloudflare 的 502 頁面(含 Ray ID),先暫時把雲朵設為「僅 DNS(灰色雲朵)」直接訪問源站。如果直連源站也是 502,那就是源站後端出問題,請照本文步驟排查;如果直連正常但透過 Cloudflare 出 502,多半是 SSL 模式不對(應設為 Full/Strict)、源站 IP 填錯或 WAF 規則擋住了回源。 |
| 重裝 PHP 或重開機都沒用,502 一直存在? | 九成是 Nginx 的 fastcgi_pass(或 proxy_pass)和 PHP-FPM pool 的 listen 參數沒有對上——一個寫 127.0.0.1:9000、一個走 unix socket,就會永遠 connect() failed (111: Connection refused)。請比對 /etc/nginx/sites-available/ 裡的設定與 /etc/php/8.x/fpm/pool.d/www.conf 中的 listen 值,並確認 Nginx 與 PHP-FPM 使用同一個 PHP 版本。 |
還在被 502 折騰?換一台穩定的 VPS 從根源解決
很多看似「設定問題」的 502,背後其實是主機超賣、記憶體不足、線路不穩。LuckVM 香港/日本/台灣/美國/新加坡/韓國/越南七大節點均採用企業級硬體與三網直連線路,7x24 小時技術支援,遇到問題不用自己一個人翻日誌。新用戶輸入優惠碼 BLOG2026 可享額外 9 折優惠(實際折扣以結帳頁顯示為準)。
延伸閱讀:SSH 連不上 7 步排查.WordPress 架站完整教學.VPS 安全防護與備份教學.VPS 延遲高怎麼辦.VPS 常見問題疑難雜症大全
本文由 LuckVM 技術團隊撰寫與維護,最後更新:2026-09-26。文中指令已於 Ubuntu 24.04 + Nginx 1.24 + PHP 8.3 FPM 環境驗證;其他發行版(CentOS、Rocky、AlmaLinux)指令路徑可能略有差異,請自行對應調整。若這篇文章對你有幫助,歡迎分享給身邊的站長朋友。




