php程序出现 502 bad gateway 的分析流程
标签(空格分隔): php 502 http
最近在开发一个基于php的充值后台, 一个很简单的充值回调接口尽然有时候会出现502的错误. 奇怪的是在本地都测试相当正常, 部署到服务器之后就会出现502错误.
分析步骤:
1. 怀疑配置环境出错
由于本地的环境是Windows+Apache+php, 服务器是centos+nginx+php-fpm, 首先想到的是服务器环境配置出错. 百度上搜索php 502
出现一大堆关于php与nginx配置错误导致的文章,比如: http://www.nginx.cn/102.html http://www.cnblogs.com/jackluo/p/3366612.html
于是, 各种php, nginx, php-fpm, linux 各种配置文件一个一个改, 一次一次重试. 然而这并没有什么用...
2. 观察 php, nginx 日志
观察 php, nginx 日志, 这一步应该是出现问题首先应该做的事, 这也是坑踩多了学到的经验. nginx的日志: /usr/local/nginx/logs/error.log php-fpm的日志: /usr/local/php5.6/var/log/php-fpm.log
不同的环境可能位置稍有区别
从日志中发现了更劲爆的错误:
2015/07/15 09:24:04 [error] 10853#0: *6453 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 219.136.34.244, server: 203.20.249.124, request: "POST /api.php/pay/uc/callback HTTP/1.1", upstream: "fastcgi://127.0.0.1:7777", host: "203.20.249.124:81"
这是nginx的错误日志, 意思是没有收到php-fpm的回复
[15-Jul-2015 18:33:01.523959] WARNING: pid 10421, fpm_request_check_timed_out(), line 281: [pool www] child 10485, script '/aries/paycenter/api.php' (request: "POST /api.php") execution timed out (34.603607 sec), terminating
[15-Jul-2015 18:33:01.524747] DEBUG: pid 10421, fpm_got_signal(), line 76: received SIGCHLD
[15-Jul-2015 18:33:01.524805] WARNING: pid 10421, fpm_children_bury(), line 252: [pool www] child 10485 exited on signal 15 (SIGTERM) after 26873.226867 seconds from start
[15-Jul-2015 18:33:01.525768] NOTICE: pid 10421, fpm_children_make(), line 421: [pool www] child 21761 started
[15-Jul-2015 18:33:01.525804] DEBUG: pid 10421, fpm_event_loop(), line 419: event module triggered 1 events
这是php-fpm的日志, 意思是php进程退出
oh my god, php进程都宕了!!! 一个简单的请求竟然导致php进程宕了.
会不会是php-fpm和nginx之间通讯不畅导致php进程宕掉? 于是, 将通信方式由 ip:port 方式改为 socket 方式. 然而这并没有什么用...
都快崩溃了, 难道是php的bug? 出现php进程退出这种错误, 应该是很严重的问题吧, 也都不给个提示. 实在是太不人性化了/(ㄒoㄒ)/~~
3. 逐行调试
这是最后的选择了, 虽然不是很复杂, 很是也有几百行的, 逐行逐字的注释调试确实是个体力活!
4. 结论
最后发现是 $responContent = curl_exec($ch);
这个函数执行的时候导致的. curl_exec
这个自带的函数毫无征兆地就把php进程搞宕掉了...
解决方法是在这行之前加上一行(超时设置): curl_setopt($ch, CURLOPT_TIMEOUT, 10);
以后学乖点, 每次请求时都加个超时时间设置, 这也是血泪教训吧...
总结
php程序出现 502 bad gateway
时, 不要急, 不要慌, 这时越要冷静. 按照下面这个步骤来排查:
- 检查程序中的请求(http, tcp)有没有加超时设置
- 创建目录时, 有没有执行权限(这个也是踩过的坑, 也会导致php进程退出. 最好调用创建目录函数时先判断权限)
- 检查php, nginx的配置(这一步工作量最大, 需要的综合知识最多, 也最容易让人烦躁, 放在最后)