前言


负载测试,压力测试可以衡量服务是否是一个高可用,高性能的服务。负载测试能检验在不同的工作负荷下,服务的硬件消耗和响应,从而得到不同负载情况下的性能指标。压力测试能检验软硬件环境下服务所能承受的最大负荷并帮助找出系统瓶颈所在。

环境说明


  • 腾讯云轻量服务器, 配置 1c 2g 6mb ,系统是 ubuntu 20.14

K6是什么


k6 是用 Go 语言编写的一种高性能的负载测试工具。具有下面几个特点。

  • K6 嵌入了 JavaScript 运行时,可以使用 JavaScript ES2015/ES6 来编写脚本。
  • 强大的 CLI 工具。
  • 使用 Checks 和 Thresholds 可以更加轻松的做面向目标的自动化的负载测试。

K6 相对于 JMeter 的优势

  • 因为 K6 是 Go 编写的,相对于 JAVA 编写的 JMeter 有性能上的差距,K6 可以只用较少的资源就能达到指定数量的负载。
  • 支持阈值。
  • Javascript 的脚本可以更好的促进协作和版本管理。
  • 资源利用率远远强于 JMeter。
  • 丰富的可视化方案。
  • K6 vs JMeter 详细报告

安装K6


Debian/Ubuntu可以执行如下命令

sudo apt-get update && sudo apt-get install ca-certificates gnupg2 -y
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6

Docker

docker pull loadimpact/k6

HTTP请求


新建一个 test.js 文件

Get 请求 get( url, [params] )

import http from 'k6/http';
export let options = {
vus: 100, // 指定要同时运行的虚拟用户数量
duration: '10s', // 指定测试运行的总持续时间
};
// default 默认函数
export default function () {
// 标头
let params = { headers: { 'Content-Type': 'application/json' } }; var res=http.get("https://test.k6.io",params)
}

Post 请求 Post( url, [body],[params])

import http from 'k6/http';
export let options = {
vus: 100,
duration: '10s',
};
// default 默认函数
export default function () {
// json 字符串
let json = { content: 'linhui', image: 'images' };
// 标头
let params = { headers: { 'Content-Type': 'application/json' } }; var res = http.post("https://host/api/feedback", JSON.stringify(json), params) console.log(res.status); }

del 请求 del( url,[body],[params])

import http from 'k6/http';
export let options = {
vus: 1,
duration: '10s',
};
// default 默认函数
export default function () {
let json = {id:1};
let params = { headers: { 'Content-Type': 'application/json' } };
http.del('https://host/delete', json, params);
}

batch 批处理,可以用来做页面并发,批处理并不能保证执行顺序,batch(method,url,[body],[params])

import http from 'k6/http';
export let options = {
vus: 1,
duration: '10s',
};
export default function () {
let get = {
method: 'GET',
url: 'https://host/get',
};
let get1 = {
method: 'GET',
url: 'https://host/get',
};
let post = {
method: 'POST',
url: 'https://host/post',
body: {
hello: 'world!',
},
params: {
headers: { 'Content-Type': 'application/json' },
},
};
let res = http.batch([req1, req2, req3]);
}

使用 request 发送求 request( method, url, [body], [params])

import http from 'k6/http';
export let options = {
vus: 1,
duration: '10s',
};
export default function () {
let json = { content: 'linhui', image: 'images' };
let params = { headers: { 'Content-Type': 'application/json' } };
let res = http.request('POST', 'http://host/post', JSON.stringify(json), params);
let res1 = http.request('GET', 'http://host/get', null, params);
}

执行脚本,进入脚本根目录

k6 run test.js
# 使用 docker
docker run -i loadimpact/k6 run - <test.js

常见指标说明


指标类型

名称 描述
Counter 计数器,对值进行累加
Gauge 最小值、最大值和最后一个值。
Rate 百分比
Trend 最小值、最大值、平均值和百分位数的统计数据指标

K6 始终都会收集的指标

名称 类型 描述
vue Gauge 当前活动的虚拟用户数
vue_max Gauge 虚拟用户的最大数量
iterations Counter 脚本中的函数被执行的次数
data_received Counter 接收到的数据量大小
data_sent Counter 发送的数据量大小
iteration_duration Trend 完成默认/主函数的一次完整迭代所花费的时间。
checks Rate checks 项的成功率

HTTP 特有的指标

名称 类型 描述
http_reqs Counter 总请求数量
http_req_blocked Trend 在发起请求之前被阻塞的时间
http_req_connecting Trend 建立到远程主机的TCP连接所花费的时间。
http_req_tls_handshaking Trend 与远程主机握手建立TLS会话所花费的时间
http_req_sending Trend 将数据发送到远程主机所花费的时间
http_req_waiting Trend 等待远程主机响应所花费的时间
http_req_receiving Trend 从远程主机接收响应数据所花费的时间
http_req_duration Trend 请求的总时间。它等于http_req_sending + http_req_waiting + http_req_receiving(即,远程服务器处理请求和响应花了多长时间,而没有初始DNS查找/连接时间)
http_req_failed Rate 失败请求率

每一个 http 都会返回一个 HTTP Response 对象,下面是常用的一些属性。

属性 类型
Response.body HTTP 响应正文
Response.cookies 响应 cookies ,属性是 cookie 名称,值是 cookie 对象数组
Response.error 发送请求失败后的错误信息。
Response.error_code 错误码
Response.headers 标头,键值对
Response.status 从服务器收到的 HTTP 响应代码
Response.timings 耗时(以毫秒为单位)
Response.timings.blocked = http_req_blocked
Response.timings.connecting = http_req_connecting
Response.timings.tls_handshaking = http_req_tls_handshaking
Response.timings.sending = http_req_sending
Response.timings.waiting = http_req_waiting
Response.timings.receiving = http_req_receiving
Response.timings.duration = http_req_duration

自定义自己的指标

import http from 'k6/http';
import { Trend } from 'k6/metrics';
export let options = {
vus: 100,
duration: '10s',
};
// 新建一个类型为 Trend 名为 sending_time 的自定制指标
let sendingTime = new Trend('sending_time'); export default function () {
let res = http.get('http://www.baidu.com');
sendingTime.add(res.timings.sending);
}

常用 Option 选项

Vus:指定要同时运行的虚拟用户数量,必须是一个整数,和 duration 搭配使用。默认值:1

export let options = {
vus: 10,
duration: '10s',
};
k6 run -u 10 test.js
k6 run --vus 10 test.js

Duration:一个字符串,指定测试运行的总持续时间,与 vus 选项一起使用。默认值:null

export let options = {
vus: 10,
duration: '10s',
};
k6 run -u 10 --d 20s  test.js
k6 run --vus 10 --duration 20s test.js

User Agent:发送 HTTP 请求时指定 User-Agent 标头。默认值:k6/0.27.0 (https://k6.io/) 取决于你 k6 的版本

export let options = {
userAgent: 'Mozilla/5.0',
};
k6 run  --user-agent 'Mozilla/5.0'  test.js

TLS Version:表示允许在与服务器交互中使用的唯一 SSL/TLS 版本的字符串,或者一个指定允许使用的“最小”和“最大”版本的对象。 默认值:null (允许所有版本)

export let options = {
tlsVersion: 'tls1.2',
}; export let options = {
tlsVersion: {
min: 'ssl3.0',
max: 'tls1.2',
},
};

TLS Cipher Suites:允许在与服务器的 SSL/TLS 交互中使用的密码套件列表。由于底层 go 实现的限制,不支持更改 TLS 1.3 的密码,并且不会执行任何操作。 默认值:null(允许所有)

export let options = {
tlsCipherSuites: [
'TLS_RSA_WITH_RC4_128_SHA',
'TLS_RSA_WITH_AES_128_GCM_SHA256',
],
};

TLS Auth: tls 身份验证。默认值:null

export let options = {
tlsAuth: [
{
domains: ['example.com'],
cert: open('mycert.pem'),
key: open('mycert-key.pem'),
},
],
};

Throw:一个布尔值,true or false ,指定是否在失败的 HTTP 请求上抛出异常。 默认值:false

export let options = {
throw: true,
};
k6 run  --throw test.js
k6 run -w test.js

Thresholds:一组阈值规范,用于根据指标数据配置在何种条件下测试成功与否,测试通过或失败。默认值:null

export let options = {
thresholds: {
http_req_duration: ['avg<100', 'p(95)<200'],
'http_req_connecting{cdnAsset:true}': ['p(95)<100'],
},
};

Tags:指定应在所有指标中设置为测试范围的标签。如果在请求、检查或自定义指标上指定了同名标签,它将优先于测试范围的标签。 默认值:null

export let options = {
tags: {
name: 'value',
},
};
k6 run --tag NAME=VALUE test.js

RPS:每秒发出的最大请求数。 默认值:0

export let options = {
rps: 500,
};
k6 run --rps 500  test.js

Paused:是否可以暂停和和恢复的方式运行脚本,暂停启动后需要使用另外的窗口执行k6 resume 恢复使用。在恢复窗口可以实时的查看脚本的运行情况。 启动后不支持暂停, 默认值:false

export let options = {
paused: true,
};
k6 run --paused  test.js
k6 run --p test.js

No VU Connection Reuse:布尔值,是否复用 TCP 链接。默认值:false

export let options = {
noVUConnectionReuse: true,
};
run --no-vu-connection-reuse  test.js

No Usage Report:布尔值,是否给 K6 发送使用报告,true 值不会发使用报告。 默认值:false

k6 run --no-usage-report test.js

No Thresholds:布尔值,是否禁用阈值。默认是:fasle

k6 run --no-thresholds test.js

No Summary:是否禁用测试结束生成的概要。默认值:false

k6 run --no-summary test.js

No Cookies Reset:是否重置 Cookies,fasle 每次迭代都会重置 Cookie ,true 会在迭代中持久化 Cookie 。默认值:false

export let options = {
noCookiesReset: true,
};

No Connection Reuse:是否禁用保持活动连接,默认值:false

export let options = {
noConnectionReuse: true,
};
k6 run --no-connection-reuse test.js

Minimum Iteration Duration:指定默认函数每次执行的最短持续时间,任何小于此值的迭代都将剩余时间内休眠,直到达到指定的最小持续时间。默认值:0

export let options = {
minIterationDuration: '10s',
};
k6 run --min-iteration-duration '1s' test.js

Max Redirects:最大重定向,默认值:10

export let options = {
maxRedirects: 10,
};
k6 run -max-redirects 10 test.js

Batch: batch 同时调用的最大连接总数,如果同时有 20 api 请求需要发出 ,batch 值是 15,那么将会立即发出 15 个请求,其余的请求会进行一个排队。默认值:20

export let options = {
batch: 15,
};
k6 run --batch 10 test.js

Batch per host:batch 对同一个主机名同时进行的最大并行连接数。默认值:6

export let options = {
batchPerHost: 5,
};
k6 run --batch-per-host 10 test.js

Blacklist IPs:黑名单。默认值:null

export let options = {
blacklistIPs: ['10.0.0.0/8'],
};
k6 run --blacklist-ip= ['10.0.0.0/8'] test.js

Block Hostnames:基于模式匹配字符串来阻止主机,如 *.example.com , 默认值:null

export let options = {
blockHostnames: ["test.k6.io" , "*.example.com"],
};
k6 run --block-hostnames="test.k6.io,*.example.com" test.js

Discard Response Bodies:是否应丢弃响应正文,将 responseType 的默认值修改成 none,建议设置成 true,可以减少内存暂用和GC使用,有效的较少测试机的负载。默认值:false

export let options = {
discardResponseBodies: true,
};

HTTP Debug:记录所有HTTP请求和响应。默认情况下排除正文,包括正文使用 --http debug=full 默认值:false

export let options = {
httpDebug: 'full',
};
k6 run --http-debug test.js

Checks 检查


Checks 类似断言,不同在于 Checks 不会停止当前的脚本。指标都可以作为检查的项目。

import http from 'k6/http';
import { sleep } from 'k6';
import { check } from 'k6'; export let options = {
vus: 100,
duration: '10s',
};
export default function () {
let res = http.get('http://test.k6.io/');
check(res, {
'状态码为200': (r) => r.status === 200,
'响应时间小于200ms': (r) => r.timings.duration < 200,
'等待远程主机响应时间小于200ms': (r) => r.timings.waiting < 200,
});
}

Thresholds 阈值


阈值是用来指定被测系统的性能预期的通过/失败标准。阈值用来分析性能指标并确定最终测试结果。内置的指标都可以作为阈值。

K6 中包含的四种度量类型每一种都提供了自己的一组可用于阈值表达式的聚合方法。

  • Counter: count and rate
  • Gauge:value
  • Rate:rate
  • Trend:p(N)
import http from 'k6/http';
import { Trend, Rate, Counter, Gauge } from 'k6/metrics';
export let GaugeContentSize = new Gauge('ContentSize');
export let TrendRTT = new Trend('RTT');
export let options = {
vus: 10,
duration: '10s',
thresholds: {
// 发出的请求数量需要大于1000
http_reqs:['count>1000'],
// 错误率应该效率 0.01%
http_req_failed: ['rate<0.01'],
// 返回的内容必须小于 4000 字节。
ContentSize: ['value<4000'],
// p(N) 其中 N 是一个介于 0.0 和 100.0 之间的数字,表示要查看的百分位值,例如p(99.99) 表示第 99.99 个百分位数。这些值的单位是毫秒。
// 90% 的请求必须在 400 毫秒内完成,95% 必须在 800 毫秒内完成,99.9% 必须在 2 秒内完成
http_req_duration: ['p(90) < 400', 'p(95) < 800', 'p(99.9) < 2000'],
// 99% 响应时间必须低于 300 毫秒,70% 响应时间必须低于 250 毫秒,
// 平均响应时间必须低于 200 毫秒,中位响应时间必须低于 150 毫秒,最小响应时间必须低于 100 毫秒
RTT: ['p(99)<300', 'p(70)<250', 'avg<200', 'med<150', 'min<100'],
},
}; export default function () { let res = http.get('http://www.baidu.com');
TrendRTT.add(res.timings.duration);
GaugeContentSize.add(res.body.length);
}

阈值标签,测试中可以给指定的 url 或者特定标签上使用阈值。

import http from 'k6/http';
import { sleep } from 'k6';
import { Rate } from 'k6/metrics'; export let options = {
vus: 10,
duration: '10s',
thresholds: {
// type 为 baidu 使用
'http_req_duration{type:baidu}': ['p(95)<500'],
// type 为 bing 使用
'http_req_duration{type:bing}': ['p(95)<200'],
},
}; export default function () {
let res1 = http.get('https://www.baidu.com', {
tags: { type: 'baidu' },
});
let res2 = http.get('https://cn.bing.com/', {
tags: { type: 'bing' },
}); let res3 = http.batch([
[
'GET',
'https://www.baidu,com',
null,
{ tags: { type: 'baidu' } },
],
[
'GET',
'https://cn.bing.com/',
null,
{ tags: { type: 'bing' } },
],
]); }

默认情况下没有达标阈值标准是不会停止脚本的,通过设置阈值的 abortOnFail: true 来终止。

import http from 'k6/http';
export let options = {
vus: 10,
duration: '10s',
thresholds: {
http_req_duration: [{threshold: 'p(99) < 10', abortOnFail: true}],
},
}; export default function () {
let res = http.get('http://www.baidu.com');
}

对通过的阈值前面会有一个✓,而失败的则会有一个 ✗ 。只有满足所有阈值的情况下测试才算通过。

日志输出


输出到控制台。

import http from 'k6/http';
export let options = {
vus: 10,
duration: '2s',
}; export default function () {
let res = http.get('http://www.baidu.com');
console.log('log')
console.info('info');
console.error('err');
console.debug('debug')
console.warn('warn')
}

输出到文件,输出到文件的同时控制台不在输出。

k6 run  test.js --console-output=test.log

InfluxDB + Grafana 可视化测试结果


Docker 启动 InfluxDB

docker pull tutum/influxdb
# 8083是influxdb的web管理工具端口,8086是influxdb的HTTP API端口
docker run -d -p 8083:8083 -p8086:8086 --expose 8090 --expose 8099 --name influxsrv tutum/influxdb

Docker 启动 Grafana,

docker pull grafana/grafana

docker run -d -p 3000:3000 grafana/grafana

新建一个 K6test 数据库,访问 "http://xxxxx:8083" InfluxDB web 管理页面,新建一个 K6test 数据库

配置 Grafana 数据源

选择 InfluxDB

填写域名端口和数据库,点击 sava&test 。出现 Data source is working 表示成功,如遇到问题查看一下端口是否放行。

导入仪表盘

通过 ID 导入,输入 2587 点击 load 数据源选择 InfluxDB 点击 Import

官方还有几款仪表盘

将 K6 的测试指标导入到 InfluxDB

k6 run --out influxdb=http://xxxxx:8086/K6test test.js

效果图

总结


动手实践了一下 K6 , 作为一款全面高效的性能测试工具,功能远远不止这些,需要在工作中不断的去挖掘。

使用 K6 来给你的服务做一次负载和压力测试吧的更多相关文章

  1. Jmeter做压力测试的心得

    什么是性能压测? 也是最近刚刚接触到,就是被测试的系统,在一定的访问压力下,看程序运行是否稳定/服务器运行是否稳定,通常情况,是模拟多个请求同时 请求服务器,也就是在某个时间内,比如说1秒内,调用接口 ...

  2. (转)学习使用Jmeter做压力测试(一)--压力测试基本概念

    一.性能测试的概念 性能测试是通过自动化的测试工具模拟多种正常峰值及异常负载条件来对系统的各项性能指标进行测试.负载测试和压力测试都属于性能测试,两者可以结合进行. 通过负载测试,确定在各种工作负载下 ...

  3. SpringCloud学习系列之二 ----- 服务消费者(Feign)和负载均衡(Ribbon)使用详解

    前言 本篇主要介绍的是SpringCloud中的服务消费者(Feign)和负载均衡(Ribbon)功能的实现以及使用Feign结合Ribbon实现负载均衡. SpringCloud Feign Fei ...

  4. Webbench、ab命令:做压力测试的工具和性能的监控工具

    DDOS攻击:???DDOS概述:分布式拒绝服务(DDoS:Distributed Denial of Service)攻击,指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目 ...

  5. Linux学习13-CentOS安装ab做压力测试

    前言 网站性能压力测试是服务器网站性能调优过程中必不可缺少的一,测试环境准备好了后,如何对网站做压力测试? 压力测试的工具很多,如:ab.http_load.webbench.siege.jmeter ...

  6. 基于marathon-lb的服务自发现与负载均衡

    参考文档: Marathon-lb介绍:https://docs.mesosphere.com/1.9/networking/marathon-lb/ 参考:http://www.cnblogs.co ...

  7. [Jmeter]用Jmeter做压力测试(分布式)

    Jmeter 是Java应用,对于CPU和内存的消耗比较大,因此,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至会引起JAVA内存溢出错误.为了让jmeter工具提 ...

  8. 【转】学习使用Jmeter做压力测试(一)--压力测试基本概念

    一.性能测试的概念 性能测试是通过自动化的测试工具模拟多种正常峰值及异常负载条件来对系统的各项性能指标进行测试.负载测试和压力测试都属于性能测试,两者可以结合进行. 通过负载测试,确定在各种工作负载下 ...

  9. windows网络服务之配置网络负载均衡(NLB)群集

    O首页51CTO博客我的博客 搜索 每日博报 社区:学院论坛博客下载更多            登录注册 家园 学院 博客 论坛 下载 自测 门诊 周刊 读书 技术圈 曾垂鑫的技术专栏 http:// ...

随机推荐

  1. win10家庭版升级 到win10企业版

    成功升级3小时  20200124 拿到电脑 win10家庭版 不会用 找admin都找不到只能用企业版 升级win10家庭版 到win10企业版 在msdn下载win10企业版iso iso 文件管 ...

  2. jenkins部署vue项目

    一.新建自由风格的项目 二.配置项目 三.部分部署脚本 #!/bin/bashecho $PATHnpm config set proxy nullnpm config set https-proxy ...

  3. Unity3d无法导入TensorFlowSharp plugin包问题

    环境: unity3d:2018.3.0.f2 版本 解决方法: TensorFlowSharp 仍然属于测试版本. 因此,需要将Unity3d 转到测试版本. (1)点击 File > Bui ...

  4. TVM将深度学习模型编译为WebGL

    使用TVM将深度学习模型编译为WebGL TVM带有全新的OpenGL / WebGL后端! OpenGL / WebGL后端 TVM已经瞄准了涵盖各种平台的大量后端:CPU,GPU,移动设备等.这次 ...

  5. GStreamer 1.0 series序列示例

    GStreamer 1.0 series序列示例 OpenEmbedded layer for GStreamer 1.0 这layer层为GStreamer 1.0框架提供了非官方的支持,用于Ope ...

  6. kali2020.4中安装nessus 8.14.0

    1.下载软件包 官网下载地址:https://www.tenable.com/downloads/nessus 2.安装nessus dpkg -i /root/Nessus-8.14.0-debia ...

  7. python-selenium 引入包或者类的清晰写法

    #cording=gbk#一般最上面放系统自带的包或者类import os import time##第二层放第三方下载的包或者类from selenium import webdriverfrom ...

  8. 【SQLite】教程02-SQLite命令

    获取帮助 sqlite> .help 获得以下帮助: 命令 描述 .backup ?DB? FILE 备份 DB 数据库(默认是 "main")到 FILE 文件. .bai ...

  9. SpringBoot面试题 (史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  10. 终于放弃了单调的swagger-ui了,选择了这款神器—knife4j

    knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案(在非Java项目中也提供了前端UI的增强解决方案),前身是swagger-bootstrap-ui,取名knife ...