背景

recv() failed (104: Connection reset by peer) while reading response header from upstream问题很显然是 nginx 与php-fpm 间的通信出现了问题,通常是php-fpm由于超时等原因终止导致nginx未收到有效回应。
我这次写这个问题比较局限,是在phalcon框架下发现偶发性的异常问题,且是在线上环境发现的,因此对此问题进行了排查。最终原因是由于内存导致的,因为我怀疑了很多原因,但都不是根源所在,也在网上找到很多类似的问题,但查到的解决方案都不是我的问题根源,所以这篇文章主要是做个记录,本片文章可能对大多数人没有参考意义。

问题发现

之前交接的一个比较老的项目使用的phalcon框架,phalcon是一个与yaf类似的,基于php扩展的注重性能的框架(官网传送门)。由于新加了一些小功能,开发完成后在提供的测试环境进行测试时,发现会出现偶发的502错误,且没有任何规律,我观察了nginx的error_log、php的error_log、php-fpm的error_log,没有找到有效的错误信息。

nginx日志:
2019/03/22 20:17:17 [error] 16436#0: *573 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: xxxxx, server: xxxxx, request: “GET /article HTTP/1.1”, upstream: “fastcgi://unix:/dev/shm/php-fpm.sock:”, host: “xxxxx”, referrer: “xxxxx”
php-fpm日志:
[23-Mar-2019 17:36:25] WARNING: [pool www] child 1843 exited on signal 9 (SIGKILL) after 248.595491 seconds from start

从日志中能够获取到的只是一个标准的反馈,nginx告诉我们没有收到反馈,php-fpm告诉我们进程中断了,但没有人告诉我们为什么。

最初我怀疑的是数据大或者逻辑错误导致php-fpm进程执行时间超时,但慢日志并没有记录,且发现请求在1s+就直接502了,所以确定并不是执行超时导致。

另外注意到我本地环境并没有发现此问题,所以我怀疑是测试环境的硬件配置或nginx/php的设置参数有问题,导致phalcon框架的异常,于是我到线上也进行了验证,结果发现。。。线上竟然也有这个问题,不过很少出现,没有测试环境这么频繁,我就纳闷这个问题一直都没人反馈吗??出于职业道德,不得不给别人擦屁股。

问题处理

于是我查找有没有使用phalcon框架的人也遇到过相同问题并已经有了解决方案,然后我找到几种看似可能的原因:

1、phalcon扩展和opcache扩展的不兼容导致

这个原因看着有点道理,毕竟都是php扩展,且phalcon扩展我并不确定他已被广泛应用并经过了大众的检验。说实话我是这次交接这个项目后才听说这个框架的,然后到官网看了看文档,觉得这个框架也不错,发展的也可以,但可能多少存在一些问题。
于是我暂时关闭了opache扩展,然后再次进行试验,结果问题依旧存在,pass

2、phalcon扩展编译时操作系统位数与实际不一致

在这里插入图片描述
在这里插入图片描述
⬆️原文地址


⬆️原文地址

这个哥们的问题和我的如出一辙啊,而且线上和测试环境都是交接时运维直接镜像部署的,phalcon扩展到底谁编译安装的,安装的对不对确实没人保证也无法查证啊。正在我以为找到了原因,准备重新编译一遍试试时,我注意到我之前在本地搭建环境编译安装时没有选择操作系统位数,并且这个问题是2013年解答的,时间跨度有点大,于是我又到官网确认了下,linux系统的扩展安装没有提及操作系统位数,况且编译的位数不对也不应该偶发,应该会始终异常才对。
显然这个原因也不是我想要的。

3、phalcon框架本身原因

在这里插入图片描述
文档有这样一段描述,“phalcon可能会使您的某些web服务器进程崩溃”。那如果是这样的话,就无解了啊。。

于是我觉得我应该脱离phalcon框架,从php本身去思考问题,说不定问题并不想我想的那么复杂,只是一个小问题。

确实,我起初所有的猜测都是以phalcon扩展为出发点的,不知道怎么的注意力就全被拉到了phalcon上。

问题解决

于是我查阅了可能php-fpm出现recv() failed (104: Connection reset by peer) while reading response header from upstream问题的原因,两大主要原因就是执行超时进程终止和可用内存不够进程终止。
执行超时我之前已经检查过了,php.ini和php-fpm.conf中对php-fpm和cli的超时时间都远超我业务实际执行时间,不存在超时的问题,且请求返回的时间就一两秒。
所以内存成了主要怀疑对象。确实我之前一直没有核对过这个测试服务器的配置,因为一般都会给到2c2g左右的配置,况且只有我一个人在访问,应该不存在性能问题。但我检查机器配置发现这个机器是1c1g,且每次出问题时mem和swap的可用大小都很小了,寥寥可数,那问题就在这了。
于是再次检查php配置,发现php-fpm的配置

pm = static
pm.max_children = 64

以static模式运行64个php-fpm进程,不太适合这个机器的实际配置情况,但应该不至于挂啊,观察php-fpm进程,确实在执行多次请求,且查询大量数据时,很多php-fpm进程占用了大概15%以上的内存,想起phalcon对分页的处理貌似是使用整个orm对象结果集来构造分页数据对象(具体的暂时没有仔细研究),加之数据量确实很大,可能存在消耗内存的情况,如果存在内存泄漏,那这个情况会更凸显。

这样分析较为符合目前偶发的异常问题,另外就这台机器的配置而言,dynamic模式更加适合,进程数也不适合那么多,目前的设置明显也不符合实际,哪怕这不是问题原因肯定也需要优化,内存泄漏直接用pm.max_requests来处理,如果存在的话会得到缓解。

于是我修改了php-fpm的配置:

pm = dynamic
pm.max_children = 15
pm.start_servers = 8
pm.min_spare_servers = 6
pm.max_spare_servers = 15
pm.max_requests = 500

貌似接近默认配置,不过我觉得这样比之前要合适的多。

然后重启php-fpm再次验证一下异常问题是否也得到解决。

在几百次请求后,问题确实没在出现,机器内存也没在像之前一样出现低于1000k的情况。

那么问题到这里结束,之后再去温习一下php-fpm的相关配置,然后深入研究一下对问题进行确认。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐