以前公司网站架构一直都是nginx+apache,因为apache市场占有率还是很大的,稳定性也一直很好,加上如今版本已经升级到2.4,安全和性能方面都有提升,因为公司业务访问量不是太大,所以一直也没计划更换,但最近因为测试人员用jmeter连续测压测3轮200并发(压测都是动态请求)反馈很多报错,查了一个apache的错误日子,报内存不够,8G的内存应该不会这么差吧!而且响应时间在我看来也比较久,其中当然也有一些代码的原因,这里我只想从运维的角度去试试php-fpm替代apache看看效果如何?其实说白了最后主要就是看响应时间和错误率。
1、首先保存单台apache(kvm运行,apache还是优化了的)的压测数据(总共29个接口)
再看看apache优化之后的参数
2、因为这次在测试swarm mode,所以正好通过swarm部署php-fpm环境,单台docker容器运行,代码一样,php.ini版本和参数基本都一样,下面看一组www.conf基本没有做任何优化的压测结果
分析nginx日志和压测结果看到很多500错误,当时我就纳闷了,php-fpm不至于这么弱吧?不是高并发的网站都是使用php-fpm嘛!当时查了一下php-fpm日志报错如下:
Failed to connect to redis: Cannot assign requested address
经排查是php-fpm服务端连接redis有问题,php-fpm频繁的连redis服务器,由于每次连接都在很短的时间内结束,导致产生太多的TIME_WAIT不释放,以至于用完了可用的默认端口号,所以新的连接没办法绑定端口,说明是php-fpm服务端的问题,而不是redis服务器端的问题。通过netstat的确也看到很多TIME_WAIT状态的连接,所以我们需要简单的做一些内核参数优化。
解决办法:
在docker容器所在的宿主机上执行命令
sysctl -w net.ipv4.tcp_timestamps=1 开启对于TCP时间戳的支持,若该项设置为0,则下面一项设置不起作用
sysctl -w net.ipv4.tcp_tw_recycle=1 表示开启TCP连接中TIME-WAIT sockets的快速回收
再次压测已经看到没有500错误,也就是错误率为0,响应时间和apache不分上下,有的接口高,有的接口低,虽然相差不是很大,但这只是php-fpm参数没有优化压测的结果,已经让我感到一丝丝的欣慰啦!
下面是响应时间的截图对比
关于php-fpm优化压测的细节和结论
对于www.conf优化并不是设置的进程数量越高越好,如果设置不合适就会导致系统负载很高,也需要根据压测结果和php-fpm报的错误日志需要不断的调试和压测,提一句还是看结果最重要。下面是我压测过程中日志警告的截图
下面是我调优的参数,系统负载最高都能到30左右。其实还是建议大家根据实际的硬件配置优化,这里我限制了CPU能使用宿主机的400%,内存8G。一般一个php-fpm占用20M内存左右。
www.conf主要优化参数:
php-fpm工作模式选为默认,如果内存很大可以设置为static,但是设置static后只有pm.max_children一个参数有效(切记切记),设置dynamic是所有参数都有效,另外还有一种ondemand管理方式,这里不多议。
www.conf文件优化如下:
pm = dynamic
子进程最大数
pm.max_children = 50
优化后为100,因为并发是200,持续3轮,理论上一般并发多少这个值就设置多少,然后相对于的增加一点点即可!这样php-fpm日志就不会报最大子进程数不够的警告。比如这里我压测的时候也设置了300,观察了php-fpm最多250个左右子进程,但是设置为300的响应时间还没有100好看。
初始子进程数
pm.start_servers = 5
优化后为50
最小空闲子进程数
pm.min_spare_servers = 5
优化后为50
最大空闲子进程数
pm.max_spare_servers = 35
优化后为70
每个子进程重生之前服务的请求数
pm.max_requests = 500
优化后为4000
单个请求的超时中止时间
request_terminate_timeout = 0
优化后为10,如果后端处理时间大于10秒就会报出502,这也是为了很好释放资源的优化,设置的时候一定要注意。
文件打开描述符的rlimit限制
rlimit_files = 1024
优化后为8192
再次压测结果响应时间php-fpm还不如apache好看,甚至比apache弱,这一点确实让我很惊讶,关于www.conf配置文件我优化了N次,但是压测结果在处理时间都没让我很满意,虽然在错误率这方面优势很明显,难道只是我一厢情愿的认为php-fpm比apache强很多吗?难道对于我这种压测标准默认的配置就是最优的吗?这里结果是单台php-fpm只是在错误率上面有明显的优势,处理时间上如果优化不好会比apache弱或者不分上下?以后准备抛除所有压测php测试页面进行对比看看!
个人疑问:
1、最大子进程数设置很大,系统负载偶尔会飙升很高,甚至有时候能到一百多,这里让我很不解。
2、当top看到系统负载不高,而vmstat查看r列会造成cpu严重不足,也能到一百多,又让我真心有点不理解了。