[转载] PHP升级导致系统负载过高问题分析

本文详述了一个PHP从5.3.8升级到5.5.13后,系统负载升高的问题分析过程。作者通过背景介绍、猜想、分析、突破等步骤,发现大量TCP连接处于CLOSE_WAIT状态,最终定位到backlog设置过大导致连接积压,配合Nginx超时设置不合理,引发负载异常。解决方案包括调整backlog、优化日志写入和Nginx超时设置。
摘要由CSDN通过智能技术生成

原文:http://chuansongme.com/n/797172

背景

据XX部门兄弟反应, 其在将PHP从5.3.8 升级到5.5.13 时, 开始运行正常, 运行一段时间后, 系统负载变高,达到200%以上, 从netstat看到大量连接处在CLOSE_WAIT状态。 最终导致系统不可用, 将PHP 回滚到5.3. 8 后, 一切正常。

php-fpm 配置文件除了由版本引起的差异外, 没做任何改变。

猜想

根据TCP关闭连接的流程图:

可以看到, 一个处于连通状态(ESTABLISHED)的连接, 当接收到FIN数据包(对方调用close)后,TCP 连接的状态由ESTABLISHED变为CLOSE_WAIT,等待应用调用close(即发送FIN给对方)。

因此我怀疑PHP由于某种原因被堵塞住(比如数据库等资源太慢),导致请求超时, nginx 主动close连接,而PHP 程序由于一直堵塞,导致其无法调用close,造成大量TCP连接处于CLOSE_WAIT状态。

由于当时没有故障现场, 因此我们挑选一台机器,将PHP5.5重新上线,等待故障现象重现,我计划问题重现时, 用strace 看下进程的系统调用,找出PHP进程到底堵塞在哪里。

分析

1. Strace

周一将PHP5.5.13上线后, 周三大约上午9:30左右,系统负载飙升至200%以上, 立刻用strace 查看,结果没有发现任何堵塞的情况,却发现另一个异常现象:write函数调用失败

当PHP调用write返回响应时,结果报错:Brokenpipe,这说明TCP连接其实已经关闭。PHP并没有堵塞住,这跟我猜想的完全不同,一时想不明白为什么PHP会write 一个关闭了的连接,于是我先用sar 将当前的系统状态保持起来,包括磁盘,内存,网卡,CPU,中断,上下文切换等,留待以后慢慢分析。

分析sar的结果, 发现内存,CPU基本没有什么大的变化, 网卡流量明显降低,上下文切换(cswch/s)明显升高。网卡流量降低可以理解,因为当前系统已不能正常返回响应,但上下文切换(cswch/s)升高却不知道什么原因。

sar的结果暂时没有什么思路, 继续分析strace的结果。Brokenpipe说明连接早已经被对方关闭,难道是nginx超时了?看一下从accept连接到关闭连接的整个流程:

从accept 接受一个socket, 到read 读取数据一直正常, 但调用write当返回响应时,却报错Brokenpipe,从accept到write 一共花费大约1ms ,这段时间内nginx肯定是不会超时的!那为什么连接会关闭呢?我们用tcpdump抓包看下网络到底发生了什么。

Tcpdump

用tcpdump 抓包,由于数据量太大, 我只选择了一台Nginx 的IP10.121.96.200,抓包并传回到本地用wireshark打开(wireshark便于分析),发现网络已经一团糟:

上图是tcp.port == 61029 的过滤结果,10.121.96.200是NGINX的IP, 10.121.96.206 是PHP的IP,后面为了方便直接用NGINX,PHP 来代称这两台机器。

  • 异常1: 从图上可以看到, 开始NGINX向PHP发送SYN, 这是TCP创建连接三次握手的第一次, 然后PHP响应ACK, 这里PHP应该响应SYN+ACK 才是正确的,acknumber 是3646825320 也跟NGINX 发的SYN的序列号对应不起来,因此接下来NGINX 返回RST,直接重置了连接。

  • 异常2: 先不管异常1, 我们继续往下看, 第4个数据包,过了3s后,nginx 重传了SYN包,这时PHP响应SYN+ACK, 序列号也能对应上,NGINX 回应ACK,三次握手完成,连接成功建立。然后NGINX向PHP发送HTTP请求,到了第9个包, NGINX发送FIN 关闭连接,而PHP除了返回对应的ACK外,没有返回任何东西:没有返回响应数据(len=0),也没有返回FIN来关闭连接。从AbsTime字段可以看到第8,9包之间相隔2s,因此合理推测NINGX应该是2s后超时,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值