原文地址:http://raocl.spaces.live.com/blog/cns!3F6CFF93FD0E3B79!181.entry http://edu.codepub.com/2010/0504/22510.php
Nginx 502 Bad Gateway的含義是請求的PHP-CGI已經執行,但是由於某種原因(一般是讀取資源的問題)沒有執行完畢而導致PHP-CGI進程終止。
Nginx 504 Gateway Time-out的含義是所請求的網關沒有請求到,簡單來說就是沒有請求到可以執行的PHP-CGI。
解決這兩個問題其實是需要綜合思考的,一般來說Nginx 502 Bad Gateway和php-fpm.conf的設定有關,而Nginx 504 Gateway Time-out則是與nginx.conf的設定有關。
1.查看FastCGI進程是否已經啟動
NGINX 502錯誤的含義是sock、連接埠沒被監聽造成的。我們先檢查fastcgi是否在運行
2.檢查系統Fastcgi進程運行情況
除了第一種情況,fastcgi進程數不夠用、php執行時間長、或者是php-cgi進程死掉也可能造成nginx的502錯誤
運行以下命令判斷是否接近FastCGI進程,如果fastcgi進程數接近設定檔中設定的數值,表明worker進程數設定太少
netstat -anpo | grep "php-cgi" | wc -l
3.FastCGI執行時間過長
根據實際情況調高以下參數值
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
4.頭部太大這種情況可能是由於nginx預設的fastcgi進程響應的緩衝區太小造成的, 這將導致fastcgi進程被掛起, 如果你的fastcgi服務對這個掛起處理的不好, 那麼最後就極有可能導致504 Gateway Time-out
現在的網站, 尤其某些論壇有大量的回複和很多內容的, 一個頁面甚至有幾百K
預設的fastcgi進程響應的緩衝區是8K, 我們可以設定大點: fastcgi_buffer_size 128k;
fastcgi_buffers 8 128k;
如果你使用的是nginx的負載平衡Proxying,調整
proxy_buffer_size 16k; 這裡參數調大
proxy_buffers 4 16k;
5.https轉寄配置錯誤
正確的配置方法
server_name www.xok.la;
location /myproj/repos {
set $fixed_destination $http_destination;
if ( $http_destination ~* ^https(.*)$ )
{
set $fixed_destination http$1;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Destination $fixed_destination;
proxy_pass http://subversion_hosts;
}
下面我們來仔細分析一下php-fpm.conf幾個重要的參數:
php-fpm.conf有兩個至關重要的參數,一個是”max_children”,另一個是”request_terminate_timeout”
我的兩個設定的值一個是”40″,一個是”900″,但是這個值不是通用的,而是需要自己計算的。
計算的方式如下:
如果你的伺服器效能足夠好,且寬頻資源足夠充足,PHP指令碼沒有系迴圈或BUG的話你可以直接將”request_terminate_timeout” 設定成0s。0s的含義是讓PHP-CGI一直執行下去而沒有時間限制。而如果你做不到這一點,也就是說你的PHP-CGI可能出現某個BUG,或者你的寬頻不夠充足或者其他的原因導致你的PHP-CGI能夠假死那麼就建議你給”request_terminate_timeout”賦一個值,這個值可以根據你伺服器的效能進行設定。一般來說效能越好你可以設定越高,20分鐘-30分鐘都可以。由於我的伺服器PHP指令碼需要長時間運行,有的可能會超過10 分鐘因此我設定了900秒,這樣不會導致PHP-CGI死掉而出現502 Bad gateway這個錯誤。
而”max_children”這個值又是怎麼計算出來的呢?這個值原則上是越大越好,php-cgi的進程多了就會處理的很快,排隊的請求就會很少。設定”max_children”也需要根據伺服器的效能進行設定,一般來說一台伺服器正常情況下每一個php-cgi所耗費的記憶體在20M左右,因此我的”max_children”我設定成40個,20M*40=800M也就是說在峰值的時候所有PHP-CGI所耗記憶體在800M以內,低於我的有效記憶體1Gb。而如果我的”max_children”設定的較小,比如5-10個,那麼php-cgi就會“很累”,處理速度也很慢,等待的時間也較長。如果長時間沒有得到處理的請求就會出現504 Gateway Time-out這個錯誤,而正在處理的很累的那幾個php-cgi如果遇到了問題就會出現502 Bad gateway這個錯誤。
一個執行個體:
http://www.levil.cn/post/29/
我在CentOS下配置lnmp組合基本上用的都是同樣的設定檔,一直都沒出現過問題,可最近在一個vps上安裝同樣的環境之後,網站線上10多人就出現了開啟速度非常緩慢的情況,有好幾次都是直接達到了nginx中設定的指令碼最大逾時時間300秒,結果導致nginx往用戶端瀏覽器發送了一個504 Gateway Time-out的錯誤碼,分析了之後改動了幾處設定檔,終於避免了該情況的出現。
從錯誤碼基本可以確定跟nginx本身無關,主要是提交給php-fpm的請求未能正確反饋而導致,一般情況下,提交動態請求的時候,nginx會直接把請求轉交給php-fpm,而php-fpm再分配php-cgi進程來處理相關的請求,之後再依次返回,最後由nginx把結果反饋給用戶端瀏覽器,但我這個vps目前跑的是個純php應用內容,實際上使用者所有的請求都是php請求,有的耗費時間比較久,php-cgi進程就一直都被用滿,而php- fpm本身的設定檔只開啟了10組php-cgi進程,這樣的話線上使用者稍微多的話就會導致請求無法被正常處理而出錯。
大概分析出了原因,下面做就比較容易了,首先是更改php-fpm的幾處配置:
把max_children由之前的10改為現在的30,這樣就可以保證有充足的php-cgi進程可以被使用;
把request_terminate_timeout由之前的0s改為60s,這樣php-cgi進程處理指令碼的逾時時間就是60秒,可以防止進程都被掛起,提高利用效率。
接著再更改nginx的幾個配置項,減少FastCGI的請求次數,盡量維持buffers不變:
fastcgi_buffers由 4 64k 改為 2 256k;
fastcgi_buffer_size由 64k 改為 128K;
fastcgi_busy_buffers_size 由 128K 改為 256K;
fastcgi_temp_file_write_size 由 128K 改為 256K。
好了,重新載入php-fpm和nginx的配置,再次測試,至今兩周時間內沒有再出現504 Gateway Time-out的情況,算是達到效果了。
另一例子:
使用ie正常.其他人用FF也正常.但是有個人使用FF瀏覽報錯502
查看後台error日誌,發現一句
upstream sent too big header while reading response header from upstream
就是反饋回來的頭部資訊太大
一般應該是cookie裡面帶的
懷疑是FF裡面的某個外掛程式引起返回太多的頭部資訊
一個個排查.最後發現是FireBug導致的
既然是fastcgi返回的頭部太大.應該可以配置
尋找資料後發現應該是和fastcgi_buffer_*有關的
將相關配置增大.發現問題解決
這邊使用的是
fastcgi_buffer_size 32k;
fastcgi_buffers 8 32k;
比原來的預設4k/8k要大許多
http400錯:
nginx的HTTP400錯誤,而且這個HTTP400錯誤並不是每次都會出現的,查了一下發現nginx 400錯誤是由於request header過大,通常是由於cookie中寫入了較長的字串所引起的。解決方案是不要在cookie裡記錄過多資料,如果實在需要的話可以考慮調整在nginx.conf中的client_header_buffer_size(預設1k)
若cookie太大,可能還需要調整large_client_header_buffers(預設4k),該參數說明如下:
請求行如果超過buffer,就會報HTTP 414錯誤(URI Too Long)
nginx接受最長的HTTP頭部大小必須比其中一個buffer大,否則就會報400的HTTP錯誤(Bad Request)。
http413錯:
在上傳時nginx返回了413錯誤,查看log檔案,顯示的錯誤資訊是:”413 Request Entity Too Large”, 於是在網上找了下“nginx 413錯誤”發現需要做以下設定:
在nginx.conf增加client_max_body_size的設定, 這個值預設是1m,可以增加到8m以增加提高檔案大小限制;
如果啟動並執行是php,那麼還要檢查php.ini,這個大小client_max_body_size要和php.ini中的如下值的最大值一致或者稍大,這樣就不會因為提交資料大小不一致出現的錯誤。
post_max_size = 8M
upload_max_filesize = 2M