1.502 Bad Gateway 网关错误

Bab Gateway 502 网关错误,php来说造成502的原因常见的就是脚本执行超过timeout设置时间,或者timeout设置过大,导致php进程长时间不能释放,没有空闲worker进程来执行请求。

1.1 第一种情况【fpm超时】:
php-fpm的worker进程 执行php程序脚本时,超过了配置的最长执行时间,master进程将worker进程杀掉,直接返回502.
返回502后nginx对应error日志是104:Connection reset by peer
控制php执行时间的选项有两个,在php.ini中max_execution_time和php-fpm中request_terminate_timeout。其中request_terminate_timeout可以覆盖max_execution_time,所以如果不想修改全局的php.ini。只能修改php-fpm的配置就可以了。

502 demo:

php-fpm配置:
request_terminate_timeout = 10

php.ini配置:
max_execution_time = 30

编辑test.php
<?php
sleep(40);
echo 111;
?>

浏览器请求:192.168.1.10/test.php

浏览器返回:502

Request URL: http://192.168.1.10/test.php
Request Method: GET
Status Code: 502 Bad Gateway
Remote Address: 192.168.1.10:80
Referrer Policy: no-referrer-when-downgrade

nginx的error.log

[root@192 ~]# cd /usr/local/openresty/nginx/logs/
 [root@192 logs]# ls
 access.log error.log nginx.pid
 [root@192 logs]# cat error.log2020/04/06 11:48:35 [error] 4198#4198: *1 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 192.168.1.2, server: localhost, request: “GET /test.php HTTP/1.1”, upstream: “fastcgi://127.0.0.1:9000”, host: “192.168.1.10”

php-fpm错误日志:

[root@192 log]# cd /usr/local/php7.2/var/log/
 [root@192 log]# cat php-fpm.log
 [06-Apr-2020 11:48:35] WARNING: [pool www] child 4206, script ‘/usr/local/openresty/nginx/html/test.php’ (request: “GET /test.php”) execution timed out (13.127069 sec), terminating
 [06-Apr-2020 11:48:35] WARNING: [pool www] child 4206 exited on signal 15 (SIGTERM) after 16.673493 seconds from start
 [06-Apr-2020 11:48:35] NOTICE: [pool www] child 4221 started

说明:child 4206 exited on signal 15 (SIGTERM) after 16.673493 seconds from start此处worker进程长时间占用进程,所以master发送信号kill worker进程

1.2 连接已满:
连接请求数(accept之前)超出了端口所能监听的tcp最大值(backlog值),进不了fpm的部分带accept的链接队列,直接返回502,;返回502后nginx对应的error日志是Connection refused backlog 的值是半连接或全连接的总和,它的存在也有短时间缓冲解耦nginx请求与fpm处理的作用,“半连接”指收到了syn请求,3次握手尚未连接,“全连接”指的是3次握手成功,不过尚未被accept的请求,fpm里面有调节的参数,如果fpm的参数设置为-1,则默认走的是系统内存参数net.core.somaxconn设置的值,如果不设置可以在 /proc/sys/net/core/somaxconn 里查看,默认值是 128,所以在连接请求较高的业务里面要增大这个值。

502优化建议

502主要从php-fpm的配置方面考虑,根据服务器情况,适量增大php-fpm的工作进程数,适当增加php的执行时间,适当增加backlog值。
php的工作进程数也不是越大越好,这种进程模型运行时间长了占用的内存会增大,一般一个php进程占到30M左右的内存。开多少合适具体看机器和服务决定。
nginx的worker进程一般也能跑到30M的内存,综合计算一下:php的执行时间可以根据你的服务标准来设定,超过服务时间浏览器你去返回的502错误,这个按照实际的情况处理,至于backlog值,建议设置器数量为php的工作进程的1到2倍。

php-fpm的进程公式:

  • 适用于 dynamic 方式:在 N + 20% 和 M / m 之间。
    N 是 CPU 内核数量。
    M 是 PHP 能利用的内存数量。
    m 是每个 PHP 进程平均使用的内存数量。
  • 适用于static方式:M / (m * 1.2)

2.504 Gateway Time-out 网关超时

1.1 第一种情况【nginx连接超时】:
php的worker 进程池处理慢,无法尽快处理等待accept的链接队列,导3次握手后的链接队列长时间没有被accept,nginx链接等待超时;返回504后nginx对应的error日志是110:Connection timed out

1.2第二种情况【nginx超时】:
后端php-fpm执行脚本的时间太长,超过了nginx配置的超时机制,这个时候也是会报504错误的,
nginx超时时间为90秒(keepalive_timeout 90; [nginx.conf])
php-fpm的超时时间300秒 (request_terminate_timeout = 300】[php-fpm.d/www.conf])

demo: 504 Gateway Timeout

浏览器请求:192.168.1.10/test.php

浏览器返回:504

Request URL: http://192.168.1.10/test.php
Request Method: GET
Status Code: 504 Gateway Time-out
Remote Address: 192.168.1.10:80
Referrer Policy: no-referrer-when-downgrade

nginx的error.log

2020/04/06 21:54:31 [error] 2014#2014: *4 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.1.2, server: localhost, request: “GET /test.php HTTP/1.1”, upstream: “fastcgi://127.0.0.1:9000”, host: “192.168.1.10”

504优化建议

504主要从nginx的配置方考虑,根据业务情况配置好超时的各种机制。在配置过程中,比如遇到大并发或者是特殊业务场景,不合理的fd,buffer等设置也会带来5XX错误,比如说大并发连接的业务要增大系统和单个程序的fd数量,如果是上传业务员要增大buffer等,这些要视情况优化

pm = static | dynamic | ondemand 静态池、服务优先、内存优先 pm.max_children = 256 开启的最大 php 进程数 pm.max_requests = 1024 在执行了 1024 个请 求后重启 worker 进程,避免内存意外增长

web 服务的机器是 12 核 cpu 、 16G 内存, nginx 开启 12 个 worker 进程, php 开启 256 个进程, 跑起来后每个进程大概占用 30M 内存,也就是( 256+12 )* 30=8G, 这种静态池的配置大大减少了prefork 进程带来的开销.