概述 一个产品的编码完成,并不能代表产品能够给用户体验,其中还必须包含测试、压测分析等,而往往我们的产品上线前却忽略掉压测分析。既然压测分析很重要那么我们应该如何进行呢? 本文章主要通过实践经验来学习了解压测过程,并且提出一些在 PHP 端可以进
概述
一个产品的编码完成,并不能代表产品能够给用户体验,其中还必须包含测试、压测分析等,而往往我们的产品上线前却忽略掉压测分析。既然压测分析很重要那么我们应该如何进行呢?
本文章主要通过实践经验来学习了解压测过程,并且提出一些在PHP端可以进行优化的功能点,从而帮助后续开发过程中应用最优方式去编码。
有道是磨刀不误砍柴工,要有好的工具才能做事更有效率,要学会工具的应用才能更进一步的优化系统项目。
关于PHP的工具性能检测工具的话,可以应用xhprof工具或者CI的原生时间打印工具。Xhprof工具的使用方法大家可以参考:http://blog.snsgou.com/post-278.html。
CI原生工具打印时间则了解CI中Benchmark类库中关于mark方法的应用,其主要是针对mark中包含*_start和*_end的所有标记时间添加到CI的debug页面信息中。因此如果我希望查看某个类库的加载时间,我只需要做例如下面的处理方式:
$BM =& load_class('Benchmark', 'core'); $BM->mark('base_classes_start'); // load base classes $BM->mark('base_classes_end);
如果这样一个个添加会让你觉得很蛋疼,因为类库太多了,那么这里就可以应用小技巧,你只需要在load model和load library处添加该处理功能,那如果使用的是原生的require时,则会相对较为麻烦。
在调整如上代码时,切记要备份一份完整的代码。将如上的工具都应用到项目代码中后,我们接下来就是来分析需要优化的接口。
在压测前首先你需要解决那些很明显的问题,比如说一个请求会多次加载类库、一个请求会多次请求memcached中相同数据、一个请求会多次请求redis中相同的数据、一个请求会多次的new一个类库等等。而这些问题都可以在压测前分析解决。以下是一个自我检测表格,如果大家以后有需要可以进行相应的检查并优化。
优化问题 |
分析 |
优化方向 |
备注 |
多次加载类库 |
在创建类似redis、memcached以及mongodb的类库时,都会在构造函数中创建连接,而如果处理不当时则会加载多次创建多个句柄,导致服务端句柄连接非常多,加大每个连接处理的时间。 |
如果有长连接方式则尽量使用长连接,如果没有则在每次连接时,应用静态变量保存,下次需要重新创建连接时则进行判断,避免一个请求产生多个句柄。 |
一般经常性使用的类库都有做这种处理,但也不排除未做处理的,因此在压测前可以好好的查看一下。 |
单个数据多次请求缓存 |
在正常情况下,大家都会觉得既然是读取缓存那么效率上应该很高,所以一般情况下需要数据时都直接读取缓存内容。这样会导致一个情况是单个数据的缓存可能被请求了多次。 |
首先需要知道哪些数据被请求了多次,因此可以在缓存的get方法中添加日志,记录每一次读取缓存的key值,最后再分析查看哪些数据被读取了多次。从而来进一步优化,在缓存读取完成后,使用一个静态数组保存读取完成的数据,如果读取过则直接从本地内存中获取,而无需远程缓存数据。 |
如果缓存在静态变量中相当于读取本地内存,而如果应用其他缓存工具,则会在创建连接以及算法上有细微的差距。而如果在高并发的情况下,这种对比就会被无限的放大。 |
关闭debug日志 |
一般PHP系统都会存在debug日志,在压测并非时可能会存在影响,因此最好是关闭debug模拟现网只有info和error日志内容。 |
关闭debug日志,保留info和error,与现网保持一致。 |
这部分在低并发时也时也很难看出问题,但在高并发时可以明显看出这会影响到系统性能,因此在压测前以及现网必须要进行关闭。 |
对以上三个方向进行了优化后,我们接下来就开始准备对系统进行压测分析。
压测前需要注意以下几点:
1、压测前必须要保证去除登录逻辑,并能够进入正常的数据请求;
2、压测将接口分析以便同一类接口,可以避免修改逻辑一起压测;
3、压测数据表格设计,尽量能够设计分析出系统的极限处理能力,例如下面表格;
压测并发 |
压测请求量 |
压测服务器 |
吞吐量 |
Xhprof标准 |
20 |
10000 |
236 |
510 |
http://xxx |
50 |
10000 |
236 |
550 |
http://xxx |
4、应用xhprof工具打点分析,为了xhprof不影响现网的运行,可以使用概率打点方法。
如果前期准备完善的话,接下来的压测就较为简单了,只需要跑一下流程,然后查看一下xhprof打印的数据,并且记录下xhprof页面url以及压测结果的吞吐量。这部分需要注意的一点是必须要等被压测服务器的负载降低时才能进行下一次压测,避免压测未达到最佳性能。
1、压测数据分析
如果前期压测数据都已经完成后,再将压测表格数据做成一个折线图(绘制折线图的方法,可以使用execl)。通过折线图分析出系统服务器的最佳并发以及最佳并发下的最大吞吐量,例如下面的折线图。
分析完成以后,就可以看到服务器在大概100并非时是最大的性能,因此我们接下来就可以分析在100并发以后系统代码运行的异常问题。
2、xhprof性能分析
从上面的数据分析后,对于100并发前的性能就无需进行查看,而对100并非后的xhprof结果进行分析,细致的查看每个函数的处理时间以及请求次数。再记录完这些数据后,在通过源码对比,查看是否有部分接口可以再进行优化,或者说再进一步降低请求次数从而达到优化的目的。
在进行压测后发现,mongodb的连接和读取都会对系统产生一个非常大的影响,因此我记录下了其优化方案(加大缓存时间,并整改代码,在拥有缓存数据时则不加载mongodb类库,如果没有缓存则加载类库,即修改基类,在构造函数中不直接加载mongodb类库,而是单独的添加一个方法来加载mongodb类库)。
完成压测后,对代码进行部分的整个优化(整改前请注意备份),优化完成后再跑一遍代码逻辑,避免整改后服务异常,从而未达到压测逻辑的目的。
代码完成以后再进行下一轮的压测对比,而这时的对比就可以看出优化后的明显变化,这也会让我们的信息进一步提升,让我们对压测过程更加充满一种满足的感觉。
在PHP压测优化过程中整体学到了很多知识,在后续的开发过程中则会更加有经验,我也希望通过这个简短的总结能够让大家了解更多学习更多。
关于更多请查看我的个人资讯
http://blog.lovedan.cn/