ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

使用 k6 与 xk6-loki 对 Loki 日志查询(读路径)进行压测的完整指南

使用 k6 与 xk6-loki 对 Loki 日志查询(读路径)进行压测的完整指南 使用 k6 与 xk6-loki 对 Loki 日志查询读路径进行压测的完整指南【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki本篇技术指南围绕 Loki 读路径查询的负载测试展开讲解如何基于 Grafana k6 与 xk6-loki 扩展对 Loki 安装实例的五种查询类型instant、range、labels、label values、series进行压测。你将掌握每一种查询的 xk6-loki JavaScript API 用法、对应的 Loki HTTP 端点与底层实现原理、压测指标的含义以及如何通过标签池和查询比例配置构建接近真实场景的读路径压测脚本。前置准备构建带 xk6-loki 扩展的 k6xk6-loki是 k6 的扩展它充当 Loki 客户端既可向 Loki 推送日志也可从 Loki 查询日志从而模拟真实负载来测试 Loki 安装实例的可扩展性、可靠性与性能。在使用查询场景之前需要先构建一个包含该扩展的自定义 k6 二进制详见 k6 压测总览安装xk6扩展打包工具k6 使用 Go 编写需先准备好 Go 环境go install go.k6.io/xk6/cmd/xk6latest克隆grafana/xk6-loki仓库并进入目录git clone https://github.com/grafana/xk6-loki cd xk6-loki构建带扩展的 k6 二进制make k6构建完成后在压测脚本中通过import loki from k6/x/loki;导入模块。该模块暴露两个核心类ConfigClient的配置与Client读写 Loki 的客户端。Config和Client必须在 k6 的 init 上下文default 函数之外中实例化保证客户端只配置一次、并在所有 VU虚拟用户迭代间共享。Loki 读路径的五种查询类型在设计 Loki 读路径压测场景之前必须先明确你预期会遇到哪些类型的查询。Loki 一共有 5 种查询类型查询类型xk6-loki API对应 Loki HTTP 端点instant query瞬时查询instantQuery(query, limit)GET /loki/api/v1/queryrange query范围查询rangeQuery(query, duration, limit)GET /loki/api/v1/query_rangelabels query标签名查询labelsQuery(duration)GET /loki/api/v1/labelslabel values query标签值查询labelValuesQuery(label, duration)GET /loki/api/v1/label/name/valuesseries query序列查询seriesQuery(matcher, range)GET /loki/api/v1/series在真实场景中例如把 Loki 作为 Grafana 数据源进行查询这五类查询都会被用到且每一类都对应不同的 API 端点。xk6-loki 扩展为所有这些查询类型提供了对应的 JavaScript API。这些端点路径可以在仓库的查询路由实现中确认例如 pkg/querier/queryrange/codec.go 中注册了/loki/api/v1/query_range、/loki/api/v1/series、/loki/api/v1/query以及/loki/api/v1/label/{name}/values等路径pkg/loghttp/versions_test.go 中的测试也验证了这些路径归属于VersionV1API 版本。Instant query瞬时查询瞬时查询返回单个时间点上的查询结果通过loki.Client实例上的instantQuery(query, limit)函数执行其中limit为可选参数export default () { client.instantQuery(rate({appmy-app-name} | logfmt | levelerror [5m])); }从源码实现看瞬时查询走的是 QuerierAPI 的InstantQueryHandler见 pkg/querier/http.go。值得注意的一个细节是该处理器只允许指标查询SampleExpr不允许纯日志选择器表达式作为瞬时查询否则会返回ErrUnsupportedSyntaxForInstantQuery错误。因此在编写瞬时查询压测语句时应使用rate()、count_over_time()这类聚合/范围向量表达式而不是裸的{app...}日志选择器。Range query范围查询范围查询返回一个时间区间内的查询结果通过rangeQuery(query, duration, limit)执行duration用于指定查询的时间跨度limit为可选参数export default () { client.rangeQuery({appmy-app-name} | logfmt | levelerror, 15m); }范围查询对应的处理函数是RangeQueryHandler见 pkg/querier/http.go它是压测中最接近 Grafana 仪表盘真实查询形态的一类请求。Labels query标签名查询标签名查询返回某个时间范围内出现的所有标签名通过labelsQuery(duration)执行export default () { client.labelsQuery(10m); }Label values query标签值查询标签值查询返回指定标签在某个时间范围内的取值通过labelValuesQuery(label, duration)执行export default () { client.labelValuesQuery(app, 10m); }在 Loki 服务端标签名查询与标签值查询都由LabelHandler处理见 pkg/querier/http.go其底层通过querier.Label()查询索引并使用logql.QueryTime中QueryTypeLabels类别的计时器记录耗时。Series query序列查询序列查询返回与某个标签匹配器匹配的时间序列列表通过seriesQuery(matcher, range)执行export default () { client.seriesQuery(match[]{app~loki-.*}, 10m); }注意示例中match[]前缀用于传递标签匹配器。服务端对应的处理函数是SeriesHandler见 pkg/querier/http.go其注释明确说明该端点返回“匹配特定标签集的 time series 列表”并引用 Prometheus 的 Finding series by label matchers API 语义。压测指标Metricsxk6-loki 扩展会额外收集以下指标并打印在 k6 测试结束时的 end-of-test summary 中与 k6 内置指标并列展示。这些指标仅为 instant query 和 range query 收集指标名称说明loki_bytes_processed_per_secondLoki 每秒处理的字节数loki_bytes_processed_totalLoki 处理的字节总数loki_lines_processed_per_secondLoki 每秒处理的行数loki_lines_processed_totalLoki 处理的行总数这些指标来自 Loki 查询响应中携带的统计信息stats直接反映读路径上 Loki 实际扫描与处理的数据量是评估查询压测是否真正打满存储与计算资源的关键依据。标签池Labels poolxk6-loki 允许你在Config对象上使用labels字段它包含以可复现方式生成的标签名与标签值集合。压测时应保证write写入测试与read读取测试使用相同的标签基数配置这样才能保证读路径压测命中的流streams确实存在于被压测的 Loki 实例中压测结果才具有真实参考意义。JavaScript 示例代码片段const labelCardinality { app: 5, namespace: 2, }; const conf new loki.Config(BASE_URL, 10000, 1.0, labelCardinality); const client new loki.Client(conf); function randomChoice(items) { return items[Math.floor(Math.random() * items.length)]; } export default() { let app randomChoice(conf.labels.app); let namespace randomChoice(conf.labels.namespace); client.rangeQuery({app${app}, namespace${namespace}} | logfmt | levelerror, 15m); }这里new loki.Config(BASE_URL, timeout, ratio, labelCardinality)的第二个参数是请求超时毫秒第三个参数是 Protobuf 编码请求占比0.0~1.0默认 0.9详见 log-generation.md第四个参数即标签基数。由于标签值是确定性地生成每次压测产生相同的标签名与取值组合从而保证测试可复现、可对比。除此之外你也可以自定义自己的标签名与标签值池然后从自己的池中随机选择标签而不是使用生成的池。这在高保真模拟生产环境标签分布时非常有用。需要提醒的是不同标签值的笛卡尔积决定了活跃流streams的总量标签基数过高会对 Loki 实例性能产生负面影响详见 log-generation.md 中的标签说明压测时应从较小的基数起步。综合读场景按比例混合五种查询在 xk6-loki 仓库中提供了一个更完整的读场景示例read-scenario.js测试文件可直接复用并扩展。它允许你为每种查询类型配置比例也可以配置时间范围的比例。JavaScript 示例const queryTypeRatioConfig [ { ratio: 0.1, item: readLabels }, { ratio: 0.15, item: readLabelValues }, { ratio: 0.05, item: readSeries }, { ratio: 0.5, item: readRange }, { ratio: 0.2, item: readInstant }, ];在上述配置下一次压测运行期间大约会执行10% 的 labels 请求15% 的 label values 请求5% 的 series 请求50% 的 range 查询20% 的 instant 查询这种按比例混合的方式能很好地模拟 Grafana 面板加载、变量刷新、日志流切换等真实交互行为——例如 Grafana 变量下拉框会触发 labels 与 label values 查询日志浏览与面板会触发 range/instant 查询。你可以参考 write-scenario.md 中的完整脚本骨架包含ramping-vus场景、thresholds、check断言等要素将上述比例配置嵌入其中构建读写一体的压测流程。压测实战建议明确目标查询画像压测前先梳理你的 Grafana 数据源或其他客户端实际发出的查询构成类型占比、时间范围、标签基数再据此设置queryTypeRatioConfig避免只压单一查询类型导致结论失真。控制标签基数从少量标签值起步例如app5 个、namespace2 个确认集群能承受后再逐步放大因为高基数标签会显著影响索引与查询性能。关注处理指标而非仅看延迟loki_bytes_processed_per_second与loki_lines_processed_per_second能直观反映读路径实际吞吐结合 k6 内置的http_req_duration、http_req_failed等指标才能全面评估查询性能与稳定性。读写压测保持一致读路径命中的流必须由写路径产生务必让 read 与 write 测试共享相同的labelCardinality配置必要时可先运行写场景预热数据再进行读场景压测。VU 数量与资源匹配与写路径类似读路径压测中 VU 数量决定了并发查询压力可根据 k6 工作机 CPU 核数经验上 1~1.5 倍核数设置 VU 上限避免压测机自身成为瓶颈详见 write-scenario.md 的讨论。通过上述方法你可以在本地或 CI 环境中复现接近真实的查询负载系统性地评估 Loki 读路径在预期查询画像下的吞吐、延迟与资源消耗为容量规划与性能调优提供可靠依据。【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表