使用 k6 下载整个网站
Posted
技术标签:
【中文标题】使用 k6 下载整个网站【英文标题】:Downloading whole websites with k6 【发布时间】:2020-03-30 09:33:16 【问题描述】:我目前正在评估 k6 是否适合我们的负载测试需求。我们有一个相当传统的网站架构,它使用带有 php 和 mysql 数据库的 Apache 网络服务器。使用 k6 发送简单的 HTTP 请求看起来很简单,我认为我们将能够使用它测试所有主要功能,因为我们不那么依赖 javascript,而且大多数页面都是静态的。
但是,我不确定如何处理请求中返回的 html 中引用的资源(样式表、图像等)。我们也需要加载它们,因为这有时会导致数据库请求,这必须是负载测试的一部分。
k6 中是否有一些开箱即用的功能,可以让您像浏览器一样加载所有资源?我知道 k6 确实 NOT 呈现页面,我不需要它。我只需要请求 HTML 中的所有资源。
【问题讨论】:
【参考方案1】:您基本上有两个选择,都有各自的注意事项:
Record your session - 您可以直接从浏览器中导出 har,如图所示,或者在您的浏览器中使用 extension made,这里是 firefox 和 chromes。两者都应该可以在没有 k6 云帐户的情况下使用,您只需将它们设置为下载 har,当您点击停止时它会自动(并且有点静默)下载它们。然后使用 in k6 har 转换器(已弃用,但仍然有效)或新的 har-to-k6 一个。
如果你有很多页面和/或资源,这个方法特别好,如果你有一个单一页面样式的应用程序,它甚至可以工作,因为它只是获取浏览器请求的HAR,然后将其转换为脚本。如果没有需要输入的动态内容(用户名/密码),则大多数情况下都可以使用最终脚本。
这种方法最大的问题是,如果你添加了一个 css 文件,你需要重做整个练习。如果您在每次更改时更改 css/js 文件名或类似的东西,这将更加成问题。下一个方法有什么好处:
使用parseHTML,然后找到您关心的元素并提出请求。import http from "k6/http";
import parseHTML from "k6/html";
export default function()
const res = http.get("https://***.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/***/img/favicon.ico?v=4f32ecc8f43d
INFO[0001] https://cdn.sstatic.net/Sites/***/img/apple-touch-icon.png?v=c78bd457575a
INFO[0001] https://cdn.sstatic.net/Sites/***/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/***/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,所以可能需要更多的过滤。 这里的问题是您需要编写代码,并且如果您添加相对链接或其他内容,您需要处理它。幸运的是,k6 是可编写脚本的,因此您可以重用代码:D。
【讨论】:
【参考方案2】:我遵循了 Михаил Стойков 的建议并编写了自己的函数来加载资源。也许它可以帮助一些未来的读者。您可以设置资源的加载方式(使用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,
);
);
【讨论】:
这缺少很多定义,例如resolveUrl
和 createHeader
。以上是关于使用 k6 下载整个网站的主要内容,如果未能解决你的问题,请参考以下文章