关于grafana:Grafana-k6-上手实践

5次阅读

共计 7046 个字符,预计需要花费 18 分钟才能阅读完成。

大家好,我是张晋涛。

本篇我将为你介绍一个工具 – k6,它和 K8s 并没有什么间接的关系,它是一款开源的性能压测工具。

k6 背地的故事

2016 年 8 月,k6 在 GitHub 上公布了第一个版本,至此,一个杰出的开源负载压测工具进入了人们的视线。

2021 年的 6 月,对于 Grafana 和 k6 来讲是个大日子,Grafana Labs 收买了 k6。

而事实上,Grafana 与 k6 的缘分还要追溯到更早的 2 年前。

2019 年,在进行 Grafana 6.0 的短期令牌刷新行为的压测时,Grafana Labs 进行了一系列的技术选型。

因为 Grafana Labs 的大部分后端软件是应用 Go 来实现的,凑巧 k6 满足 OSS 和 Go 需要,并且负载测试是应用 JS 编写(Grafana 前端框架及 UI 都在应用)。这使得 k6 自 Grafana 6.0 版本开始,一直地为 Grafana 开发者及测试者实现追踪 bug 的使命。

图 1,k6 退出 Grafana Labs

多样的压测工具

一个满意应手的自动化负载压测工具会极大的晋升程序开发人员的代码品质及效率。

下图中是一些比拟常见的用于负载压测的工具,咱们能够在 GitHub 上看到,目前,更新比拟频繁、沉闷的我的项目次要有:Gatling, Jmeter 和 k6。

图 2,压测工具们

如何从中抉择,简略的讲就是工具效率的比拼。次要从以下两个方面来考量:

  • 工具性能
  • 工具应用体验

下图对以上工具进行了一些简略的比照。

这里我次要比照下其中较为沉闷的 3 个我的项目。

  • JMeter – 相熟 Java 的小伙伴可能比拟理解这个工具。因为存在工夫久,JMeter 的性能是这之中最全面的,并且集成、附加组件做的较好。基于它构建的 SaaS 服务 Blazemeter,置信大家也都熟识。这也导致了一个极大的问题,应用的复杂性高及不够轻量级;
  • Gatling – Gatling 也有着 SaaS 产品 Gatling Frontline。就应用门槛来讲,JS 要比 Scala 要低很多;
  • k6 – k6 最后是由 SaaS 服务 Load Impact 的几名员工开发保护。应用门槛低(JS),参数化更简略,并且“负载测试即代码”的理念也让他的保护老本更低。将来可期。

图 3,3 种热门工具比一比

执行成果

或者这样:

装置 k6

k6 是用 Go 语言开发的,要装置 k6 步骤很简略,只有间接在其 GitHub 的 Release 页面下载二进制文件即可。比方:

(MoeLove) ➜ wget -q https://github.com/grafana/k6/releases/download/v0.35.0/k6-v0.35.0-linux-amd64.tar.gz 
(MoeLove) ➜ tar -xzf k6-v0.35.0-linux-amd64.tar.gz 
(MoeLove) ➜ ls
k6-v0.35.0-linux-amd64  k6-v0.35.0-linux-amd64.tar.gz
(MoeLove) ➜ mv ./k6-v0.35.0-linux-amd64/k6 ~/bin/k6
(MoeLove) ➜ k6 version
k6 v0.35.0 (2021-11-17T09:53:18+0000/1c44b2d, go1.17.3, linux/amd64)

或者也能够间接应用它的 Docker 镜像:

➜  ~ docker run  --rm loadimpact/k6  version   
k6 v0.35.0 (2021-11-17T09:53:03+0000/1c44b2d, go1.17.3, linux/amd64)

外围概念

在 k6 中并没有太多的概念。其中最次要的就是用来执行测试的 virtual users (VUs),它的实质就是并发执行工作的次数。

在应用 k6 执行测试的时候,能够通过 --vus 或者 -u 进行指定,默认是 1。

上手实际

我个人感觉 k6 在目前的这些支流压测工具中算用户体验比拟好的一个。它应用 JS(ES6)作为配置语言,还是比拟不便的,咱们来做一些示例。

简略申请

如果对于进行 HTTP 申请的时候,咱们只须要从 k6/http 导入 http 即可。

留神在 k6 中,默认状况下必须得有个作为入口的 default 函数,这相似咱们罕用的 main 函数。

import http from "k6/http";

export default function(){http.get("https://test-api.k6.io/public/crocodiles/")
}

执行后成果如下:

(MoeLove) ➜ k6 run simple_http_get.js 

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  (‾)  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: simple_http_get.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)


running (00m01.1s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs  00m01.1s/10m0s  1/1 iters, 1 per VU

     data_received..................: 6.3 kB 5.7 kB/s
     data_sent......................: 634 B  578 B/s
     http_req_blocked...............: avg=848.34ms min=848.34ms med=848.34ms max=848.34ms p(90)=848.34ms p(95)=848.34ms
     http_req_connecting............: avg=75.59µs  min=75.59µs  med=75.59µs  max=75.59µs  p(90)=75.59µs  p(95)=75.59µs 
     http_req_duration..............: avg=247.46ms min=247.46ms med=247.46ms max=247.46ms p(90)=247.46ms p(95)=247.46ms
       {expected_response:true}...: avg=247.46ms min=247.46ms med=247.46ms max=247.46ms p(90)=247.46ms p(95)=247.46ms
     http_req_failed................: 0.00%  ✓ 0        ✗ 1  
     http_req_receiving.............: avg=455.24µs min=455.24µs med=455.24µs max=455.24µs p(90)=455.24µs p(95)=455.24µs
     http_req_sending...............: avg=103.77µs min=103.77µs med=103.77µs max=103.77µs p(90)=103.77µs p(95)=103.77µs
     http_req_tls_handshaking.......: avg=848.07ms min=848.07ms med=848.07ms max=848.07ms p(90)=848.07ms p(95)=848.07ms
     http_req_waiting...............: avg=246.9ms  min=246.9ms  med=246.9ms  max=246.9ms  p(90)=246.9ms  p(95)=246.9ms 
     http_reqs......................: 1      0.911502/s
     iteration_duration.............: avg=1.09s    min=1.09s    med=1.09s    max=1.09s    p(90)=1.09s    p(95)=1.09s   
     iterations.....................: 1      0.911502/s
     vus............................: 1      min=1      max=1
     vus_max........................: 1      min=1      max=1

k6 默认会将执行后的后果输入到终端。同时它自带了一些指标会同时输入。

这些指标基本上都是语义化的,看名字就能够了解其含意,这里就不一一介绍了。

带查看的申请

咱们能够在申请中同时减少一些测试,判断接口的响应值是否合乎咱们的预期。如下:

import http from "k6/http";
import {check, group} from "k6";

export default function() {group("GET", function() {let res = http.get("http://httpbin.org/get?verb=get");
        check(res, {"status is 200": (r) => r.status === 200,
            "is verb correct": (r) => r.json().args.verb === "get",});
    });
}

通过引入了 check 函数,来执行一些判断的逻辑,当然上述的 ==> 其实是 ES6 中的一种简写,将其开展为失常的函数也能够。比方:

import http from "k6/http";
import {check, group} from "k6";

export default function() {group("GET", function() {let res = http.get("http://httpbin.org/get?verb=get");
        check(res, {"status is 200": function(r){return r.status === 200},
            "is verb correct": (r) => r.json().args.verb === "get",});
    });
}

应用 k6 执行此脚本后,失去的输入相比之前的多了如下内容:

     █ GET

       ✓ status is 200
       ✓ is verb correct

     checks.........................: 100.00% ✓ 2        ✗ 0

从这里能够看到咱们以后申请接口的测试是否通过(也能够用来判断以后接口是否能失常提供服务)。

自定义指标输入

接下来咱们尝试下在压测过程中定义一些本人定的指标。只须要从 k6/metrics 中导入一些不同类型的指标即可。这和在 Prometheus 中的类型基本一致。

这里我减少了两个 metric。一个 testCounter 用于统计一共执行了多少次测试,passedRate 计算通过率。

import http from "k6/http";
import {Counter, Rate} from "k6/metrics";
import {check, group} from "k6";


let testCounter = new Counter("test_counter");
let passedRate = new Rate("passed_rate");

export default function() {group("GET", function() {let res = http.get("http://httpbin.org/get?verb=get");
        let passed = check(res, {"status is 200": (r) => r.status === 200,
            "is verb correct": (r) => r.json().args.verb === "get",});

        testCounter.add(1);
        passedRate.add(passed);
    });
}

这里咱们设置了 2 个 VU,以及设置了执行过程为 10s 执行后的输入如下:

(MoeLove) ➜ k6 run -u 2 -d 10s  simple_custom_metrics.js
...
  execution: local
     script: simple_custom_metrics.js
     output: -

  scenarios: (100.00%) 1 scenario, 2 max VUs, 40s max duration (incl. graceful stop):
           * default: 2 looping VUs for 10s (gracefulStop: 30s)


running (10.4s), 0/2 VUs, 36 complete and 0 interrupted iterations
default ✓ [======================================] 2 VUs  10s

     █ GET

       ✓ status is 200
       ✓ is verb correct

     checks.........................: 100.00% ✓ 72       ✗ 0  
     data_received..................: 18 kB   1.7 kB/s
     data_sent......................: 3.9 kB  372 B/s
     group_duration.................: avg=567.35ms min=440.56ms med=600.52ms max=738.73ms p(90)=620.88ms p(95)=655.17ms
     http_req_blocked...............: avg=266.72µs min=72.33µs  med=135.14µs max=776.66µs p(90)=644.4µs  p(95)=719.96µs
     http_req_connecting............: avg=170.04µs min=45.51µs  med=79.9µs   max=520.69µs p(90)=399.41µs p(95)=463.55µs
     http_req_duration..............: avg=566.82ms min=439.69ms med=600.31ms max=738.16ms p(90)=620.52ms p(95)=654.61ms
       {expected_response:true}...: avg=566.82ms min=439.69ms med=600.31ms max=738.16ms p(90)=620.52ms p(95)=654.61ms
     http_req_failed................: 0.00%   ✓ 0        ✗ 36 
     http_req_receiving.............: avg=309.13µs min=122.4µs  med=231.72µs max=755.3µs  p(90)=597.95µs p(95)=641.92µs
     http_req_sending...............: avg=80.69µs  min=20.47µs  med=38.91µs  max=235.1µs  p(90)=197.87µs p(95)=214.79µs
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=566.43ms min=439.31ms med=600.16ms max=737.8ms  p(90)=620.19ms p(95)=654.18ms
     http_reqs......................: 36      3.472534/s
     iteration_duration.............: avg=567.38ms min=440.62ms med=600.53ms max=738.75ms p(90)=620.89ms p(95)=655.2ms 
     iterations.....................: 36      3.472534/s
     passed_rate....................: 100.00% ✓ 36       ✗ 0  
     test_counter...................: 36      3.472534/s
     vus............................: 2       min=2      max=2
     vus_max........................: 2       min=2      max=2

能够看到在输入中多了两行:

     passed_rate....................: 100.00% ✓ 36       ✗ 0  
     test_counter...................: 36      3.472534/s

与咱们的预期相符。

不过这样看起来不够直观,咱们能够尝试应用 k6 Cloud 来展现后果。登陆后,只有在执行 k6 时,通过 -o cloud 的形式将输入指定到 cloud 就能够在 cloud 上看到所有的指标了

总结

本篇次要是在介绍一个现代化的用户体验绝对较好的压测工具 k6。我目前正在打算将其引入到咱们我的项目的 CI 中,以便理解每次外围局部的变更对我的项目性能的影响。

后续推动顺利的话,会再分享 k6 如何利用到 CI 环境中,敬请期待。


欢送订阅我的文章公众号【MoeLove】

正文完
 0