使用 k6 下载整个网站
Downloading whole websites with k6
我目前正在评估 k6 是否符合我们的负载测试需求。我们有一个相当传统的网站架构,它使用带有 PHP 和 MySQL 数据库的 Apache 网络服务器。使用 k6 发送简单的 HTTP 请求看起来很简单,我认为我们将能够用它测试所有主要功能,因为我们不那么依赖 JavaScript 并且大多数页面都是静态的。
但是,我不确定如何处理请求返回的 HTML 中引用的资源(样式表、图像等)。我们也需要加载它们,因为这有时会导致数据库请求,这必须是负载测试的一部分。
k6 中是否有一些开箱即用的功能可以让您像浏览器一样加载所有资源?我知道 k6 NOT 呈现页面,我不需要它。我只需要请求HTML.
里面的所有资源
你基本上有两个选择,都有它们的注意事项:
Record your session - you can either export har directly from the browser as shown there or use an extension made for your browser here is firefox and chromes. Both should be usable without a k6 cloud account you just need to set them to download the har and it will automatically (and somewhat silently) download them when you hit stop. And then either use the in k6 har converter (which is deprecated, but still works) or the new har-to-k6其中一个。
如果你有很多页面 and/or 资源,这种方法特别好,如果你有单页样式的应用程序,这种方法甚至可以工作,因为它只是获取浏览器请求的 HAR然后将其转换为脚本。如果没有需要输入的动态内容 (username/password),大多数时候可以按原样使用最终脚本。
这种方法的最大问题是,如果您添加一个 css 文件,您需要重做整个练习。如果您 css/js 文件名在每次更改或类似的情况下都更改,则问题会更大。下一个方法适用于:
- 使用parseHTML然后找到您关心的元素并为它们提出请求。
import http from "k6/http";
import {parseHTML} from "k6/html";
export default function() {
const res = http.get("https://whosebug.com");
const doc = parseHTML(res.body);
doc.find("link").toArray().forEach(function (item) {
console.log(item.attr("href"));
// make http gets for it
// or added them to an array and make one batch request
});
}
会产生
NFO[0001] https://cdn.sstatic.net/Sites/Whosebug/img/favicon.ico?v=4f32ecc8f43d
INFO[0001] https://cdn.sstatic.net/Sites/Whosebug/img/apple-touch-icon.png?v=c78bd457575a
INFO[0001] https://cdn.sstatic.net/Sites/Whosebug/img/apple-touch-icon.png?v=c78bd457575a
INFO[0001] /opensearch.xml
INFO[0001] https://cdn.sstatic.net/Shared/stacks.css?v=53507c7c6e93
INFO[0001] https://cdn.sstatic.net/Sites/Whosebug/primary.css?v=d3fa9a72fd53
INFO[0001] https://cdn.sstatic.net/Shared/Product/product.css?v=c9b2e1772562
INFO[0001] /feeds
INFO[0001] https://cdn.sstatic.net/Shared/Channels/channels.css?v=f9809e9ffa90
如您所见,有些网址是相对的而非绝对的,因此您需要处理这个问题。在这个例子中只有一些是 css,所以可能需要更多的过滤。
这里的问题是你需要编写代码,如果你添加一个相对 link 或其他你需要处理它的东西。幸运的是,k6 是可编写脚本的,因此您可以重用代码 :D。
我已经按照 Михаил Стойков 的建议编写了自己的函数来加载资源。也许它可以帮助一些未来的读者。您可以设置资源的加载方式(批量或顺序获取 options.concurrentResourceLoading
)。
/**
* @param {http.RefinedResponse<http.ResponseType>} response
*/
export function getResources(response) {
const resources = [];
response
.html()
.find('*[href]:not(a)')
.each((index, element) => {
resources.push(element.attributes().href.value);
});
response
.html()
.find('*[src]:not(a)')
.each((index, element) => {
resources.push(element.attributes().src.value);
});
if (options.concurrentResourceLoading) {
const responses = http.batch(
resources.map((r) => {
return ['GET', resolveUrl(r, response.url), null, { headers: createHeader() }];
})
);
responses.forEach(() => {
check(response, {
'resource returns status 200': (r) => r.status === 200,
});
});
} else {
resources.forEach((r) => {
const res = http.get(resolveUrl(r, response.url), {
headers: createHeader(),
});
!check(res, {
'resource returns status 200': (r) => r.status === 200,
});
});
}
}
我目前正在评估 k6 是否符合我们的负载测试需求。我们有一个相当传统的网站架构,它使用带有 PHP 和 MySQL 数据库的 Apache 网络服务器。使用 k6 发送简单的 HTTP 请求看起来很简单,我认为我们将能够用它测试所有主要功能,因为我们不那么依赖 JavaScript 并且大多数页面都是静态的。
但是,我不确定如何处理请求返回的 HTML 中引用的资源(样式表、图像等)。我们也需要加载它们,因为这有时会导致数据库请求,这必须是负载测试的一部分。
k6 中是否有一些开箱即用的功能可以让您像浏览器一样加载所有资源?我知道 k6 NOT 呈现页面,我不需要它。我只需要请求HTML.
里面的所有资源你基本上有两个选择,都有它们的注意事项:
Record your session - you can either export har directly from the browser as shown there or use an extension made for your browser here is firefox and chromes. Both should be usable without a k6 cloud account you just need to set them to download the har and it will automatically (and somewhat silently) download them when you hit stop. And then either use the in k6 har converter (which is deprecated, but still works) or the new har-to-k6其中一个。
如果你有很多页面 and/or 资源,这种方法特别好,如果你有单页样式的应用程序,这种方法甚至可以工作,因为它只是获取浏览器请求的 HAR然后将其转换为脚本。如果没有需要输入的动态内容 (username/password),大多数时候可以按原样使用最终脚本。
这种方法的最大问题是,如果您添加一个 css 文件,您需要重做整个练习。如果您 css/js 文件名在每次更改或类似的情况下都更改,则问题会更大。下一个方法适用于:
- 使用parseHTML然后找到您关心的元素并为它们提出请求。
import http from "k6/http";
import {parseHTML} from "k6/html";
export default function() {
const res = http.get("https://whosebug.com");
const doc = parseHTML(res.body);
doc.find("link").toArray().forEach(function (item) {
console.log(item.attr("href"));
// make http gets for it
// or added them to an array and make one batch request
});
}
会产生
NFO[0001] https://cdn.sstatic.net/Sites/Whosebug/img/favicon.ico?v=4f32ecc8f43d
INFO[0001] https://cdn.sstatic.net/Sites/Whosebug/img/apple-touch-icon.png?v=c78bd457575a
INFO[0001] https://cdn.sstatic.net/Sites/Whosebug/img/apple-touch-icon.png?v=c78bd457575a
INFO[0001] /opensearch.xml
INFO[0001] https://cdn.sstatic.net/Shared/stacks.css?v=53507c7c6e93
INFO[0001] https://cdn.sstatic.net/Sites/Whosebug/primary.css?v=d3fa9a72fd53
INFO[0001] https://cdn.sstatic.net/Shared/Product/product.css?v=c9b2e1772562
INFO[0001] /feeds
INFO[0001] https://cdn.sstatic.net/Shared/Channels/channels.css?v=f9809e9ffa90
如您所见,有些网址是相对的而非绝对的,因此您需要处理这个问题。在这个例子中只有一些是 css,所以可能需要更多的过滤。 这里的问题是你需要编写代码,如果你添加一个相对 link 或其他你需要处理它的东西。幸运的是,k6 是可编写脚本的,因此您可以重用代码 :D。
我已经按照 Михаил Стойков 的建议编写了自己的函数来加载资源。也许它可以帮助一些未来的读者。您可以设置资源的加载方式(批量或顺序获取 options.concurrentResourceLoading
)。
/**
* @param {http.RefinedResponse<http.ResponseType>} response
*/
export function getResources(response) {
const resources = [];
response
.html()
.find('*[href]:not(a)')
.each((index, element) => {
resources.push(element.attributes().href.value);
});
response
.html()
.find('*[src]:not(a)')
.each((index, element) => {
resources.push(element.attributes().src.value);
});
if (options.concurrentResourceLoading) {
const responses = http.batch(
resources.map((r) => {
return ['GET', resolveUrl(r, response.url), null, { headers: createHeader() }];
})
);
responses.forEach(() => {
check(response, {
'resource returns status 200': (r) => r.status === 200,
});
});
} else {
resources.forEach((r) => {
const res = http.get(resolveUrl(r, response.url), {
headers: createHeader(),
});
!check(res, {
'resource returns status 200': (r) => r.status === 200,
});
});
}
}