使用 loadimpact k6 对使用 oauth 令牌进行授权的 API 进行负载测试
Load testing an API which uses oauth token for authorization using loadimpact k6
我正在尝试使用 loadimpact k6 对 API(GET 方法)进行负载测试,这需要 oauth 令牌进行授权才能获得成功的响应。我已经有一个邮递员收集文件,它通过 运行 预请求脚本执行此操作。预请求脚本将从授权服务器请求令牌,然后将令牌填充到环境变量中。我使用 "Postman to LoadImpact converter" 生成了 k6 脚本,但它没有任何帮助。脚本无法获取访问令牌。
转换器生成的脚本如下:
// Auto-generated by the Load Impact converter
import "./libs/shim/core.js";
export let options = { maxRedirects: 4 };
const Request = Symbol.for("request");
postman[Symbol.for("initial")]({
options,
collection: {
currentAccessToken: "",
"Client-Id": "",
"Client-Secret": "",
"Token-Scope": "",
"Grant-Type": "client_credentials",
"Access-Token-URL": "",
accessTokenExpiry: ""
}
});
export default function() {
postman[Request]({
name: "Collection Mock",
id: "",
method: "GET",
address:
"",
headers: {
Authorization: "Bearer {{currentAccessToken}}"
},
pre() {
const echoPostRequest = {
url: pm.environment.get("Access-Token-URL"),
method: "POST",
header: "Content-Type:x-www-form-urlencoded",
body: {
mode: "urlencoded",
urlencoded: [
{ key: "client_id", value: pm.environment.get("Client-Id") },
{
key: "client_secret",
value: pm.environment.get("Client-Secret")
},
{ key: "grant_type", value: pm.environment.get("Grant-Type") },
{ key: "scope", value: pm.environment.get("Token-Scope") }
]
}
};
var getToken = true;
if (
!pm.environment.get("accessTokenExpiry") ||
!pm.environment.get("currentAccessToken")
) {
console.log("Token or expiry date are missing");
} else if (
pm.environment.get("accessTokenExpiry") <= new Date().getTime()
) {
console.log("Token is expired");
} else {
getToken = false;
console.log("Token and expiry date are all good");
}
if (getToken === true) {
pm.sendRequest(echoPostRequest, function(err, res) {
console.log(err ? err : res.json());
if (err === null) {
console.log("Saving the token and expiry date");
var responseJson = res.json();
pm.environment.set("currentAccessToken", responseJson.access_token);
var expiryDate = new Date();
expiryDate.setSeconds(
expiryDate.getSeconds() + responseJson.expires_in
);
pm.environment.set("accessTokenExpiry", expiryDate.getTime());
}
});
}
}
});
}
问题出在转换器不支持的 pm.sendRequest 上,我不确定替代方案是什么。因此,我正在寻找从授权服务器动态请求访问令牌并使用该令牌向 API 发出请求以在 k6 脚本中进行负载测试的方法。
如您所见,不支持 sendRequest
...
这主要是因为 pm.sendRequest is asynchronous but k6 at this point doesn't have a event loop so ... no asynchronous http calls :( (except with http.batch 但...不是
我发现你不太可能希望它是异步的,或者......好吧你现在不能用 k6 来做......你可以重写它以使用 k6's http.post
据我所知,这应该是
pre() {
var getToken = true;
if (
!pm.environment.get("accessTokenExpiry") ||
!pm.environment.get("currentAccessToken")
) {
console.log("Token or expiry date are missing");
} else if (
pm.environment.get("accessTokenExpiry") <= new Date().getTime()
) {
console.log("Token is expired");
} else {
getToken = false;
console.log("Token and expiry date are all good");
}
if (getToken === true) {
let res = http.post(pm.environment.get("Access-Token-URL"), {
"client_id": pm.environment.get("Client-Id") ,
"client_secret": pm.environment.get("Client-Secret"),
"grant_type": pm.environment.get("Grant-Type"),
"scope": pm.environment.get("Token-Scope")
});
console.log(err ? err : res.json());
if (err === null) {
console.log("Saving the token and expiry date");
var responseJson = res.json();
pm.environment.set("currentAccessToken", responseJson.access_token);
var expiryDate = new Date();
expiryDate.setSeconds(
expiryDate.getSeconds() + responseJson.expires_in
);
pm.environment.set("accessTokenExpiry", expiryDate.getTime());
}
}
免责声明:我从未使用过邮递员,上面的代码是 written/copy-pasted 手工编写的,未经测试:)
我最终使用以下代码片段成功调用了我的目的:
// Auto-generated by the Load Impact converter
import "./libs/shim/core.js";
import http from "k6/http";
import { check, sleep } from "k6";
export let options = {
max_vus: 10,
vus: 10,
stages: [
{ duration: "1m", target: 10 }
]
}
const Request = Symbol.for("request");
pm.environment.set("currentAccessToken", "");
pm.environment.set("accessTokenExpiry", "");
pm.environment.set("clientId", "");
pm.environment.set("clientSecret", "");
pm.environment.set("tokenScope", "");
pm.environment.set("grantType", "");
pm.environment.set("accesstokenUrl", "");
pm.environment.set("apiUrl", "");
pm.environment.set("subscriptionKeys", "");
export default function() {
var getToken = true;
if (!pm.environment.get("accessTokenExpiry") || !pm.environment.get("currentAccessToken")) {
//console.log("Token or expiry date are missing");
} else if (pm.environment.get("accessTokenExpiry") <= new Date().getTime()) {
//console.log("Token is expired");
} else {
getToken = false;
//console.log("Token and expiry date are all good");
}
if (getToken === true) {
//get the access token first
let res = http.post(pm.environment.get("accesstokenUrl"), {
"client_id": pm.environment.get("clientId"),
"client_secret": pm.environment.get("clientSecret"),
"grant_type": pm.environment.get("grantType"),
"scope": pm.environment.get("tokenScope")
});
var checkRes = check(res, {
"Token Request status is 200": (r) => r.status === 200,
});
if (checkRes) {
var responseJson = res.json();
pm.environment.set("currentAccessToken", responseJson.access_token);
var expiryDate = new Date();
expiryDate.setSeconds(
expiryDate.getSeconds() + responseJson.expires_in
);
pm.environment.set("accessTokenExpiry", expiryDate.getTime());
}
sleep(1);
//make the api request using the access token and subscription keys (if required)
let apiRes = http.get(pm.environment.get("apiUrl"),
{
headers: { "Authorization": "Bearer " + pm.environment.get("currentAccessToken"),
"Subscription-Key" : pm.environment.get("subscriptionKeys")
}
});
check(apiRes, {
"API Request status is 200": (res) => res.status === 200
});
sleep(3);
}
}
我正在尝试使用 loadimpact k6 对 API(GET 方法)进行负载测试,这需要 oauth 令牌进行授权才能获得成功的响应。我已经有一个邮递员收集文件,它通过 运行 预请求脚本执行此操作。预请求脚本将从授权服务器请求令牌,然后将令牌填充到环境变量中。我使用 "Postman to LoadImpact converter" 生成了 k6 脚本,但它没有任何帮助。脚本无法获取访问令牌。
转换器生成的脚本如下:
// Auto-generated by the Load Impact converter
import "./libs/shim/core.js";
export let options = { maxRedirects: 4 };
const Request = Symbol.for("request");
postman[Symbol.for("initial")]({
options,
collection: {
currentAccessToken: "",
"Client-Id": "",
"Client-Secret": "",
"Token-Scope": "",
"Grant-Type": "client_credentials",
"Access-Token-URL": "",
accessTokenExpiry: ""
}
});
export default function() {
postman[Request]({
name: "Collection Mock",
id: "",
method: "GET",
address:
"",
headers: {
Authorization: "Bearer {{currentAccessToken}}"
},
pre() {
const echoPostRequest = {
url: pm.environment.get("Access-Token-URL"),
method: "POST",
header: "Content-Type:x-www-form-urlencoded",
body: {
mode: "urlencoded",
urlencoded: [
{ key: "client_id", value: pm.environment.get("Client-Id") },
{
key: "client_secret",
value: pm.environment.get("Client-Secret")
},
{ key: "grant_type", value: pm.environment.get("Grant-Type") },
{ key: "scope", value: pm.environment.get("Token-Scope") }
]
}
};
var getToken = true;
if (
!pm.environment.get("accessTokenExpiry") ||
!pm.environment.get("currentAccessToken")
) {
console.log("Token or expiry date are missing");
} else if (
pm.environment.get("accessTokenExpiry") <= new Date().getTime()
) {
console.log("Token is expired");
} else {
getToken = false;
console.log("Token and expiry date are all good");
}
if (getToken === true) {
pm.sendRequest(echoPostRequest, function(err, res) {
console.log(err ? err : res.json());
if (err === null) {
console.log("Saving the token and expiry date");
var responseJson = res.json();
pm.environment.set("currentAccessToken", responseJson.access_token);
var expiryDate = new Date();
expiryDate.setSeconds(
expiryDate.getSeconds() + responseJson.expires_in
);
pm.environment.set("accessTokenExpiry", expiryDate.getTime());
}
});
}
}
});
}
问题出在转换器不支持的 pm.sendRequest 上,我不确定替代方案是什么。因此,我正在寻找从授权服务器动态请求访问令牌并使用该令牌向 API 发出请求以在 k6 脚本中进行负载测试的方法。
如您所见,不支持 sendRequest
...
这主要是因为 pm.sendRequest is asynchronous but k6 at this point doesn't have a event loop so ... no asynchronous http calls :( (except with http.batch 但...不是 我发现你不太可能希望它是异步的,或者......好吧你现在不能用 k6 来做......你可以重写它以使用 k6's http.post
据我所知,这应该是
pre() {
var getToken = true;
if (
!pm.environment.get("accessTokenExpiry") ||
!pm.environment.get("currentAccessToken")
) {
console.log("Token or expiry date are missing");
} else if (
pm.environment.get("accessTokenExpiry") <= new Date().getTime()
) {
console.log("Token is expired");
} else {
getToken = false;
console.log("Token and expiry date are all good");
}
if (getToken === true) {
let res = http.post(pm.environment.get("Access-Token-URL"), {
"client_id": pm.environment.get("Client-Id") ,
"client_secret": pm.environment.get("Client-Secret"),
"grant_type": pm.environment.get("Grant-Type"),
"scope": pm.environment.get("Token-Scope")
});
console.log(err ? err : res.json());
if (err === null) {
console.log("Saving the token and expiry date");
var responseJson = res.json();
pm.environment.set("currentAccessToken", responseJson.access_token);
var expiryDate = new Date();
expiryDate.setSeconds(
expiryDate.getSeconds() + responseJson.expires_in
);
pm.environment.set("accessTokenExpiry", expiryDate.getTime());
}
}
免责声明:我从未使用过邮递员,上面的代码是 written/copy-pasted 手工编写的,未经测试:)
我最终使用以下代码片段成功调用了我的目的:
// Auto-generated by the Load Impact converter
import "./libs/shim/core.js";
import http from "k6/http";
import { check, sleep } from "k6";
export let options = {
max_vus: 10,
vus: 10,
stages: [
{ duration: "1m", target: 10 }
]
}
const Request = Symbol.for("request");
pm.environment.set("currentAccessToken", "");
pm.environment.set("accessTokenExpiry", "");
pm.environment.set("clientId", "");
pm.environment.set("clientSecret", "");
pm.environment.set("tokenScope", "");
pm.environment.set("grantType", "");
pm.environment.set("accesstokenUrl", "");
pm.environment.set("apiUrl", "");
pm.environment.set("subscriptionKeys", "");
export default function() {
var getToken = true;
if (!pm.environment.get("accessTokenExpiry") || !pm.environment.get("currentAccessToken")) {
//console.log("Token or expiry date are missing");
} else if (pm.environment.get("accessTokenExpiry") <= new Date().getTime()) {
//console.log("Token is expired");
} else {
getToken = false;
//console.log("Token and expiry date are all good");
}
if (getToken === true) {
//get the access token first
let res = http.post(pm.environment.get("accesstokenUrl"), {
"client_id": pm.environment.get("clientId"),
"client_secret": pm.environment.get("clientSecret"),
"grant_type": pm.environment.get("grantType"),
"scope": pm.environment.get("tokenScope")
});
var checkRes = check(res, {
"Token Request status is 200": (r) => r.status === 200,
});
if (checkRes) {
var responseJson = res.json();
pm.environment.set("currentAccessToken", responseJson.access_token);
var expiryDate = new Date();
expiryDate.setSeconds(
expiryDate.getSeconds() + responseJson.expires_in
);
pm.environment.set("accessTokenExpiry", expiryDate.getTime());
}
sleep(1);
//make the api request using the access token and subscription keys (if required)
let apiRes = http.get(pm.environment.get("apiUrl"),
{
headers: { "Authorization": "Bearer " + pm.environment.get("currentAccessToken"),
"Subscription-Key" : pm.environment.get("subscriptionKeys")
}
});
check(apiRes, {
"API Request status is 200": (res) => res.status === 200
});
sleep(3);
}
}