莫斯科保卫战之PHP-502 Bad Gateway

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了莫斯科保卫战之PHP-502 Bad Gateway相关的知识,希望对你有一定的参考价值。

前言


其实这个小报错是之前的小故障但是也可以引发血案,所以我采取了修改php-fpm.conf 配置 nginx.conf的配置也相应设置好了所以今天介绍一下php的报错。因上大学闲暇的时候喜欢军事研究、所以本节故障为名莫斯科保卫战!


报错如下:

技术分享


php-fpm5.4内容详解

现在都用php-fpm5.6 7.0 这篇5.4的php-fpm也算是之前的总结吧!


PHP5.4安装完毕后,FPM的默认配置文件于


 /usr/local/php/etc/php-fpm.conf


vim /usr/local/php/etc/php-fpm.conf


技术分享


php-fpm.conf配置详解pm = dynamic 如何控制子进程,选项有static和dynamic,默认采用dynamic;如果选择static,则由pm.max_children指定固定的子进程数。

如果选择dynamic,则由以下参数决定:
pm.max_children ,子进程最大数
pm.start_servers ,启动时的进程数
pm.min_spare_servers ,保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程
pm.max_spare_servers ,保证空闲进程数最大值,如果空闲进程大于此值,此进行清理

对于专用服务器,pm可以设置为static。 pm.max_requests 设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 ’0′ 则一直接受请求. 设置为500就可以了(默认0)。

将值修改为如下:pm.max_children = 32 pm.start_servers = 16 pm.min_spare_servers = 8 pm.max_spare_servers = 32 pm.max_requests = 500 之后php-fpm -t  或者 sbin目录下 出现如下:NOTICE: configuration file /usr/local/php/etc/php-fpm.conf test is successful 表示正确。

测试配置文件是否正常,没问题,杀掉当前的FPM进程/usr/local/php/sbin/php-fpm 或者 systemctl restart php-fpm 启动

有时候,运行 Nginx、PHP-CGI(php-fpm) Web服务的 Linux 服务器,突然系统负载上升,使用 top 命令查看,很多 php-cgi 进程 CPU 使用率接近100%。后来,我通过跟踪发现,这类情况的出现,跟 PHP 的 file_get_contents() 函数有着密切的关系。

  

大、中型网站中,基于 HTTP 协议的 API 接口调用,是家常便饭。PHP 程序员们喜欢使用简单便捷的 file_get_contents("http://example.com/") 函数,来获取一个 URL 的返回内容,但是,如果 http://example.com/ 这个网站响应缓慢,file_get_contents() 就会一直卡在那儿,不会超时。

  

我们知道,在 php.ini 中,有一个参数 max_execution_time 可以设置 PHP 脚本的最大执行时间,但是,在 php-cgi(php-fpm) 中,该参数不会起效。真正能够控制 PHP 脚本最大执行时间的是 php-fpm.conf 配置文件中的以下参数:

<value name="request_terminate_timeout">0s</value>


注意!新版的 php-fpm 中配置文件中格式是:

request_terminate_timeout=0s


默认值为 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”。

  

要做到彻底解决,只能让 PHP 程序员们改掉直接使用 file_get_contents("http://example.com/") 的习惯,而是稍微修改一下,加个超时时间,用以下方式来实现 HTTP GET 请求。要是觉得麻烦,可以自行将以下代码封装成一个函数。

 

当然,导致 php-cgi 进程 CPU 100% 的原因不只有这一种,那么,怎么确定是 file_get_contents() 函数导致的呢?

首先, 开启 PHP <value name="request_slowlog_timeout">3s</value> 记录慢执行日志

新版 php-fpm 想来想去文件中格式是:

slowlog=/tmp/slow.log

request_slowlog_timeout=3s


日志中打印出执行慢的代码行数。

  

首先,使用 top 命令查看 CPU 使用率较高的 php-cgi 进程。

找其中一个 CPU 100% 的 php-cgi 进程的 PID,用以下命令跟踪一下:

strace -p 10747

  

如果屏幕显示:

技术分享


php-cgi(php-fpm) 使用了Libevent,而Libevent 在 Linux 2.6 内核以上默认会使用 epoll I/O 模型处理 FastCGI 网络请求,而非 select/poll。在慢日志记录的代码行数中,包含 file_get_contents 以及其他函数,而 file_get_contents 等作为 Client 发起 HTTP 请求的函数使用的是 select/poll 模型,也就是说,只有 file_get_contents 等满足“TCP请求默认不超时、使用select/poll 模型、进程CPU 100%”的网络操作函数,会导致 strace -p 看到的这种情况。


总结:上不厌高,海不厌深

本文出自 “李世龙” 博客,谢绝转载!

以上是关于莫斯科保卫战之PHP-502 Bad Gateway的主要内容,如果未能解决你的问题,请参考以下文章

第二次世界大战Second World War游戏攻略 操作步骤如下

php502故障处理

PHP-FPM 和 Nginx:502 错误网关

nginx+php,502错误

八疾病冬季易高发

Nginx+php-fpm 502 504问题