首页 运维 nginx nginx+php-fpm服务HTTP状态码502怎么解决

nginx+php-fpm服务HTTP状态码502怎么解决

May 21, 2023 am 08:07 AM
php nginx fpm

我们的一个web项目,由于新上城市增多,导致访问量增大,db压力增大,作为提供接口的业务方,最近被下游反馈大量请求“502”。

502,bad gateway,一般都是upstream(这里就是php)出错,对于php,造成502的原因常见的就是脚本执行超过timeout设置时间,或者timeout设置过大,导致php进程长时间不能被释放,没有空闲worker进程来接客。

我们的项目就是php执行时间设置过短导致的,对于这种情况,可以先适当增大php的执行时间,先保证清除502,优化的事情毕竟要花更多的时间。

控制php执行时间的选项有两个,在php.ini中 max_execution_time 和php-fpm中 request_terminate_timeout,其中 request_terminate_timeout 可以覆盖 max_execution_time,所以如果不想改全局的php.ini,那只改php-fpm的配置就可以了。

下边我就来详细的分析一下为什么php脚本执行超出设置时间会导致nginx返回502。

先来布景,让问题复现:

nginx和php分别只启动一个worker,方便追踪。

php-fpm的request_terminate_timeout设置为3s。

测试脚本test.php

sleep(20);
echo 'ok';
登录后复制

go go go:

在浏览器访问www.v.com/test.php,3s后如期出现...404???what???

nginx+php-fpm服务HTTP状态码502怎么解决

出师不利啊,赶紧看看nginx的配置文件

nginx+php-fpm服务HTTP状态码502怎么解决

这个location配置是当发生5xx错误时跳转到一个好看点的界面,但是我在/usr/share/nginx/html下并没有50x.html这个文件。所以搞了个404出来。这不是很影响我判断问题的准确性?直接注释掉!再次访问,等待3s,终于'正常'的界面出来了。

nginx+php-fpm服务HTTP状态码502怎么解决

环境好了,下边就上套路,按照web问题的排查套路走一遍,先看看错误日志吧:

nginx:

nginx+php-fpm服务HTTP状态码502怎么解决

报错都是 recv() failed (104: connection reset by peer。

recv时失败了,连接被重置了。为啥连接被重置了?难道一言不合。

我们在看看php-fpm的错误日志:

(注意php-fpm中php_admin_value[error_log]选项指定php的错误日志,会覆盖php.ini中的。但是这里不是看php的错误,而是看php-fpm的错误。php-fpm的错误日志由php-fpm.conf中的error_log选项指定。)

nginx+php-fpm服务HTTP状态码502怎么解决

每一次请求都是产生2个warning和1个notice:

warning:脚本执行超时了,终止了。

warning:子进程收到sigterm信号退出了。

notice:启了一个新的子进程(因为我设置的pm.min_spare_servers = 1)

看来如果php的worker进程执行超时,不仅终止脚本执行,而且worker进程也会退出。看来nginx的报错连接被重置是因为php的worker进程退出了(在tcp连接中一方如果断掉的话会发送rst给另一方)

通过日志已经可以知道php脚本执行超时,worker子进程退出,导致nginx报错connection reset by peer,下边我们通过strace来看看php和nginx的情况:

php:

nginx+php-fpm服务HTTP状态码502怎么解决

1.accept一个nginx的连接请求(socket,bind,listen都在master中完成 ),可以看到nginx的端口是47039,从fd0中读取数据,就是从标准输入中,这个是fast-cgi协议规定的。accept之后的已连接描述符是3。

2.从fd3中读取nginx传递过来的数据,fastcgi协议格式,接收了856字节。为什么read5次呢?

因为fastcgi协议数据包是8字节对齐,由包头和包体组成。并且都是会先发一个request数据包,包含一些请求id,版本,typpe等信息(包头包体各占8字节),再发一个params数据包,传递get参数和环境变量(包头8字节,包体变长),最后发送一个没有包体只有包头的params数据包,表示参数发送结束(包头8字节)。所以前3个read用来读出request包的包头和包体,还有params包的包头,第四个read是读取真正的数据,最后一个read是读取最后一个params包的包头。所以nginx传递的数据应该是8+8+8+856+8=896字节(和下边nginx的传输bytes能对应上)。注意如果是post方式,还会发送stdin数据包。

3.设置休眠20s,就是php程序中的sleep(20),之后由于进程被终止了,所以后边就没啦。strace程序也退出啦。

nginx:

nginx+php-fpm服务HTTP状态码502怎么解决

1.accept到浏览器的请求,可以看到浏览器端的端口是56434,ip是192.168.1.105,已建立连接的fd是3。

2.从fd3中接收数据,http协议。

3.创建一个socket,fd21,用于和php建立连接。

4.连接到fd21,可以看到连接的是本机的9000端口,这里nginx和php-fpm使用ip socket连接方式,nginx和php-fpm部署在一台机器上可以考虑unix domain socket。

5.向fd21写入数据,fast-cgi协议格式,我们看到写入的长度是896,和上边的php接收的长度是对应的。

6.recvfrom函数从fd21中返回 econnreset (connection reset by peer)

7.向fd9中写入错误信息,可以推断fd9就是nginx错误日志的文件描述符。

8.关闭和fd21的连接。

9.向fd3写入502 bad gateway,就是返回给浏览器的信息。

10.向fd8写入一条访问日志,可以推断fd8就是nginx访问日志的文件描述符。

来验证一下nginx访问日志和错误日志的推断。可以看到的确是fd8,fd9,并处于写入模式。

nginx+php-fpm服务HTTP状态码502怎么解决

那么在这个过程中整个网络包的传输我们不妨也看一下:

通过tcpdump抓包,用神器看比较方便。

因为只想看nginx和php的通讯,在上边又知道nginx的端口是47039,可以通过tcp.srcport==47039过滤出对应的包。

nginx+php-fpm服务HTTP状态码502怎么解决

可以看到nginx和php-fpm数据交互的过程:47039->9000建立三次握手,接着向9000发送数据,9000回复ack,3s后9000回复rst。没毛病。

注意:

syn,fin各占一个序列号

ack,rst不占序列号(28,29两个包的reqnum和acknum都是相同的)

序列号是每一字节加1(29包发送896字节,同时29包seq为4219146879,30包的ack为4219147775,正好相差896)

rst不需要回复。

以上是nginx+php-fpm服务HTTP状态码502怎么解决的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP:处理数据库和服务器端逻辑 PHP:处理数据库和服务器端逻辑 Apr 15, 2025 am 12:15 AM

PHP在数据库操作和服务器端逻辑处理中使用MySQLi和PDO扩展进行数据库交互,并通过会话管理等功能处理服务器端逻辑。1)使用MySQLi或PDO连接数据库,执行SQL查询。2)通过会话管理等功能处理HTTP请求和用户状态。3)使用事务确保数据库操作的原子性。4)防止SQL注入,使用异常处理和关闭连接来调试。5)通过索引和缓存优化性能,编写可读性高的代码并进行错误处理。

怎么查看nginx是否启动 怎么查看nginx是否启动 Apr 14, 2025 pm 01:03 PM

确认 Nginx 是否启动的方法:1. 使用命令行:systemctl status nginx(Linux/Unix)、netstat -ano | findstr 80(Windows);2. 检查端口 80 是否开放;3. 查看系统日志中 Nginx 启动消息;4. 使用第三方工具,如 Nagios、Zabbix、Icinga。

PHP的目的:构建动态网站 PHP的目的:构建动态网站 Apr 15, 2025 am 12:18 AM

PHP用于构建动态网站,其核心功能包括:1.生成动态内容,通过与数据库对接实时生成网页;2.处理用户交互和表单提交,验证输入并响应操作;3.管理会话和用户认证,提供个性化体验;4.优化性能和遵循最佳实践,提升网站效率和安全性。

nginx在windows中怎么配置 nginx在windows中怎么配置 Apr 14, 2025 pm 12:57 PM

如何在 Windows 中配置 Nginx?安装 Nginx 并创建虚拟主机配置。修改主配置文件并包含虚拟主机配置。启动或重新加载 Nginx。测试配置并查看网站。选择性启用 SSL 并配置 SSL 证书。选择性设置防火墙允许 80 和 443 端口流量。

PHP和Python:代码示例和比较 PHP和Python:代码示例和比较 Apr 15, 2025 am 12:07 AM

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。

linux怎么查看nginx是否启动 linux怎么查看nginx是否启动 Apr 14, 2025 pm 12:48 PM

在 Linux 中,使用以下命令检查 Nginx 是否已启动:systemctl status nginx根据命令输出进行判断:如果显示 "Active: active (running)",则 Nginx 已启动。如果显示 "Active: inactive (dead)",则 Nginx 已停止。

linux怎么启动nginx linux怎么启动nginx Apr 14, 2025 pm 12:51 PM

在 Linux 中启动 Nginx 的步骤:检查 Nginx 是否已安装。使用 systemctl start nginx 启动 Nginx 服务。使用 systemctl enable nginx 启用在系统启动时自动启动 Nginx。使用 systemctl status nginx 验证启动是否成功。在 Web 浏览器中访问 http://localhost 查看默认欢迎页面。

nginx304错误怎么解决 nginx304错误怎么解决 Apr 14, 2025 pm 12:45 PM

问题的答案:304 Not Modified 错误表示浏览器已缓存客户端请求的最新资源版本。解决方案:1. 清除浏览器缓存;2. 禁用浏览器缓存;3. 配置 Nginx 允许客户端缓存;4. 检查文件权限;5. 检查文件哈希;6. 禁用 CDN 或反向代理缓存;7. 重启 Nginx。

See all articles