说人话!互联网公司里测试接口的性能要怎么搞?——简单粗暴地搞!

作为一个QA,性能测试是避不开的。说性能测试的书、帖子都有少,它们会告诉你什么是性能测试,什么是压力测试,什么是负载测试等等,然后还会告诉你做性能测试的时候可以用jmeter、loadRunner等等工具。。。。。问题是,如果我是一个入门者,我即使了解了这些,对我的实际测试工作会有什么实质性的帮助吗?实际工作中会那么区分负载啊、压力啊这些概念性的东西吗?我知道了这些概念又能怎样?。。。。

综上,我认为现实中的性能测试是具体的,是基于业务的,正因为基于业务,这就决定了现实的性能测试不会去区分压力或者负载,这些通常要在一次测试中同时完成。

互联网软件实际中的性能测试,往往不会专门去针对硬件去测试它的性能(也没有那么绝对),更多的是以软件的性能去驱动硬件的配置。而软件的性能测试往往会针对两种对象,一种是底层的公用软件,比如数据库、web容器、mq、框架等等,再具体点,是mysql、redis、nginx、kafka、thrift、dubbo等等,这些通常要求QA在项目开始架构时完成,及时确定这些基础架构的性能,从而帮助架构师和运维从容不迫的完成架构设计和基础搭建工作。拿mysql举个栗子,我作为一个架构师,我不知道mysql能不能满足业务的需求,如此就需要QA出马,模拟出线上的极限访问量,测试下mysql的极限在哪,能不能满足线上业务量的需求。当然这对于经验丰富的架构师来说,可以一眼看出破绽,而QA的意义在于在各种基础软件搭配在一起的极其复杂的环境下找出薄弱的一环,出具性能测试报告,为架构提供官方性能依据。

上面说了那么多,其实本文主要说的是另一种对象,

也是最常见的对象,即在项目中由RD实实在在写出来的代码。测试的代码种类太多,本文说的是接口。

我们开始了。互联网行业的项目,通常都是快速迭代的,不会给QA太多的时间去做一套完整的性能测试,所以这里的性能测试目标简单粗暴——保证测试的接口在线上稳定运行而不挂。以下说的东西都是基于这个目标,简单而有效的进行的。

首先,不管做什么测试,了解测试对象的逻辑是必须的。做测试之前,按照正规的流程肯定会有评审,到了功能测试的时候,我们的测试用例也肯定已经刷刷地写出来了。但我认为以功能测试的测试用例来驱动性能测试,是不科学的。测试用例通常是我们根据业务场景做出来的,不是我们根据代码做出来的,是黑盒的。因此,我们并不知道逻辑怎么走是最消耗性能的,各种测试用例杂糅在一起展现不出极限压力,因为每个测试用例走的代码路径都不相同,有些测试用例甚至没有走到目标接口的内核就已经return了。这个时候,走进代码,查看代码逻辑就很重要的,换句话说我们的接口性能测试是基于白盒测试的。此时,小伙伴会问,代码看不懂怎么办?那就办不了了,只能加强学习咯。。。

既然是基于白盒的,那么测试路径的选择就可以按照白盒测试方式进行。但是测性能不需要白盒测试那么多数量的测试用例。在白盒用例的基础上进行裁剪,选择能够展现出压力的测试用例即可。例如,我们测试一段代码:

public int test(int i) {
    a = 3;
    if(i < 10) return 0;
    else if(i =10) {
        a = op1(a);
        return a;
    } else {
        a = op2(a);
        return a;
    }
}

显然,对于上述代码,对于白盒测试来说,需要测试三条路径以确保功能正确,分别是i<10、i=10和i>10。但对于性能测试来说,i<10这条路径直接返回了0,没有做任何事情,这条路径是可以筛减的,它根本没有展现出测试数据对代码的性能压力。换句话说,能扛得住i=10和i>10这两条路径的压力,对付i<10的压力也是不在话下。我们尽可能筛选一些能够跑出压力的路径来作为我们的测试用例,用例尽可能的少,保证整个接口的性能测试简单有效。

另一方面,如果测试的项目是一个优化类的项目,可以更加着重于新增功能的性能。当然,这不意味着放弃之前功能的性能回归,只是可以将之前的功能放在稳定性测试中去,以排除新增功能对老功能的影响。

再者,性能测试工具的选择上。jmeter是很有效的测试工具,对于http接口,使用jmeter简单轻松。我们可以根据我们决定好的性能测试用例来设置输入参数和开放的线程数。对于rpc接口来说,jmeter并没有直接提供现成的界面,我们需要自行开发一个java取样器来开展测试。这么做当然无可厚非,然而调试java取样器的过程繁琐复杂,需要写好脚本,再打成jar包,放在jmeter的lib文件夹中进行调试,效率极低。加上jmeter自身有若干bug,运气不好撞上了,一般人只能挠头叹气了。所以,对于rpc接口,我在这里安利大伙一个工具——JMH,一款由openJDK团队开发的性能测试工具,JDK9以上版本自带,JDK8需要引入依赖,工具质量可以保障(毕竟JDK团队出品的,质量要比jmeter靠谱的多)。JMH没有界面(PS:真正的猛士是不屑于使用带界面的工具的),一切靠代码(这使得测试变得非常灵活),可以在eclipse里直接运行(调试非常方便),当然也可以打成jar包,放到服务器上去运行。怎么用的?限于篇幅本文不说,参见官网http://openjdk.java.net/projects/code-tools/jmh/ ,官方文档是英文的,之后我也会写若干关于JMH的文章。

还需要准备的是对于接口的预期性能目标,即性能能不能满足线上的需求。举个栗子,拿滴滴打车的业务来说,我们要测试下单接口。需要了解每天的下单量,每天下单量的峰值是多少,线上机器有多少台,测试环境机器有多少台等等。一般我们人工制造的压力(以吞吐量tps为单位)通常为每天下单量峰值的1.5倍。另外,需要注意的是,一般情况下,线上机器数量与测试环境机器的数量是不一样的,而我们的性能测试只能存在于测试环境,因此我们需要计算测试环境每台机子对应应该达到的吞吐量。这需要了解,请求分发机制。以nginx轮询机制来说,请求平均被分发再每台机器上,我们可以简单的按照总吞吐量除以线上机器数量来得到每台机器的吞吐量。综上,可以拿到测试环境下的预期性能目标,能不能达到目标,就要拿测试结果说话了。

接下来就要真正进入测试状态了。测试是分多轮的,每轮的测试时间不必太长,5分钟足够。每一轮测试所发起的线程数量呈线性增加,以达到逐轮增加接口压力的效果。接口的性能测试通常以两种状态结束:第一种,程序扛不住,挂了;第二种,随着测试线程数的增加,tps不再增加,因为此时已经存在请求在等候队列中排队了,此时的tps数就是该接口的性能峰值。对于以第一种结果结束的情况,不仅要查看程序崩溃时的吞吐量是否已经达到预期性能,也要查看程序崩溃的原因,多数是因为内存溢出造成的。对于第二种,要查看最总吞吐量是否符合预期,小于预期的话,则需要进一步优化。

最后,以上测试都通过了,性能应该不存在什么问题了。在实际工作中,我通常还会拉一些线上的真实数据作为测试的输入数据来一次测试,并模仿线上真实的tps来兜底。线上的数据来源于线上机器的log文件,这是一个野路子,但是很有效,可以弥补我们测试用例的疏漏。测试的时间很长,通常用一晚上的时间来跑真实数据,第二天早上来看结果(又是简单粗暴的方式。。。)。我把它叫做稳定性测试。值得注意的是,用一晚上的时间来测试,会产生大量的log,这样我们需要有专门的脚本来定时删除log,避免磁盘空间的报警。

综上,接口的性能就可以保证了。总结一下我们这个简单粗暴的接口性能测试的流程:了解代码逻辑——筛选性能测试脚本——确定预期性能——选择测试工具——逐轮测试——稳定性测试——完。

猜你喜欢

转载自blog.csdn.net/qilinxo/article/details/84932832
今日推荐