zoukankan      html  css  js  c++  java
  • JMeter、K6、locust、FunTester,Who更胜一筹?

    经过了之前的铺垫:性能测试框架对比初探,目前留下来的几个测试框架就是JMeterK6locustFunTester。本次测试目的是对比几种框架的在各个并发下面的发压能力和资源消耗。本次值测试了最简单的GET接口,不涉及参数和POST接口。

    先说结论:

    • 低并发(100线程)情况下,FunTester资源消耗略微占优,但是高并发(200线程)情况下K6牛逼,golang还是比较狂野,优势明显。
    • 在尚未达被测服务性能拐点的时候,FunTester测试框架在资源消耗还有一些优势,但是达到拐点之后,由于线程的频繁上下文切换,K6的优势就非常明显了,总体来看大概两倍的差距。
    • 本地测试也验证了上面两点,不过被测服务的QPS达到6万+,而局域网被测服务最高1.5万徘徊。

    准备工作

    本机硬件2.6 GHz 六核Intel Core i7,CPU统计数据来自活动监视器100%代表消耗了一个CPU线程,理论上全部CPU资源当做1200%,内存数据也来自活动监视器

    首先我利用FunTester moco server框架架构图测试框架在局域网环境起了一个测试服务,只有一个兜底接口。Groovy脚本如下:

    import com.mocofun.moco.MocoServer
    
    class TestDemo extends MocoServer{
    
        static void main(String[] args) {
            def log = getServerNoLog(12345)
            log.response("hello funtester!!!")
            def run = run(log)
            waitForKey("fan")
            run.stop()
        }
    }
    

    同一局域网服务的性能没有问题的,跟本地启动服务区别在于,本地请求太快了,各种框架压测差不不够明显。而且测试本地服务,QPS太高平均响应时间太低了,导致误差会比较大。

    脚本准备

    locust

    本地Python版本3.8locust默认下载版本:locust 1.5.3

    locust框架只需要一个写好的Python脚本,下面分享一下测试脚本。

    第一版非常基础,但是实测太拉胯了,如下:

    from locust import HttpUser, TaskSet, task
    class UserBehavior(TaskSet):
        @task(1)
        def profile(self):
            self.client.get("/m")
    class WebsiteUser(HttpUser):
        tasks = [UserBehavior]
        min_wait = 5000
        max_wait = 9000
    

    经过FunTester地球分社群友指正,这里使用了FastHttpUser代替原来的HttpUser,还有另外一个类似的框架FastAPI,经过测试,性能提升一倍。最终版本内容如下:

    from locust.contrib.fasthttp import FastHttpUser
    from locust import HttpUser, TaskSet, task
    class UserBehavior(TaskSet):
        @task(1)
        def profile(self):
            self.client.get("/m")
    class WebsiteUser(FastHttpUser):
        tasks = [UserBehavior]
        min_wait = 5000
        max_wait = 9000
    
    

    JMeter

    本地Java SDK版本1.8.0_281,运行方式采取了command方式。GUI是在太坑了。

    由于JMeter不用脚本,是在没啥好分享了,一切默认,配置协议、地址、端口、接口路径即可。

    配置文件内容:

     <stringProp name="HTTPSampler.domain">192.168.80.169</stringProp>
              <stringProp name="HTTPSampler.port">12345</stringProp>
              <stringProp name="HTTPSampler.protocol">http</stringProp>
              <stringProp name="HTTPSampler.contentEncoding"></stringProp>
              <stringProp name="HTTPSampler.path">/m</stringProp>
              <stringProp name="HTTPSampler.method">GET</stringProp>
              <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
              <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
              <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
              <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
              <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
              <stringProp name="HTTPSampler.connect_timeout"></stringProp>
              <stringProp name="HTTPSampler.response_timeout"></stringProp>
    

    K6

    虽然k6是用golang写的,但是测试脚本语言是JavaScript,内容如下:

    import http from 'k6/http';
    import { sleep } from 'k6';
    
    
    export default function() {
      http.get('http://192.168.80.169:12345/m');
    }
    

    FunTester

    本机Java SDK版本同上,Groovy SDK版本:Groovy Version: 3.0.8 JVMJava堆内存设置1G,其他参数默认。

    本次默认使用看Groovy测试脚本的方式,运行方式也是Groovy脚本运行方式,是的,还有可以通过Java方式运行,优点就是控制设置JVM参数,实测影响不大。这个方式后期会在阿里开源龙井(Alibaba Dragonwell)时候会对比测试一下结果。

    下面是脚本内容:

    
    import com.funtester.config.Constant
    import com.funtester.frame.execute.Concurrent
    import com.funtester.frame.thread.RequestThreadTimes
    import com.funtester.httpclient.ClientManage
    import com.funtester.httpclient.FunLibrary
    import com.funtester.utils.ArgsUtil
    import org.apache.http.client.methods.HttpGet
    
    class Share extends FunLibrary{
    
        public static void main(String[] args) {
            ClientManage.init(10, 5, 0, EMPTY, 0);
            def util = new ArgsUtil(args)
            int thread = util.getIntOrdefault(0,200);
            int times = util.getIntOrdefault(1,10000);
            String url = "http://192.168.80.169:12345/m";
            HttpGet get = getHttpGet(url);
            Constant.RUNUP_TIME = 0;
            RequestThreadTimes task = new RequestThreadTimes(get, times);
            new Concurrent(task, thread, "本地固定QPS测试").start();
            testOver();
        }
    }
    
    

    万事俱备,准备测试!!!

    实战开始

    我查资料的时候,很多直接从100线程并发开始,以倍增甚至质数增长到上万的,但在实际使用中单机根本用不到,我本机测试性能拐点大概150左右,最终瓶颈点也在200以内。所以呢,我设置了四项1050100200

    首先10线程肯定都是轻轻松松的,硬件资源都是足够的,可以做一个参照。50线程算是一个中等压力,主要对比10线程,100线程差不多性能已经比较高了,但是应该还没到拐点,200线程应该是超过拐点,到达瓶颈点。

    当然这里有照顾locust的因素,经过我前期初测,实在没必要搞多节点的必要。

    10线程

    测试结果:

    框架 CPU 内存 QPS RT
    JMeter 37.58 472.7 1040 9
    K6 53.54 78.2 2302 4.26
    locust 83.65 45.9 1049 8
    FunTester 28.82 385.3 2282 4

    JMeterFunTester内存都比较高,这个特点一直存在。实测结果中,k6FunTester所测QPS比较高,也比较接近,JMeterlocust基本砍半,补充测试JMeter GUI测试结果更惨,还得砍。CPU数据除了locust以外其他都差不多,因为这个数据是我肉眼 记录感觉平均,实际测试过程中波动也比较大,误差是难免的。

    盲猜locust应该是花费了一些精力同步计算测试结果了。而JMeter我是先测试后查看结果,应该排除了这个问题。

    测到这里,locust基本要被淘汰了,实在有点低,消耗CPU还多,不过还是下一轮还是测了locust

    50线程

    测试结果:

    框架 CPU 内存 QPS RT
    JMeter 120.71 776.7 3594. 13
    K6 161.02 107.9 9805 5.02
    locust 99.45 55.8 1424.52 27
    FunTester 88.64 392.6 9773 5

    结论跟上一轮差不多,具体的各位可以看看数据。

    整个测试过程中JMeter数据中QPS波动过于大了,最低的不到2000,上面是QPS最高的一次。而且我发现JMeter对于端口或者连接利用率不是很好,QPS一高起来,一会就报连接异常,网上一查说是端口不够用了,改完就好,继续增大线程,继续垮掉。可能是我姿势不太对,反正FunTester足够用。

    经过查证,JMeter端口数大概使用了线程数三倍再多一点的端口数。FunTester用了两倍多一点,k6一直比较稳定的低,一直在50以内。这一点我以后得研究研究继续优化。

    接下来的测试我抛弃locust,也抛弃JMeter了,错误率太高了,测试过程中,JMeter测试用例可读性差的问题,显露无疑。

    100线程

    只剩下两个强者,测试结果:

    框架 CPU 内存 QPS RT
    K6 199.69 168.4 12631 7.84
    FunTester 225.74 424.7 13604 7

    数据相差并不大,K6消耗的CPU也逐渐降下来了,与FunTester很接近了,说明此时差不多应该是到了性能拐点附近。

    200线程

    测试结果:

    框架 CPU 内存 QPS RT
    K6 239.97 240.4 15354 12.94
    FunTester 431.52 427.9 14940 13

    这里可以看出K6的优势还是非常明显的。初步判断应该到了瓶颈点,线程数增加了一倍,QPS只增加了10%量级,而且响应时间明显升高。

    后来我通过修改JVM启动参数,增加堆内存,实际效果上没有明显提升。不得不说,golang协程非常厉害,Java协程这块有一个阿里龙井的解决方案,开源免费,我暂时没有测试,有兴趣的可以了解一下,真的相当牛逼。

    今天的对比测试结束了,有兴趣的同学可以到FunTester地球分社中多多交流。

    Goold Luck ! FunTester !


    FunTester腾讯云年度作者Boss直聘签约作者GDevOps官方合作媒体,非著名测试开发,欢迎关注。

  • 相关阅读:
    【MongoDB】MongoDB服务器搭建(Unix/Linux)
    【MongoDB】MongoDB VS SQL数据库
    【谷歌市场安装】Google Play 闪退问题解决
    【安卓面试题】简述一下Android系统的架构?
    【安卓面试题】Activity和Task的启动模式有哪些?每种含义是什么?举例说明各自的应用场景
    【AR】Vuforia App key is missing.Please get a valid key
    备忘录
    docker 学习笔记
    java -jar 参数前后位置说明
    SaltStack实现动态文件分发,支持脚本换行,中文乱码
  • 原文地址:https://www.cnblogs.com/FunTester/p/14950968.html
Copyright © 2011-2022 走看看