0

0

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

PHPz

PHPz

发布时间:2023-05-21 08:07:05

|

1474人浏览过

|

来源于亿速云

转载

我们的一个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:

a0.dev
a0.dev

专为移动端应用开发设计的AI编程平台

下载

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不需要回复。

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

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

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

44

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

58

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

11

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

21

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

35

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.7万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 7万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号