大家好,我是张锦涛。在本文中,我将向大家介绍一个工具——k6,它与K8s没有直接关系,是一个开源的性能压测工具。k6背后的故事2016年8月,k6的第一个版本在GitHub上发布。至此,一款优秀的开源负载压测工具进入了人们的视野。2021年6月对于Grafana和k6来说是个大日子,GrafanaLabs收购了k6。其实Grafana和k6的缘分可以追溯到2年前。2019年,GrafanaLabs在对Grafana6.0的短期token刷新行为进行压力测试时,进行了一系列的技术选型。由于GrafanaLabs的大部分后端软件都是使用Go实现的,正好k6满足了OSS和Go的要求,负载测试是用JS写的(Grafana前端框架和UI都用到了)。这使得k6从Grafana6.0开始继续完成为Grafana开发人员和测试人员跟踪bug的使命。图1、k6加入GrafanaLabs的各种压力测试工具一款好用的自动化负载压力测试工具,将大大提高程序开发人员的代码质量和效率。下图展示了一些常用的负载测试工具。我们可以在GitHub上看到它。目前经常更新活跃的项目主要有:Gatling、Jmeter和k6。图2展示了如何选择压力测试工具。简单来说,就是工具效率的比拼。主要从以下两个方面考虑:工具性能工具体验下图对以上工具做了一些简单的对比。这里我主要比较比较活跃的三个项目。JMeter——熟悉Java的朋友可能更了解这个工具。由于存在时间长,JMeter的功能是其中最全面的,集成和插件也比较好。相信大家对基于其构建的SaaS服务Blazemeter并不陌生。这也导致了一个巨大的问题,复杂度高,不够轻量化;Gatling-Gatling还有一款SaaS产品GatlingFrontline。在使用门槛上,JS远低于Scala;k6-k6最初是由SaaS服务LoadImpact的几名员工开发和维护的。低使用门槛(JS)、更简单的参数化、“负载测试即代码”的理念也让他的维护成本更低。未来可期。图3三种流行工具执行效果对比还是这个:安装k6k6是用Go语言开发的,安装k6的步骤非常简单,直接从它的GitHubRelease页面下载二进制文件即可。例如:(MoeLove)?wget-qhttps://github.com/grafana/k6/releases/download/v0.35.0/k6-v0.35.0-linux-amd64.tar.gz(MoeLove)?tar-xzfk6-v0.35.0-linux-amd64.tar.gz(萌爱)?lsk6-v0.35.0-linux-amd64k6-v0.35.0-linux-amd64.tar.gz(萌爱)?mv./k6-v0.35.0-linux-amd64/k6~/bin/k6(MoeLove)?k6版本k6v0.35.0(2021-11-17T09:53:18+0000/1c44b2d,go1.17.3,linux/amd64)也可以直接使用Docker镜像:?~dockerrun--rmloadimpact/k6versionk6v0.35.0(2021-11-17T09:53:03+0000/1c44b2d,go1.17.3,linux/amd64)k6中核心概念不多的概念。其中最重要的是用于执行测试的虚拟用户(VU)。它的本质是并发执行任务的数量。使用k6执行测试时,可以通过--vus或-u指定,默认为1。个人感觉k6在目前主流的压测工具中,用户体验更好。它使用JS(ES6)作为配置语言,相当方便。让我们做一些例子。简单请求在进行HTTP请求时,我们只需要从k6/http中导入http即可。注意,在k6中,默认必须有一个默认函数作为入口,类似于我们常用的main函数。importhttpfrom"k6/http";exportdefaultfunction(){http.get("https://test-api.k6.io/public/crocodiles/")}执行后效果如下:(MoeLove)?k6runsimple_http_get.js/\| ̄ ̄|/ ̄ ̄// ̄ ̄//\/\||/////\/\|(/ ̄ ̄\/\||\\|( ̄)|/__________\|__|\__\\_____/.io执行:本地脚本:simple_http_get.js输出:-场景:(100.00%)1个场景,1个最大VU,10分钟30秒最大持续时间(包括优雅停止):*默认值:1个VU中的每一个迭代1次(最大持续时间:10分钟,优雅停止:30秒)运行(00m01.1秒),0/1个VU,1个完成和0个中断iterationsdefault?[======================================]1VUs00m01.1s/10m0s1/1迭代器,每个VU1个data_received.....................:6.3kB5.7kB/sdata_sent...........................:634B578B/shttp_req_blocked......:avg=848.34msmin=848.34msmed=848.34msmax=848.34msp(90)=848.34毫秒p(95)=848.34mshttp_req_connecting...............:avg=75.59μsmin=75.59μsmed=75.59μsmax=75.59μsp(90)=75.59μsp(95)=75.59μshttp_req_duration。...............:avg=247.46msmin=247.46msmed=247.46msmax=247.46msp(90)=247.46msp(95)=247.46ms{expected_response:true}。..:avg=247.46msmin=247.46msmed=247.46msmax=247.46msp(90)=247.46msp(95)=247.46mshttp_req_failed................:0.00%?0?1http_req_receiving................:avg=455.24μsmin=455.24μsmed=455.24μsmax=455.24μsp(90)=455.24μsp(95)=455.24μshttp_req_sending......:avg=103.77μsmin=103.77μsmed=103.77μsmax=103.77μsp(90)=103.77μsp(95)=103.77μshttp_req_tls_handshaking.......:avg=848.07msmin=848.07msmed=848.07msmax=848.07msp(90)=848.07msp(95)=848.07mshttp_req_waiting..........:avg=246.9msmin=246.9msmed=246.9msmax=246.9msp(90)=246.9msp(95)=246.9mshttp_reqs.....................…………:10.911502/秒iteration_duration............:avg=1.09smin=1.09smed=1.09smax=1.09sp(90)=1.09sp(95)=1.09s迭代..............................:10.911502/s对......................:1分钟=1max=1vus_max................................:1min=1max=1k6默认情况下,结果执行后会输出到终端,同时自带一些指标会同时输出。这些指标基本都是语义化的,看名字就可以理解它们的含义,这里就不一一介绍了。Requestwithinspection我们可以在request中同时加入一些测试,判断接口的response值是否符合我们的预期。如下:importhttpfrom"k6/http";从“k6”导入{检查,组};exportdefaultfunction(){group("GET",function(){letres=http.get("http://httpbin.org/get?verb=get");check(res,{"statusis200":(r)=>r.status===200,"isverbcorrect":(r)=>r.json().args.verb==="get",});});}通过引入check函数,执行一些判断逻辑,当然上面的==>其实是ES6中的简写,扩展到普通函数也可以。例如:从“k6/http”导入http;从“k6”导入{检查,组};exportdefaultfunction(){group("GET",function(){letres=http.get("http://httpbin.org/get?verb=get");check(res,{"statusis200":function(r){returnr.status===200},"动词是否正确":(r)=>r.json().args.verb==="get",});});}使用k6执行这个脚本后,得到的输出更多如下:█GET?statusis200?isverbcorrectchecks...................................:100.00%?2?0从这里可以看出我们当前请求接口的测试是否通过(或者用来判断当前接口是否可以正常提供服务).自定义指标输出接下来我们尝试在压测过程中定义一些自定义的指标。只需从k6/metrics导入一些不同类型的指标。这个和Prometheus里面的type基本一样。在这里我添加了两个指标。testCounter用于统计总共执行了多少次测试,passedRate用于计算通过率。从“k6/http”导入http;从“k6/metrics”导入{计数器,速率};从“k6”导入{检查,组};让testCounter=newCounter(“test_counter”);让passedRate=newRate(“passed_rate”);导出默认函数(){group(“GET”,function(){letres=http.get(“http://httpbin.org/get?verb=get”);让passed=check(res,{"statusis200":(r)=>r.status===200,"isverbcorrect":(r)=>r.json().args.verb==="get",});testCounter.add(1);passedRate.add(passed);});}这里设置2个VU,执行过程设置为10s。执行后的输出如下:(MoeLove)?k6run-u2-d10ssimple_custom_metrics.js...execution:localscript:simple_custom_metrics.jsoutput:-scenarios:(100.00%)1scenario,2maxVUs,最长40秒持续时间(包括优雅停止):*默认值:2个循环VU持续10秒(优雅停止:30秒)运行(10.4秒),0/2个VU,36次完整迭代和0次中断迭代默认?[=======================================]2VUs10s█GET?statusis200?isverbcorrectchecks...........................:100.00%?72?0data_received......:18kB1.7kB/sdata_sent..............................:3.9kB372B/sgroup_duration.....................:avg=567.35msmin=440.56msmed=600.52msmax=738.73msp(90)=620.88msp(95)=655.17mshttp_req_blocked......:avg=266.72μsmin=72.33μsmed=135.14μsmax=776.66μsp(90)=644.4μsp(95)=719.96μshttp_req_connecting......:avg=170.04μsmin=45.51μsmed=79.9μsmax=520.69μsp(90)=399.41μsp(95)=463.55μshttp_req_duration.....................:avg=566.82msmin=439.69msmed=600.31msmax=738.16msp(90)=620.52msp(95)=654.61ms{expected_response:true}...:avg=566.82msmin=439.69msmed=600.31msmax=738.16msp(90)=620.52msp(95)=654.61mshttp_req_failed.................:0.00%?0?36http_req_receiving...............:avg=309.13μsmin=122.4μsmed=231.72μsmax=755.3μsp(90)=597.95μsp(95)=641.92μshttp_req_sending......:avg=80.69μsmin=20.47μsmed=38.91μsmax=235.1μsp(90)=197.87μsp(95)=214.79μshttp_req_tls_handshaking......:avg=0smin=0smed=0smax=0sp(90)=0sp(95)=0shttp_req_waiting…………:avg=566.43msmin=439.31msmed=600.16msmax=737.8msp(90)=620.19msp(95)=654.18mshttp_reqs……......................:363.472534/siteration_duration.......:avg=567.38msmin=440.62msmed=600.53msmax=738.75msp(90)=620.89msp(95)=655.2msiterations................:363.472534/spassed_rate...........................:100.00%?36?0test_counter.....................:363.472534/svus..........................:2min=2max=2vus_max............................:2min=2max=2可以看到输出中多了两行:passed_rate...................:100.00%?36?0test_counter.....................:363.472534/s符合我们的预期,但这似乎不够直观,我们可以尝试使用k6Cloud显示结果。登录后,只要在执行k6时通过-ocloud指定输出到云端,就??可以看到云端的所有指标。总结本文主要介绍一款用户体验相对较好的现代压测工具k6。我目前正计划将其引入到我们项目的CI中,以了解每个核心部分变更对项目性能的影响。如果后续进展顺利,我会分享k6如何应用于CI环境,敬请期待。欢迎订阅我的文章公众号【MoeLove】
