1概述

LNMP架构下 发生502 bad gateway  一般有两种情况

1,没有可用的php-fpm 没有可用的worker进程

2,脚本执行时间超过了 php-fpm request_terminate_timeout 设置的值 这时 worker进程会被kill 或者  request_terminate_timeout 设置的值过大 导致整个worker进程长时间工作不能释放 没有空闲的进程来处理请求从而报502

我们知道控制php脚本执行时间 有两个值 一个是php.ini 的 max_execution_time 和php-fpm 的request_terminate_timeout

我们可以分析下 超过最大请求时间报502错误的原因

 

2环境

为了测试的方便 可以将nginx 设置一个进程 php-fpm 设置 pm = static 模式  pm.max_children=1  request_terminate_timeout = 3

请求本地localhost/index.php  文件类容为sleep(20);

浏览器执行ocalhost/index.php 

lnmp 502错误分析

3分析

3.1先查看nginx 和 fpm错误日志

lnmp 502错误分析lnmp 502错误分析

fpm错误日志

lnmp 502错误分析

1,脚本执行超时

2,子进程收到SIGTERM信号退出了

3,开启了一个新的进程

可以看出 脚本执行超时 worker进程就会退出  ngixn 的报错 connection reset by peer 是因为这个worker进程退出导致的 tcp连接中一方断掉的话 会给对方发RST

lnmp 502错误分析

3.2使用strace -p 来追踪进程

strace -p 11032  追踪 ngixn worker进程 如下图

lnmp 502错误分析

3.2.1,epoll_wait(9...) = 1  表示有一个文件描述符有事件发生 此处为可读

3.2.2,accept4(6,....)=3 表示 accept接受请求 浏览器端口37226 IP 127.0.0.1 该socket fd=3

3.2.3,epoll_ctl(9,EPOLL_CTL_ADD,3,....) 将文件描述符3 加入到事件监听机制里面

3.2.4,recvfrom(3,.......) 表示 读取 从发生可读事件的socket描述符3 中读取内容  http协议

3.2.5,stat() 判断客户端请求的文件是否存在 存在返回0

至此 nginx 和客户端交互到一段落 接下来就是nginx和fpm的通信

3.2.6,socket(_)创建一个socket  fd=11

3.2.7,connect(11,,9000,127.0.0.1,,) 请求的是127.0.0.1 port为9000   nginx 和php-fpm是用tcp socket 方式 

3.2.8,writev(11,........808)=808  向fd11中发送数据 大小为808字节

3.2.9,recvfrom(11,.....) = -1 ECONNRESET (Connection reset by peer) 从 fd11 读到ECONNRESET (Connection reset by peer)

3.2.10,writev(5,'''''')=249  向fd5中写入错误信息,fd5就是nginx错误日志的文件描述符。

3.2.11,close(11) 关闭和fd11的连接

3.2.12,writev(3,......) 向fd3 (浏览器) 发送502 bad Gateway

3.2.13,向fd4写入一条访问日志,fd4就是nginx访问日志的文件描述符。

以上就是浏览器输入一个url nginx 发生的事 , 接下来追踪下php-fpm  的 worker进程

3.3追踪php-fpm 

lnmp 502错误分析

在上面介绍的 3.2.6 3.2.7 步骤中  nginx 向fpm发起tcp连接

3.3.1  accept(10 ...46554 ,,1270.0.01)  = 5   accpet nginx 的请求 (socket connetc bind listen 在phpfpm master进程中执行) 文件描述符为5 端口号46554 ip 127.0.0.1

3.3.2  5次从发生可读事件的socket 描述符为5中读取数据

3.3.3 到最后 nanosleep(20,0)  脚本中slee(20) 然后执行 kill(12194)

4总结

使用tcpdump 抓包分析了nginx和php-fpm tcp情况可以发现 在进过三次握手之后 

nginx 向fpm发送数据  fpm返回ACK 3s之后 fpm 回复了RST (tcp连接中 一方断掉 会给一方发送RST)

nginx 和fpm 通信方式有两种 一种是 tcp socket   另一种 unix socket

tcp socket  当nginx 和php-fpm不在同一个服务器时 只能使用这种方式

unix socket 当nginx和php-fpm在同一台服务器上时可以使用该方式 进程间通信 相对于tcp更加高效

因为 unix socket  不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等 是需要将应用数据从一个进程拷贝到另一个进程中

盗用一张图来表示几种方式

lnmp 502错误分析

相关文章: