遇到這種狀況,首先看一下慢日誌php
[17-Aug-2015 13:13:43] WARNING: [pool www] child 27780, script '/data/s.com/index.php' (request: "GET /index.php") executing too slow (5.226952 sec), logging [17-Aug-2015 13:13:43] NOTICE: child 27780 stopped for tracing [17-Aug-2015 13:13:43] NOTICE: about to trace 27780 [17-Aug-2015 13:13:43] ERROR: failed to ptrace(PEEKDATA) pid 27780: Input/output error (5) [17-Aug-2015 13:13:43] NOTICE: finished trace of 27780 [17-Aug-2015 13:14:16] WARNING: [pool www] child 28262, script '/data/s.com/index.php' (request: "GET /index.php/Admin/Login") executing too slow (5.205117 sec), logging [17-Aug-2015 13:14:16] NOTICE: child 28262 stopped for tracing [17-Aug-2015 13:14:16] NOTICE: about to trace 28262 [17-Aug-2015 13:14:16] ERROR: failed to ptrace(PEEKDATA) pid 28262: Input/output error (5) [17-Aug-2015 13:14:16] NOTICE: finished trace of 28262 [17-Aug-2015 13:15:16] WARNING: [pool www] child 27802, script '/data/s.com/ss/connect.php' (request: "GET /ss/connect.php") executing too slow (5.579121 sec), logging [17-Aug-2015 13:15:16] NOTICE: child 27802 stopped for tracing [17-Aug-2015 13:15:16] NOTICE: about to trace 27802 [17-Aug-2015 13:15:16] ERROR: failed to ptrace(PEEKDATA) pid 27802: Input/output error (5) [17-Aug-2015 13:15:16] NOTICE: finished trace of 27802 [17-Aug-2015 13:16:11] WARNING: [pool www] child 27803, script '/data/s.com/ss/url_api.inc.php' (request: "POST /ss/url_api.inc.php") executing too slow (5.130357 sec), logging [17-Aug-2015 13:16:11] NOTICE: child 27803 stopped for tracing [17-Aug-2015 13:16:11] NOTICE: about to trace 27803 [17-Aug-2015 13:16:11] NOTICE: finished trace of 27803
究竟爲什麼會有這麼多錯誤,部分PHP程序的執行時間超過了Nginx的等待時間html
那麼咱們先看一下php-fpm的配置文件php-fpm.confnginx
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.log log_level = error ;錯誤級別. 可用級別爲: alert(必須當即處理), error(錯誤狀況), ;warning(警告狀況), notice(通常重要信息), debug(調試信息). 默認: notice. emergency_restart_threshold = 10 emergency_restart_interval = 1m ;表示在emergency_restart_interval所設值內出現SIGSEGV或者SIGBUS錯誤的php-cgi進程數若是超過 ;emergency_restart_threshold個,php-fpm就會優雅重啓。這兩個選項通常保持默認值。 process_control_timeout = 10s ;設置子進程接受主進程複用信號的超時時間. 可用單位: s(秒), m(分), h(小時), 或者 d(天) 默認單位: s(秒). 默認值: 0 daemonize = 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的配置文件web
; 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 = www listen.group = webgrp listen.mode = 0666 ;unix socket設置選項,若是使用tcp方式訪問,這裏註釋便可 user = www group = 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 格式文本. 默認值: pong request_terminate_timeout = 600s ;設置單個請求的超時停止時,. 該選項可能會對php.ini設置中的'max_execution_time'由於某些特殊緣由沒有停止運行的腳本有用 ;設置爲0表示 Off,當常常出現502錯誤時能夠嘗試更改此選項 request_slowlog_timeout = 5s ;當一個請求該設置的超時時間後,就會將對應的PHP調用堆棧信息完整寫入到慢日誌中. 設置爲 0 表示 Off slowlog = /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 www@my.domain.com ;php_flag[display_errors] = on php_admin_value[error_log] = /var/log/php-fpm/www-error.log php_admin_flag[log_errors] = on ;php_admin_value[memory_limit] = 32M
那麼咱們看一下502錯誤的罪魁禍首api
一、php執行時間長,致使進程不夠用服務器
1)、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參數app
參數優先級 nginx > php-fpm > php
dom
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-fpm 進程,每秒鐘只能處理 5 個請求,WebServer 一樣很難避免」502 Bad Gateway」。socket
解決辦法是增大php-fpm數量,增大request_terminate_timeout,設置爲300s或者一個合理的值,或者給file_get_contents加一個超時參數
二、php-fpm進程死掉,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進程,會是更好的一個解決方案
三、引發的錯誤
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 it The 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
四、504錯誤,能夠進行以下修改
fastcgi_connect_timeout 180; fastcgi_read_timeout 600; fastcgi_send_timeout 600;
五、總結參數能夠以下設置
#php.ini max_execution_time = 300 #php-fpm.conf request_terminate_timeout = 300 #nginx location ~ \.php$ { include /etc/nginx/fastcgi_params; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_read_timeout 300; }
能夠調整以上參數爲500
php-fpm 進程數不夠用、php執行時間長、或者是php-fpm進程死掉,都會出現502錯誤
參見文章以下
http://www.cnblogs.com/argb/p/3604340.htmlhttp://yangjunwei.com/a/725.htmlhttp://www.pooy.net/nginx-open-php-fpm-error-log.htmlhttp://serverfault.com/questions/406532/i-o-error-with-php5-fpm-ptracepeekdata-failedhttp://ju.outofmemory.cn/entry/102988