nginx 502 bad gateway
總結
一般是php問題居多,也需要調整相應的nginx參數,最后也可能是mysql假死
nginx問題
查看日志中的報錯error.log
一般設置路徑/usr/local/nginx/logs/nginx_error.log
nginx等待時間超時
Nginx代理過程,將業務服務器請求數據緩存到本地文件,再將文件數據轉發給請求客戶端。高並發的客戶端請求,必然要求服務器文件句柄的並發打開限制。
使用ulimit命令(ulimit -n),查看Linux系統文件句柄並發限制,默認是1024,我們可以改為65535(2 的 16 次方,這是系統端口的極限)。
修改的方法為:修改系統文件/etc/security/limits.conf,添加如下信息,並重新啟動系統生效。
修改nginx.conf配置參數
部分PHP程序的執行時間超過了Nginx的等待時間,可以適當增加nginx.conf配置文件中FastCGI的timeout時間,例如:
http { fastcgi_connect_timeout 300; # 鏈接 fastcgi_send_timeout 300; # 讀取 fastcgi_read_timeout 300; # 發請求 ...... }
fastcgi_read_timeout是指fastcgi進程向nginx進程發送response的整個過程的超時時間
fastcgi_send_timeout是指nginx進程向fastcgi進程發送request的整個過程的超時時間
這兩個選項默認都是秒(s),可以手動指定為分鍾(m),小時(h)等
php問題
一般是/usr/local/php/etc/php-fpm.conf三個參數(最主要的問題)
pm.max_children pm.max_requests request_terminate_timeout
php-cgi進程數不夠用、php執行時間長、或者是php-cgi進程死掉,都會出現502錯誤。
具體根據php-fpm.conf中error.log跟slow.log兩個日志來判斷
/usr/local/php/var/log/php-fpm.log /usr/local/php/var/log/php-fpm-slowlog.log
1.php進程池pm.max_children參數
netstat -anp | grep php | grep CONNECTED
ps aux | grep php-fpm 觀察fastcgi/php-fpm進程數,假如使用的進程數等於或高於5個,說明需要增加
vim /usr/local/php/etc/php-fpm.conf pm.max_children = 50
max_children是PHP-FPM Pool 最大的子進程數,他數值取決於你的服務器內存。
假設你打算給10G內存給當前配置的PHP-FPM Pool,一般一個PHP請求占用內存20M-30M,我們按站點每個PHP請求占用內存25M,這樣max_children = 10G/25M = 409。所以,這個值可以根據情況算出來
每個PHP請求占用內存可以在測試你的php程序時通過memory_get_peak_usage(true)這個函數獲得內存峰值,以此作為單個請求的程序內存消耗消耗量,並考慮進php-fpm本身的基礎內存消耗,可以得到一個近似的單進程內存消耗量。
- 只要在峰值的時候所有PHP pool所耗內存低於我的有效內存80%算是合理的
pm.max_spare_servers這個參數值要小於pm.max_children的值,不然會啟動php-fpm失敗
2.pm.max_requests參數
我們知道這個參數的含義是php-fpm工作進程處理完多少請求后自動重啟,主要目的就是為了控制請求處理過程中的內存溢出,使得內存占用在一個可接受的范圍內。
max_requests = N 是指當每個children接受了N次請求以后,就會把自己殺死,然后重新建立一個children。
比如上面的值是1000,而你定義的是10240,那么fpm要超過10天才能殺死children並重建,這樣如果存在內存泄露的話,就會導致進程占用過多的內存而無法釋放,從而使fpm的處理能力降低,還會產生一些莫名其妙的錯誤。
但是如果你把這個值設置的過小,fpm頻繁的殺死children並重建,也會導致額外的開銷。
- 這個參數依情況而定吧,具體沒有實驗測試過
3.request_terminate_timeout參數
max_requests是每個子進程重生之前處理的請求數, 默認值為unlimited(默認為1024),可以設置小一點(如500左右),這樣可以避免內存泄露帶來的問題
或者在/usr/local/php/etc/php.ini下的max_execution_time參數修改,百度這兩個值貌似沒有什么區別,最好的就是兩個都設置一下
request_terminate_timeout = 0s #表示關閉,即無限執行下去。
4.php權限問題
php-fpm.conf中定義屬主,屬組
listen.owner = nobody //定義屬主
listen.group = nobody //定義屬組
這里的nobody只的是nginx的用戶
5.php內存不足
php.ini中memory_limit設低了會出錯,修改了php.ini的memory_limit為64M,重啟nginx,發現好了,原來是PHP的內存不足了。
mysql假死
根據mysql日志排查,這種情況不多,但要注意,暫時沒有遇到過
一般引起mysql假死的原因有兩種:
- mysql假死了,你也請求不到后端的
- mysql慢查詢也會引起
mysql 的cpu占用率高,導致后台差不到數據也要注意
或者
Nginx 502 Bad Gateway的含義是請求的PHP-CGI已經執行,但是由於某種原因(一般是讀取資源的問題)沒有執行完畢而導致PHP-CGI進程終止,一般來說Nginx 502 Bad Gateway和php-fpm.conf的設置有關。
常見的原因可能是php-cgi進程數不夠用、php執行時間長(mysql慢)、或者是php-cgi進程死掉,都會出現502錯誤。
1. 在安裝好的環境中,運行一段時間出現502問題,一般是因為默認php-cgi進程是5個,可能因為phpcgi進程不夠用而造成502,需要修改/usr/local/php/etc/php-fpm.conf 將其中的max_children值適當增加。
2. php執行超時,修改/usr/local/php/etc/php.ini 將max_execution_time 改為300
3. 磁盤空間不足,可以使用 # df -h命令查看磁盤使用量
4. php-cgi進程死掉了。
通常的排查方法如下:
1、查看php fastcgi的進程數(max_children值)
# netstat -anop | grep php-cgi | wc -l
# netstat -anpo | grep php-fpm | wc -l
假如顯示是5
2、查看當前進程
# ps aux | grep php-fpm 觀察fastcgi/php-fpm進程數,假如使用的進程數等於或高於5個,說明需要增加。
3、調整/usr/local/php/etc/php-fpm.conf 的相關設置
pm.max_children = 5
request_terminate_timeout = 60
max_children最多5個進程,按照每個進程20MB內存,最多100MB。也就是1分鍾。max_children增多,則php-cgi的進程多了就會處理的很快,排隊的請求就會很少。 但是設置max_children也需要根據服務器的性能進行設定,一般來說一台服務器正常情況下每一個php-cgi所耗費的內存在20M左右。根據自己服務器購買的內存來實際決定。
request_terminate_timeout執行的時間為60秒,request_terminate_timeout值可以根據服務器的性能進行設定。一般來說性能越好你可以設置越高,20分鍾-30分鍾都可以。
4. 部分PHP程序的執行時間超過了Nginx的等待時間,可以適當增加nginx.conf配置文件中FastCGI的timeout時間,例如:
http
{
......
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
......
}
參考資料