彻底弄懂502/503/504(php-fpm+nginx)亲测可用

参考:http://phpmianshi.com/?id=90

环境 php7.3.5 + nginx1.16.0

 

相信大家都遇到过50X的问题,网上也看了很多文章,总是各种不对,所以今天咱们详解各种出现50X的情况和原因

502:Bad Gateway  作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。

503:Service Unavailable 由于临时的服务器维护或者过载,服务器当前无法处理请求。这个状况是临时的,并且将在一段时间以后恢复。如果能够预计延迟时间,那么响应中可以包含一个 Retry-After 头用以标明这个延迟时间。如果没有给出这个 Retry-After 信息,那么客户端应当以处理500响应的方式处理它。

504:Gateway Time-out 作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应。

 

nginx+php 出现502 bad gateway,一般这都不是nginx的问题,而是由于 fastcgi或者php的问题导致的,常见的有以下几种。

1.php-fpm进程挂掉或者重启,大家可以service php-fpm stop 然后再打开php页面就返回502

nginx错误日志:

*153514 connect() to unix:/dev/shm/php-cgi.sock failed (2: No such file or directory) while connecting to upstream

所以平时我们要平滑重启 kill -USR2 pid  就不会报错了

 

2.php-fpm 平滑重启时也是有可能有502的,大家可以打开一个sleep(10) 的页面,然后service php-fpm reload  或者 kill -USR2 pid 测试

php-fpm错误日志:

/phpmianshi.com/test.php' (request: "GET /test.php") executing too slow

 

主要原因是:php-fpm.conf中process_control_timeout 设置过小造成的

process_control_timeout 参数解释

参数含义是 设置子进程接受主进程复用信号的超时时间. 控制子进程处理来自master的信号的时间,默认为0.如果正在处理请求, 很可能会收到错误报警。建议将此参数设置为相同的值 request_terminate_timeout,以便worker有时间完成处理请求, 否则将会中断。

 

3.request_terminate_timeout 设置的过小,php没有执行完就被中断,大家可以设置小一点,写一个sleep脚本测试

php-fpm错误日志:

[18-May-2020 19:37:47] WARNING: [pool www] child 7906, script '/data/wwwroot/mianshiphp/test.php' (request: "GET /test.php") executing too slow (1.295579 sec), logging
[18-May-2020 19:37:47] WARNING: [pool www] child 7906, script '/data/wwwroot/mianshiphp/test.php' (request: "GET /test.php") execution timed out (1.629247 sec), terminating
[18-May-2020 19:37:47] WARNING: [pool www] child 7906 exited on signal 15 (SIGTERM) after 72.682120 seconds from start

4.nginx fastcgi_read_timeout 设置过小,返回504

比如:设置 fastcgi_read_timeout =1 ,php脚本sleep(3)  ,则返回504

php-fpm错误日志:

[18-May-2020 20:01:47] WARNING: [pool www] child 12044, script '/data/wwwroot/mianshiphp/test.php' (request: "GET /test.php") executing too slow (1.235212 sec), logging

5.当服务器压力过大,没有更多的php-fpm处理请求时,返回504

比如设置php-fpm进程数为1,压力测试 ab -n 100 -c 20 http://phpmianshi.com/?id=90

 

有文章说,压力过大,没有足够的php-fpm处理时会返回502,我这里测试是不对的,而是部分请求返回了200,其他请求返回了504

 

说明当php-fpm不足时,是有一个等待队列存在的。已经接到请求的php-fpm会返回200,长时间得不到php-fpm处理的请求就返回了504,

 

那么这个等待队列是什么呢?分析如下:

 

其实就是php-fpm.conf 中的listen.backlog配置 ,当backlog队列满了,会出现502错误,

 

首先查看php活跃的套接字:  ss -ln |grep -E 'php|Netid'

 

Netid  State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
u_str  LISTEN     0      32768  /dev/shm/php-cgi.sock 79562794              * 0

 

关注 Recv-Q 和 Send-Q 这两个字段。

 

LISTEN 状态: Recv-Q 表示的当前等待服务端调用 accept 完成三次握手的 listen backlog 数值,也就是说,当客户端通过 connect() 去连接正在 listen() 的服务端时,这些连接会一直处于这个 queue 里面直到被服务端 accept();Send-Q 表示的则是最大的 listen backlog 数值,这就就是上面提到的 min(backlog, somaxconn) 的值。

 

 

于是修改listen.backlog = 1 ,同时开ab -n 5 -c 5 https://www.phpmianshi.com/backlog.php 测试,发现所有请求又都返回200了

 

ss -ln |grep -E 'php|Netid'

 

Netid  State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
u_str  LISTEN     3      32768  /dev/shm/php-cgi.sock 79562794              * 0

 

过一会 Recv-Q 慢慢减少到0,所有请求执行完成,说明php-fpm并没有拒绝后两次请求

 

具体原因如下:

 

当 queue 满了之后,服务器并不会按照理论所述,不再对 SYN 进行应答,返回 ETIMEDOUT。根据这篇文档的描述,服务器会随机的忽略收到的 SYN,建立起来的连接数可以无限的增加,只不过客户端会遇到延时以及超时的情况。

 

总结:适当增加max_children还是有用的,这样的话php-fpm能同时处理的请求增加,客户端的延迟等待时间也会相应的减小。

 

6.当遇到这个状态码的时候表示服务临时不可用,比如nginx配置了频率限制而client端又超过了配置的限制后就会收到503的响应。

 

其他待补充...

 

总结:

 

解决问题的最好的方式还是自己去看nginx和fastcgi的errorlog。

最后做个总结: php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉,都会出现502错误。

当nginx收到了无法理解的响应时,就返回502。当nginx超过自己配置的超时时间还没有收到请求时,就返回504错误。

 

 

 


 

 

 


 

 


 

 

编写php服务的dockerfile文档,满足如下要求: 1)基础镜像:centos:7 2)作者信息:姓名首字母 3)下载gcc gcc-c++ gd-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel openssl-devel make perl 4)将本地文件libzip-1.2.0.tar.gz解压并复制到容器中的/tmp中 5)通过以下命令对libzip进行配置编译: cd /tmp/libzip-1.2.0 && ./configure && make && make install 6)在容器中复制并解压文件php-7.3.9.tar.gz到/tmp文件夹中,然后进入到/tmp/php-7.3.9文件夹下,并通过以下命令进行编译: ./configure --prefix=/usr/local/php \ --with-config-file-path=/usr/local/php/etc \ --with-mysql --with-mysqli \ --with-openssl --with-zlib --with-curl --with-gd \ --with-jpeg-dir --with-png-dir --with-iconv \ --enable-fpm --enable-zip --enable-mbstring 6)在容器中将/usr/local/lib/libzip/include/zipconf.h文件复制到 /usr/local/include/文件加下 7)继续进行编译make -j 4 && make install 8)在容器中将/usr/local/php/etc/php-fpm.conf.default文件复制为 /usr/local/php/etc/php-fpm.conf文件 9)在容器中将文件/usr/local/php/etc/php-fpm.d/www.conf.default 复制成/usr/local/php/etc/php-fpm.d/www.conf 文件 10)在容器中修改/usr/local/php/etc/php-fpm.d/www.conf文件中的127.0.0.1为0.0.0.0 11)在容器中复制./sapi/fpm/init.d.php-fpm文件成 /etc/init.d/php-fpm文件 12)在容器中修改/etc/init.d/php-fpm权限为可执行 13)端口9000 14)在容器启动时执行命令:/etc/init.d/php-fpm start && tail -F /var/log/messages
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值