性能测试
在上一节中,您创建了一个可工作的脚本来测试端点功能。下一步是测试该系统在负载下的响应情况。这需要设置一些 options
来配置与测试逻辑无关的测试部分。
在本教程中,您将学习如何
- 使用阈值 (thresholds) 来断言性能标准
- 通过场景 (scenarios) 配置负载增加
这些示例基于上一节中的脚本。
背景: 满足服务水平目标
为了评估登录端点的性能,您的团队可能已经定义了服务水平目标 (service level objectives) (SLOs)。例如
- 99% 的请求应该成功
- 99% 的请求延迟应该小于或等于 1000ms
服务必须在不同类型的正常流量下满足这些 SLO。
通过阈值断言性能
为了规范化 SLO,添加阈值 (thresholds) 来测试您的系统是否符合其目标标准。
阈值在options
对象中设置。
export const options = {
// define thresholds
thresholds: {
http_req_failed: ['rate<0.01'], // http errors should be less than 1%
http_req_duration: ['p(99)<1000'], // 99% of requests should be below 1s
},
};
将包含阈值的 options
对象添加到您的脚本 api-test.js
中。
// import necessary modules
import { check } from 'k6';
import http from 'k6/http';
// define configuration
export const options = {
// define thresholds
thresholds: {
http_req_failed: ['rate<0.01'], // http errors should be less than 1%
http_req_duration: ['p(99)<1000'], // 99% of requests should be below 1s
},
};
export default function () {
// define URL and request body
const url = 'https://quickpizza.grafana.com/api/users/token/login';
const payload = JSON.stringify({
username: 'default',
password: '1234',
});
const params = {
headers: {
'Content-Type': 'application/json',
},
};
// send a post request and save response as a variable
const res = http.post(url, payload, params);
// check that response is 200
check(res, {
'response code was 200': (res) => res.status == 200,
});
}
运行测试。
k6 run api-test.js
检查控制台输出,确定性能是否超过了阈值。
█ THRESHOLDS
http_req_duration
✓ 'p(99)<1000' p(99)=148.21ms
http_req_failed
✗ 'rate<0.01' rate=20.%
✓ 和 ✗ 符号表示性能阈值是否通过或失败。
在不断增加的负载下测试性能
现在您的脚本包含了模拟用户行为的逻辑,以及对功能(检查 checks)和性能(阈值 thresholds)的断言。
现在是时候增加负载以查看其性能了。要增加负载,请使用 scenarios 属性。Scenarios 根据虚拟用户数 (VUs)、迭代次数、VUs 或迭代率来安排负载。
运行冒烟测试
从小开始。运行一个冒烟测试 (smoke test)(一个小型测试,用于确认脚本能正常工作),检查您的脚本是否可以处理最小负载。
要做到这一点,使用--iterations
标志,参数设置为 10 或更少。
k6 run --iterations 10 api-test.js
如果服务无法接收 10 次迭代,则系统存在一些严重的性能问题需要调试。幸好您提早运行了测试!
运行中等负载测试
通常情况下,流量不会一次全部到达。相反,它会逐渐增加到峰值负载。为了模拟这一点,测试人员会分阶段 (stages) 增加负载。
将以下 scenario
属性添加到您的 options
对象中,然后重新运行测试。
export const options = {
// define thresholds
thresholds: {
http_req_failed: ['rate<0.01'], // http errors should be less than 1%
http_req_duration: ['p(99)<1000'], // 99% of requests should be below 1s
},
// define scenarios
scenarios: {
// arbitrary name of scenario
average_load: {
executor: 'ramping-vus',
stages: [
// ramp up to average load of 20 virtual users
{ duration: '10s', target: 20 },
// maintain load
{ duration: '50s', target: 20 },
// ramp down to zero
{ duration: '5s', target: 0 },
],
},
},
};
由于这是一个学习环境,这些阶段仍然很短。冒烟测试以迭代次数定义负载,而此配置使用ramping-vus
执行器 (executor) 通过虚拟用户数和持续时间来表达负载。
不带命令行标志运行测试
k6 run api-test.js
负载较小,因此服务器应该在阈值范围内运行。但是,此测试服务器可能同时被许多 k6 学习者使用,因此结果可能不可预测。
注意
此时,最好有一个图形界面来可视化指标(metrics)随时间的推移。k6 有多种输出格式,可以作为许多可视化工具(包括开源和商业工具)的输入。有关想法,请阅读可视化 k6 结果的方法。
渐增负载直到阈值失败
最后,运行一个断点测试 (breakpoint test),探测系统的极限。在这种情况下,运行测试直到可用性(错误率)阈值被超过。
为此
- 将
abortOnFail
属性添加到http_req_failed
中。
export const options = {
// define thresholds
thresholds: {
http_req_failed: [{ threshold: 'rate<0.01', abortOnFail: true }], // http errors should be less than 1%, otherwise abort the test
http_req_duration: ['p(99)<1000'], // 99% of requests should be below 1s
},
// ...
};
- 更新
scenarios
属性,使测试渐增负载直到失败。
export const options = {
thresholds: {
http_req_failed: [{ threshold: 'rate<0.01', abortOnFail: true }],
http_req_duration: ['p(99)<1000'],
},
scenarios: {
// define scenarios
breaking: {
executor: 'ramping-vus',
stages: [
{ duration: '10s', target: 20 },
{ duration: '50s', target: 20 },
{ duration: '50s', target: 40 },
{ duration: '50s', target: 60 },
{ duration: '50s', target: 80 },
{ duration: '50s', target: 100 },
{ duration: '50s', target: 120 },
{ duration: '50s', target: 140 },
//....
],
},
},
};
以下是完整脚本。
// import necessary modules
import { check } from 'k6';
import http from 'k6/http';
// define configuration
export const options = {
// define thresholds
thresholds: {
http_req_failed: [{ threshold: 'rate<0.01', abortOnFail: true }], // availability threshold for error rate
http_req_duration: ['p(99)<1000'], // Latency threshold for percentile
},
// define scenarios
scenarios: {
breaking: {
executor: 'ramping-vus',
stages: [
{ duration: '10s', target: 20 },
{ duration: '50s', target: 20 },
{ duration: '50s', target: 40 },
{ duration: '50s', target: 60 },
{ duration: '50s', target: 80 },
{ duration: '50s', target: 100 },
{ duration: '50s', target: 120 },
{ duration: '50s', target: 140 },
//....
],
},
},
};
export default function () {
// define URL and request body
const url = 'https://quickpizza.grafana.com/api/users/token/login';
const payload = JSON.stringify({
username: 'default',
password: '1234',
});
const params = {
headers: {
'Content-Type': 'application/json',
},
};
// send a post request and save response as a variable
const res = http.post(url, payload, params);
// check that response is 200
check(res, {
'response code was 200': (res) => res.status == 200,
});
}
运行测试。
k6 run api-test.js
阈值失败了吗?如果还没有,增加一个更高目标(target)的阶段,然后重试。重复此步骤,直到阈值终止测试。
ERRO[0010] thresholds on metrics 'http_req_duration, http_req_failed' were breached; at least one has abortOnFail enabled, stopping test prematurely
下一步
在本教程中,您使用了阈值 (thresholds) 来断言性能,并使用场景 (Scenarios) 来安排不同的负载模式。要了解更多关于常用负载模式及其目标的信息,请阅读负载测试类型。
本教程的下一步将展示如何解释测试结果。这包括过滤结果和添加自定义指标。