nginx+php-fpm服务HTTP状态码502怎么解决
我们的一个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的配置文件
这个location配置是当发生5xx错误时跳转到一个好看点的界面,但是我在/usr/share/nginx/html下并没有50x.html这个文件。所以搞了个404出来。这不是很影响我判断问题的准确性?直接注释掉!再次访问,等待3s,终于'正常'的界面出来了。
环境好了,下边就上套路,按照web问题的排查套路走一遍,先看看错误日志吧:
nginx:
报错都是 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选项指定。)
每一次请求都是产生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:
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:
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,并处于写入模式。
那么在这个过程中整个网络包的传输我们不妨也看一下:
通过tcpdump抓包,用神器看比较方便。
因为只想看nginx和php的通讯,在上边又知道nginx的端口是47039,可以通过tcp.srcport==47039过滤出对应的包。
可以看到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中文网其他相关文章!

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

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

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

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

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

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

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

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

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