NGINX為何會502 Bad Gateway

NGINX作為reverse proxy效果非常的好。最近一場暴增的流量讓我們遇到了502 Bad Gateway的狀況。於是著手釐清為何會發生502 Bad Gateway、及如何解決?

為何502

首先,先說明NGINX為何會丟出502 Bad Gateway?說穿了,就是NGINX認為後端的WEB主機都無法提供服務時…當下,NGINX的錯誤log也會留下以下記錄…
no live upstreams while connecting to upstream
NGINX是如何判斷後端的WEB主機無法提供服務呢?目前有提供以下兩種方式
  1. Passive Health ChecksNGINX Open SourceNGINX Plus都支援
  2. Active Health Checks,僅NGINX Plus支援

Passive Health Checks

本文以Passive Health Checks做討論。在此模式下,以下面兩個參數控制NGINX
  • max_fails – 設定失敗幾次就將後端主機標示為無法使用(unavailable),NGINX就不送request給該主機。預設為1,如設定為0表示不計數。
  • fail_timeout – 當後端主機被標示為無法使用(unavailable)後,NGINX就不送request給該主機,直到超過fail_timeout時間。預設為10秒
當後端所有主機都符合上述兩個參數時,NGINX會認為無法將request傳送到後端主機時,就產生了502 Bad Gateway

這裡要特別提醒一件事情,當upstream中『只有設定』一台主機時,NGINX會忽略fail_timeout和max_fails。也就是說,不會將該主機設定為無法使用(unavailable)。

這點非常重要,因為在我們模擬、測試502狀態的過程中,一開始就僅設定一台主機。所以每次測試的結果都不同。直到在upstream中增加第二台後,測試結果才和官方文件所述相符。

error/timeout設定

NGINX如何判斷後端主機為無法使用(unavailable)呢?是依據proxy_next_upstream。預設如下
proxy_next_upstream error timeout;
如果有需要可以增加其他的狀態。不過…一般情況下,預設已經足夠。

接下來的疑問就是error、timeout的定義為何?這時就和下面三個參數有關了
  1. proxy_connect_timeout
  2. proxy_send_timeout
  3. proxy_read_timeout
proxy_connect_timeout這參數有一點要注意,如果設定大於75秒,NGINX依舊只會使用75秒(看網路上很多文章都設定為90秒,其實是沒有效果的。因為到了75秒時,NGINX就會產生timeout錯誤。)

另兩個參數的解釋就容易讓人困惑,以proxy_send_timeout為例,NGINX官方解釋如下…
Defines a timeout for reading a response from the proxied server. The timeout is set only between two successive read operations, not for the transmission of the whole response. If the proxied server does not transmit anything within this time, the connection is closed.
文中所提two successive read operations是什麼意思?寫得既簡單、又清楚,卻令人想得很複雜呀~ 這篇文章-nginx和php-fpm連接超時之解決方法有提供一個PHP的範例做說明,建議可以參考。

至於這三個參數該如何設定、拿捏?必須依據實際服務的狀況、前端網頁的架構才能決定,沒有一定的答案…


參考資料

留言