首先得了解502错误的定义(http://www.checkupdown.com/status/E502_zh.html)以及主要是考虑是不是代理(访问的上游)出了问题


查询php-fpm的日志可以发现有php运行超时的记录

spacer.gifwKiom1iasAiQe8kRAABISOCsWWU679.png-wh_50

...

[pool www] child 27343, script '/usr/local/tengine/html/index.php' (request: "POST /index.php") executing too slow (3.196879 sec), logging

......


想到的是哪些参数会决定了php执行的超时时间:


以下摘自章小鱼儿_linux博客的一些内容(http://zhangxylinux.blog.51cto.com/5041623/1543035)


PHP自身配置:

  1. 在php.ini里max_execution_time可以设置php脚本的最大执行时间,但是在php-cgi(php-fpm)中,该参数不生效,真正能控制php最大执行时间的是request_terminate_timeout,就是说如果是使用 mod_php5.so 的模式运行 max_execution_time 是会生效的,但是如果是php-fpm模式中运行时不生效的。参数优先级 nginx >  php-fpm > php 

  2. max_execution_time

  3. 计算的只是PHP脚本本身执行的时间,执行之外的时间都不会计算在内。哪些属于执行之外的时间呢?包含sleep、数据交互、socket交互等等。 

  4. request_terminate_timeout = 0  即为不受时间控制,永不超时


3.request_terminate_timeout引起的资源问题

  1. request_terminate_timeout的值如果设置为0或者过长的时间,可能会引起file_get_contents的资源问题。

  2. 如果file_get_contents请求的远程资源如果反应过慢,file_get_contents就会一直卡在那里不会超时。request_terminate_timeout默认值为 0 秒,也就是说,PHP 脚本会一直执行下去。这样,当所有的 php-cgi 进程都卡在 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加一个超时参数

如果常有请求超时,请打开php-fpm的慢日志,通过日志来确认评估超时时间

4.

  1. Ngnix中的fastcgi 请求时间控制

  2. fastcgi_connect_timeout

  3. 语法:fastcgi_connect_timeout time 

  4. 默认值:fastcgi_connect_timeout 60 

  5. 使用字段:http, server, location 

  6. 指定同FastCGI服务器的连接超时时间,这个值不能超过75秒。


  7. fastcgi_read_timeout

  8. 语法:fastcgi_read_timeout time 

  9. 默认值:fastcgi_read_timeout 60 

  10. 使用字段:http, server, location 

  11. 前端FastCGI服务器的响应超时时间,如果有一些直到它们运行完才有输出的长时间运行的FastCGI进程,或者在错误日志中出现前端服务器响应超时错误,可能需要调整这个值。


  12. fastcgi_send_timeout

  13. 语法:fastcgi_send_timeout time 

  14. 默认值:fastcgi_send_timeout 60 

  15. 使用字段:http, server, location 

  16. 指令为上游服务器设置等待一个FastCGI进程的传送数据时间,如果有一些直到它们运行完才有输出的长时间运行的FastCGI进程,那么可以修改这个值,如果你在上有服务器的error log里面发现一些超时错误,那么可以恰当的增加这个值。

  17. 指令指定请求服务器的超时时间,指完成了2次握手的连接,而不是完整的连接,如果在这期间客户端没有进行数据传递,那么服务器将关闭这个连接。


  1. 在nginx+FastCGI 配置测试中

  2. 其中在request_terminate_timeout设置为永不超时的情况下,nginx中fastcgi_read_timeout 的设置时间将影响到最终的超时时间。

  3. 测试中,如果是php-fpm中的超时

  4. 将显示 502 Bad Gateway

  5. 如果是nginx中cgi配置超时

  6. 将显示 504 Gateway Time-out



但是经过分析服务器上没有出现所有 php-cgi 进程都卡在 file_get_contents()上

继续查看日志发现以下内容:

 WARNING: [pool www] child 407 exited on signal 11 (SIGSEGV) after 3409158.647209 seconds from start

wKioL1ias4LR0bneAABx-2uRJo0598.jpg-wh_50

查询系统日志也能发现类似问题

php-fpm[407]: segfault at c5a1 ip 00000000007cd1cc sp 00007fff74640bc0 error 4 in php-fpm[400000+949000]

wKiom1iatUTDnF9fAAEeGs2AGgQ970.png-wh_50

发现进程遇到段错误异常退出了,但是系统并没有开启core文件,暂时不能定位了

如何发现段错误:

查看限制情况:

wKiom1iatfaw3tL-AAA7MbK14-s668.jpg-wh_50

系统对于core文件大小默认限制是0.也就是说不能生成core文件。可以通过以下命令设置大小。

执行ulimit -c unlimited

就去除了系统对core文件大小的限制,接下来我们就可以根据产生的core文件去定位问题了


利用GDB调试php core dump

应用程序因异常或bug异常退出在一定条件下会产生core文件


开启core

设置core路径

echo "/tmp/core.%p" > /proc/sys/kernel/core_pattern


修改unlimit(略)


重启php-fpm


查看core文件

gdb /usr/local/php/sbin/php-fpm -c core_file_path

.....

//查看调用栈

(gdb)bt

....


还可以利用php提供的.gdbinit(gdb命令编写脚本)帮我们查看php函数层的调用

(gdb)source /usr/local/src/autoinst.nmp_nosql_node_php54/php-5.4.30/.gdbinit

(gdb)zbacktrace


参考链接:

http://zhangxylinux.blog.51cto.com/5041623/1543035

https://yq.aliyun.com/articles/27468

http://www.vckai.com/p/38