zoukankan      html  css  js  c++  java
  • 一次简单的性能测试流程

    经常有朋友问我性能测试流程是什么样的,每次我都简单说说,但这东西三言两语说不清,刚好现在刚压测完一个项目,快要放假不忙,就拿刚测试完的项目写一下我们性能测试是怎么做的。

    一、项目背景

    此次需要压测接口共计14个,外加一个消费MQ的批处理。其中14个接口分两部分,对应两个模块,对应两个开发。

    二、环境部署

    此次项目是重构的PHP项目,所以没环境,需要申请并搭建环境,运维申请服务器并搭建PHP和nginx,然后部署和功能测试一样的环境,然后把环境交给我。拿到环境之后我需要改掉配置,配置上我们压测的MySQL、redis、MQ等,然后在服务器上配置好hosts,因为需要调用其他项目的接口,需要配置上对应压测环境的hosts才能正常访问,调试接口能正常访问基本环境就没问题。

    三、脚本调试

    一般我们都会让开发把SQL打印出来,方便我们调试,这次PHP项目最初开发说打不出来,框架打印出SQL就会报错,所以最初在没有SQL的前提下调试接口,效率非常低。后来经开发调试后,SQL能打印出来了,但是这个项目涉及到两个数据库,一个是本地项目的数据库,另一个是其他项目的从库,用来查询数据,到现在为止,那个从库的SQL依然打印不出来。

    说下打印SQL的必要性。其中最重要测是方便接口调试,其次,通过SQL的打印,可以发现一些问题。之前一个项目,其中一个SQL开发查询一次,框架会在打印一次,相当于查询了两次,这种地方都是性能问题。还有这次项目,最初没执行一次SQL都会查询一次表结构,这已经是非常严重的性能问题了,一旦上线会非常慢,后来开发找到原因,说是这是框架打印的,有个开关可以关掉,后来关掉才正常。

     

    举个具体的例子,看下接口调试的细节。下面是一个接口的返回值,不过发现hash是空的,SQL中无信息,所以需要看代码。

     

    代码如下。不全,但是问题肯定在这里,将代码前后加上标记,看是否走到这里。

    结果如下,确实走到,而且是两次,对应刚刚查出两条数据,刚好对上,现在需要走进去看具体的逻辑。

    代码如下,大意就是调用一个方法,然后对返回值进行MD5加密,继续往里看。

     

    具体代码如下,首先先清掉redis,排除已经有key的可能性,排出后,逐个执行SQL,后来发现一个SQL差不到数据,在数据库添加后,hash值正常返回,表示接口调试通过,基本逻辑走到。

     

    四、参数化数据和造数据

    如果需要造数据的话,我们一般会用存储过程,造百万数据还是挺快的,参数化的话我平时都是用一万,涉及到缓存的话清掉缓存就行,走一部分缓存问题也不大,毕竟生产也是走缓存的。

    五、压测

    这次测试其次踩了很多坑,这里就说一个典型的,整理下性能问题定位思路。

    由于我们每次接口比较多,其实我是认为没必要都压测的,压测访问量大的即可,不过老大要求,基本都要压测,所以我们每次任务非常多,有压不完的接口。所以我们习惯先把接口压完,出个结果,有时间的话我们来分析慢的原因,没时间就交给开发,我们做下一个项目。这个项目一样,我也是先压出一个结果。

    压到一半的时候,发现接口按照我们的标准,没一个是通过的,全都不合格,第二部分的接口更是非常慢,高达几秒,问题是服务器CPU并没有满,所以肯定存在严重的性能问题,所以我也就暂停了压剩下的接口,因为压下去也没意义了,所以开始分析问题的原因。

    说实话,来这个公司前我从来没接触过PHP项目,也没看过PHP代码,所以刚开始接触PHP非常头大,我对PHP的环境也不熟,而且我们的环境主要是运维不熟,环境问题应该不会出现,所以我要排除代码的问题。

    方法很简单,代码里打印时间戳,看时间主要消耗在哪里,

     

    加上时间戳之后,可以看清每个方法的时间以及总时间,压测发现一个非常诡异的现象,方法调用时间很短,然后,jmeter的时间非常长。

    至此排除了代码问题(其实错了,后面说),然后开始排除网络问题,因为这个服务器用的阿里云,我们都是用的专线,一般不存在网络问题,但是还是需要排除下。为了方便,先在服务器安装的ab,但是结果是直接返回了200,nginx返回的,接口根本没有访问到(谁知道原因可以跟我说下)。也没多纠结,赶紧在服务器上装了jdk和jmeter,把脚本放到服务器上,直接命令行执行。结果现象和之前压测一样,至此排除网络问题。

    现在把问题定位在了环境上和日志打印上,首先排除日志问题,日志的锁可能会造成上述现象,所以关掉了日志,结果依旧,至此排除日志打印问题。

    至此基本定位到nginx和PHP环境问题。和开发一起调整了nginx和PHP的很多参数,结果一无所获。但是依然不能排除环境问题,所以就想到了一个方法,写一个测试接口。代码如下,无任何逻辑直接返回,在服务器上直接压。结果很快,服务器CPU能打满,至此可以排除环境问题,但是又把问题定位到了代码问题,但是代码体本身是肯定没问题的,因为之前已经把时间打印了。然后问开始,在方法处理前是否还有其他逻辑,开发说校验了token。这个我是一直知道的,但是我们之前token都是开发写死的,我们之间用,不会有任何问题,我也没往这方面想。和开发沟通后发现这次给我的token是他自己测试用的,关键每次都去数据库里做校验,不仅查询还有insert和update操作,我很多个线程都用同一个token去更新同一条数据,必然会出现锁啊,至此也就找到了问题所在。后面写死了一个token,不再去校验,再去压测CPU可以打满了。

     

    虽说刚刚的问题找到了,但是压测发现,响应时间依然很长,在压测完之后,把响应时间最长的接口打印了时间戳,结果发现时间最长的是消耗在了一个调用了其他系统接口的方法上。后来开发决定调用其他系统的尽量都加上缓存,加完缓存后走到缓存的接口确实快了不少,但是所有的接口依然没有达标,不过至此我的任务也已经结束了,因为虽然老大定的指标没达到,但是现在的瓶颈都在CPU上,全是100%,而且用户量不大,在我看来完全满足线上真实压力。所以我就和开发说,就这样了,如果再需要我的话再找我吧,我就先发邮件,后续怎么样让老大决定吧。

    其实还一个原因,这次测试性能这么差,和阿里云有直接的关系。我们之前测试发现,阿里云的机器比m5机器性能至少差一半。这次感觉可能都不止。

    其实这次测试饶了很大的一个圈,被一个问题困恼了两天,压测的总时间才只有三天!不过还是有收获的,把PHP环境熟悉了一遍,就算是塞翁失马焉知非福吧。

    其实之所以能自己打印时间戳定位问题,还是得益于PHP,改完代码直接保存即生效,不需要发版。Java的话完全无法实现,沟通成本太高,所以java的话涉及到改代码的工作主要还是开发做,我们只负责配合。

  • 相关阅读:
    汇编随笔(第一章 基础知识)
    排序集锦(rough)
    如何让编写的Java代码规范整洁
    二分法查询数据java实现
    归并排序的学习与java实现
    小白的软件测试之路
    PyInstaller打包python脚本
    数据库SQL优化总结
    JQuery选择器
    软件测试面试题
  • 原文地址:https://www.cnblogs.com/huantianxing/p/8432714.html
Copyright © 2011-2022 走看看