前段时间,网站突然开始出现502。第一想法可能是QPS突然飙升,导致服务器迎接不暇;遂立马登上服务器加大fpm进程数;话说回来如果加大进程数能解决问题的话,这也是当前最快的问题解决方式。并在心中不由的一喜,难道网站访问量突然上升,我们要迎来高并发了吗?本人一直想实际的接触和解决高并发问题,然后像各位大神那样去分享一波经验;此处应有一波自豪而又邪恶的表情,哈哈哈...
然而问题并没有因为添加进程数而得到真正解决。在刚添加进程数时,情况确实有所改善。但短暂的十几分钟后,就又开始出现问题了。由于返回的是nginx的502错误页面,我们也就首先查看nginx的日志。跟踪到错误信息确实是nginx在代理fpm处理时出现超时。那么确实印证了fpm抗QPS能力不足的问题。遂继续加大fpm进程数,此时fpm进程数已经扩大10倍了。由于原先站点访问量一般,并且当前服务器只处理动态页面和数据接口,其他文件资源全部走的CDN和云存储;那么最初的fpm进程数只开了20,在相当长的一段时间里也没出现什么问题。确实也是访问量没上来,QPS最高也就一百出头(^_^)a。加到200进程数后,当前确实没有再收到502的情况反馈。当前问题算是解了。
但回过头来去查看问题时候,发现QPS并没有想象中爆发的那么厉害,最大QPS也才100多!那么问题来了,是什么情况导致PHP进程被占用而无法应对100多的QPS呢?
总的来说可以归结于单个PHP请求处理时间太长;当多数fpm进程被长时间处理的请求占用时,整个站点的抗QPS能力就下降了。当降到无法抗住当前QPS时,就开始频繁的502了。
由于系统较复杂,想直接找出慢执行的请求的代码并不容易。这时,fpm的slowlog功能价值就体现出来了。设置slowlog的timeout时间,并设计存放log路径。纪录能直接精确到方法,还是很赞的。然后对着纪录结果去优化对应的程序逻辑代码吧!
由于调整业务逻辑以及一些详细的优化策略都需要相对较长的时间,那么当前可以先进行一些fpm调整。上述加大进程数是一个,但一台机器的最大进程数还是有上限的。那么为了不让慢执行长时间占用进程,设置fpm的request_terminate_timeout。由于我们站点基本没有特意需要长时间执行PHP的业务,那么就可以选择降低这个值。直接设置成5s,当超出5秒无法处理完直接结束当前执行并跳出504。这样的做法好处在于,不会因为个别慢处理请求导致整站拖垮。当然对于有特殊需求长时间处理的业务就需要根据实际情况来调整了。由于我们的web系统目标是快速且纯萃,那么这样做很合适我们。对于需要长时间执行的业务,我们进行了业务逻辑拆分使用异步处理的方式进行。
我们系统拆分和分布式系统计划还在实施中,暂且写到这吧……