標籤:
先看一下php-fpm的設定檔php-fpm.conf
include=/etc/php-fpm.d/*.conf;;;;;;;;;;;;;;;;;;; Global Options ;;;;;;;;;;;;;;;;;;;[global]pid = /var/run/php-fpm/php-fpm.pid;pid設定,預設在安裝目錄中的var/run/php-fpm.pid,建議開啟error_log = /data/logs/error/php-fpm.error.log;錯誤記錄檔,預設在安裝目錄中的/data/logs/error/php-fpm.error.loglog_level = error;錯誤層級. 可用層級為: alert(必須立即處理), error(錯誤情況),;warning(警告情況), notice(一般重要訊息), debug(調試資訊). 預設: notice.emergency_restart_threshold = 10emergency_restart_interval = 1m;表示在emergency_restart_interval所設值內出現SIGSEGV或者SIGBUS錯誤的php-cgi進程數如果超過;emergency_restart_threshold個,php-fpm就會優雅重啟。這兩個選項一般保持預設值。process_control_timeout = 10s;設定子進程接受主進程複用訊號的逾時時間. 可用單位: s(秒), m(分), h(小時), 或者 d(天) 預設單位: s(秒). 預設值: 0daemonize = yes;後台執行fpm,預設值為yes,如果為了調試可以改為no。在FPM中,可以使用不同的設定來運行多個進程池。 這些設定可以針對每個進程池單獨設定;listen.backlog = -1;backlog數,-1表示無限制,由作業系統決定,此行注釋掉就行 ;listen.allowed_clients = 127.0.0.1;允許訪問FastCGI進程的IP,設定any為不限制IP,如果要設定其他主機的nginx也能訪問這台FPM進程,listen處要設定成本地可被訪問的IP。;預設值是any。每個地址是用逗號分隔. 如果沒有設定或者為空白,則允許任何伺服器請求串連;;;;;;;;;;;;;;;;;;;;; Pool Definitions ;;;;;;;;;;;;;;;;;;;;;; See /etc/php-fpm.d/*.conf
看一下具體pool的設定檔
; Start a new pool named ‘www‘[www]listen = /dev/shm/php-fpm.socket;listen = 127.0.0.1:9000;php-fpm 監聽連接埠,即nginx中php處理的地址,一般預設值即可;可用格式為: ‘ip:port‘, ‘port‘, ‘/dev/shm/php-fpm.socket‘,每個進程池都需要設定;此處是放在記憶體中,更高效listen.owner = wwwlisten.group = webgrplisten.mode = 0666;unix socket設定選項,如果使用tcp方式訪問,這裡注釋即可user = wwwgroup = webgrp;啟動進程的帳戶和組pm = static;對於專用伺服器,pm可以設定為static;選項有static和dynamic;如果選擇static,則由pm.max_children指定固定的子進程數;如果選擇dynamic,則由其餘三個參數決定pm.max_children = 16;子進程最大數pm.start_servers = 8;啟動時的進程數pm.min_spare_servers = 5;保證空閑進程數最小值,如果空閑進程小於此值,則建立新的子進程pm.max_spare_servers = 25;保證空閑進程數最大值,如果空閑進程大於此值,此進行清理pm.max_requests = 10240;設定每個子進程重生之前服務的請求數. 對於可能存在記憶體流失的第三方模組來說是非常有用的;如果設定為 0 則一直接受請求. 等同於 PHP_FCGI_MAX_REQUESTS 環境變數. 預設值: 0;pm.status_path = /status;php-fpm狀態頁面的網址. 如果沒有設定, 則無法訪問狀態頁面. 預設值: none. munin監控會使用到;ping.path = /ping;php-fpm監控頁面的ping網址. 如果沒有設定, 則無法訪問ping頁面, 該頁面用於外部檢測php-fpm是否存活並且可以響應請求,請注意必須以斜線開頭 (/)。;ping.response = pong;用於定義ping請求的返回相應, 返回為 HTTP 200 的 text/plain 格式文本. 預設值: pongrequest_terminate_timeout = 600s;設定單個請求的逾時中止時,. 該選項可能會對php.ini設定中的‘max_execution_time‘因為某些特殊原因沒有中止啟動並執行指令碼有用;設定為0表示 Off,當經常出現502錯誤時可以嘗試更改此選項request_slowlog_timeout = 5s;當一個請求該設定的逾時時間後,就會將對應的PHP呼叫堆疊資訊完整寫入到慢日誌中. 設定為 0 表示 Offslowlog = /data/logs/error/www-slow.log;慢請求的記錄日誌,配合request_slowlog_timeout使用rlimit_files = 65535 ;設定檔案開啟描述符的rlimit限制. 預設值: 系統定義值預設可開啟控制代碼是1024,可使用 ulimit -n查看,ulimit -n 2048修改rlimit_core = 0;設定核心rlimit最大限制值. 可用值: ‘unlimited‘ 、0或者正整數. 預設值: 系統定義值.catch_workers_output = yes;重新導向運行過程中的stdout和stderr到主要的錯誤記錄檔檔案中. 如果沒有設定, stdout 和 stderr 將會根據FastCGI的規則被重新導向到 /dev/null . 預設值: 空.;security.limit_extensions = .php .php3 .php4 .php5;env[HOSTNAME] = $HOSTNAME;env[PATH] = /usr/local/bin:/usr/bin:/bin;env[TMP] = /tmp;env[TMPDIR] = /tmp;env[TEMP] = /tmp;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f [email protected];php_flag[display_errors] = onphp_admin_value[error_log] = /var/log/php-fpm/www-error.logphp_admin_flag[log_errors] = on;php_admin_value[memory_limit] = 32M
那麼我們看一下502錯誤的罪魁禍首
1、request_terminate_timeout引起的資源問題
request_terminate_timeout的值如果設定為0或者過長的時間,可能會引起file_get_contents,fsockopen的資源問題
如果file_get_contents請求的遠端資源如果反應過慢,file_get_contents就會一直卡在那裡不會逾時
我們知道php.ini 裡面max_execution_time 可以設定 PHP 指令碼的最大執行時間,但是,在php-cgi(php-fpm) 中,該參數不會起效。真正能夠控制 PHP 指令碼最大執行時間的是 php-fpm.conf 設定檔中的request_terminate_timeout參數。 nginx > php-fpm > php 優先順序
request_terminate_timeout 預設值為 0 秒,也就是說,PHP 指令碼會一直執行下去。這樣,當所有的 php-fpm 進程都卡在 file_get_contents() 函數時,這台 Nginx+PHP 的 WebServer 已經無法再處理新的 PHP 請求了,Nginx 將給使用者返回“502 Bad Gateway”。修改該參數,設定一個 PHP 指令碼最大執行時間是必要的,但是,治標不治本。例如改成 30s,如果發生 file_get_contents() 擷取網頁內容較慢的情況,這就意味著 150 個 php-cgi 進程,每秒鐘只能處理 5 個請求,WebServer 同樣很難避免”502 Bad Gateway”。解決辦法是request_terminate_timeout設定為10s或者一個合理的值,或者給file_get_contents加一個逾時參數
2、max_requests參數配置不當,可能會引起間歇性502錯誤
設定每個子進程重生之前服務的請求數. 對於可能存在記憶體流失的第三方模組來說是非常有用的.
如果設定為 ‘0’ 則一直接受請求. 等同於 PHP_FCGI_MAX_REQUESTS 環境變數. 預設值: 0,這段配置的意思是,當一個 PHP-CGI 進程處理的請求數累積到 一定數量個後,自動重啟該進程
但是為什麼要重啟進程呢?
一般在項目中,我們多多少少都會用到一些 PHP 的第三方庫,這些第三方庫經常存在記憶體流失問題,如果不定期重啟 PHP-CGI 進程,勢必造成記憶體使用量量不斷增長。因此 PHP-FPM 作為 PHP-CGI 的管理器,提供了這麼一項監控功能,對請求達到指定次數的 PHP-CGI 進程進行重啟,保證記憶體使用量量不增長
正是因為這個機制,在高並發的網站中,經常導致 502 錯誤,我猜測原因是 PHP-FPM 對從 NGINX 過來的請求隊列沒處理好
目的解決方案是,把這個值盡量設定大些,儘可能減少 PHP-CGI 重新 SPAWN 的次數,同時也能提高總體效能。在我們自己實際的生產環境中發現,記憶體流失並不明顯,因此我們將這個值設定得非常大(204800)。大家要根據自己的實際情況設定這個值,不能盲目地加大
這套機制目的只為保證 PHP-CGI 不過分地佔用記憶體,為何不通過檢測記憶體的方式來處理呢?通過設定進程的峰值內在佔用量來重啟 PHP-fpm進程,會是更好的一個解決方案
3、引起的錯誤
NOTICE] child 19214 stopped for tracing [NOTICE] about to trace 19214 [ERROR] ptrace(PEEKDATA) failed: Input/output error (5) [NOTICE] finished trace of 19214 [WARNING] [pool www] child 19208, script ‘blahblah.php‘ executing too slow (30.041419 sec), logging [NOTICE] child 19208 stopped for tracing [NOTICE] about to trace 19208 [ERROR] ptrace(PEEKDATA) failed: Input/output error (5) [NOTICE] finished trace of 19208 [WARNING] [pool www] child 19218, script ‘blahblah.php‘ executing too slow (30.035029 sec), logging
解決方案
It appears you have request_slowlog_timeout enabled. This normally takes any request longer than N seconds, logs that it was taking a long time, then logs a stack trace of the script so you can see what it was doing that was taking so long.In your case, the stack trace (to determine what the script is doing) is failing. If you‘re running out of processes, it is because either:After php-fpm stops the process to trace it, the process fails to resume because of the error tracing itThe process is resuming but continues to run forever.My first guess would be to disable request_slowlog_timeout. Since it‘s not working right, it may be doing more harm than good. If this doesn‘t fix the issue of running out of processes, then set the php.ini max_execution_time to something that will kill the script for sure
4、如果報504錯誤
fastcgi_connect_timeout 180;fastcgi_read_timeout 600;fastcgi_send_timeout 600;
參見文章如下
http://www.cnblogs.com/argb/p/3604340.html
http://yangjunwei.com/a/725.html
http://www.pooy.net/nginx-open-php-fpm-error-log.html
http://serverfault.com/questions/406532/i-o-error-with-php5-fpm-ptracepeekdata-failed
http://ju.outofmemory.cn/entry/102988
nginx中的502錯誤