← 返回
AI技术

用 Grafana k6 在 AWS 上做 API 压测,AI 自动生成测试报告

✍️ zhirenhun 📅 2026/10/26 👁 105 阅读 ⏱ 37 分钟
用 Grafana k6 在 AWS 上做 API 压测,AI 自动生成测试报告

1. 引言

开发应用或服务时,我们常常会问:它能承受多少并发请求?它依赖的服务又会有怎样的响应?即使验证了所有功能都正常运行,也不能保证随着需求增长,系统依然能保持原有的性能。

正因如此,软件测试不能只停留在验证功能需求上,还要评估性能、稳定性和响应速度等方面。尤其是负载测试,目的并非把系统压到崩溃为止,而是弄清系统在各种条件下的表现,找出它在什么时候开始无法满足预期要求。

在上一篇文章中,我们使用 Amazon Bedrock、S3 Vectors 和 DynamoDB 构建了一个识别重复商品的服务,其中包含一个执行实时搜索的 AWS Lambda 函数。初步测试时,服务能在几秒内响应,但还有一个问题悬而未决:如果大量用户同时访问,它会表现如何?

为了回答这个问题,在第二部分中,我们将通过 Amazon API Gateway 把服务暴露出去,并评估它在负载下的表现。不过在跑测试之前,得先明确我们要测量什么、用什么标准来评估结果。为此,我们会介绍一些站点可靠性工程(SRE)的基础概念。接下来,我们将在 AWS 上用 Grafana k6 自动化负载测试,最后生成一份报告,由生成式 AI 帮我们解读收集到的指标。


2. 认识站点可靠性工程(SRE)

2.1. SRE 是什么?

在评估 API 的负载表现之前,我们需要先明确:什么样的性能和可靠性才算合格。一个服务也许还在持续响应请求,但这并不一定意味着它达到了预期的性能要求。

这时,站点可靠性工程(SRE)就派上用场了。SRE最早由Google提出,其核心是把软件工程的方法运用到系统的运行和维护中,以保障系统可靠性。它强调定义可量化的目标、选取能够真实反映服务状态的指标,并通过自动化来减少重复性的运维工作。
在我们的场景中,这些理念让我们不再局限于“API是否能响应”这种简单判断,而是可以进一步评估响应时间、错误率以及不同负载条件下的性能表现等具体指标。


2.2. SRE的七大原则

SRE建立在一系列原则之上,指导我们如何设计、运维和维护可靠的服务。这些原则涵盖可靠性目标的设定、风险管理、自动化、监控,以及尽量保持系统简洁等方面。
下面的信息图基于Google的《Site Reliability Engineering》一书,总结了其中的七项原则。


Illustration by the author. Based on Google's Site Reliability Engineering book.


2.3. 容量规划与性能

服务的可靠性不仅取决于可用性,还取决于能否在保持可接受性能的前提下应对需求。为此,SRE包含多项实践,旨在提前发现问题、优化资源利用,并降低生产环境变更带来的影响。

其中值得关注的实践包括:


2.4. SLI、SLO 和 SLA

评估服务的容量和性能,不能只是跑跑测试、收集指标就够了。我们还需要明确要测量什么,以及哪些服务水平是可以接受的。

在这一点上,SRE 引入了三个相互关联的概念:SLI(服务水平指标)、SLO(服务水平目标)和 SLA(服务水平协议)。三者共同把技术指标与服务目标和承诺连接起来。

下面的信息图总结了每个概念的含义、它能回答的问题,以及一个实际应用示例。

这张技术文章配图描述了SLI、SLO和SLA的定义和含义

Illustration by the author. Based on Google's SRE framework.


3. Grafana k6:性能测试工具

Grafana k6 是由 Grafana Labs 用 Go 语言开发并维护的开源工具,用于对应用、API 和微服务进行负载与性能测试。测试场景用 JavaScript 定义,因此更容易实现测试自动化,并将其集成到开发工作流中。

虽然我们常把这类工具和压力测试画上等号,但 k6 其实可以评估系统在不同负载条件下的表现,而不一定要把系统压到崩溃为止。


Illustration by the author. Based on Grafana k6 documentation.


3.1. 负载测试的类型

根据评估目标的不同,可以定义各种测试场景:


3.2. k6 的核心组件

要执行这些测试,k6 提供了若干组件,用于配置负载、校验响应、收集指标,并将结果与其他工具集成。


Illustration by the author. Based on Grafana k6 documentation.

这些组件可以归纳为四大类:


4. 架构

我们的负载测试方案建立在上一篇文章开发的game-catalog-resolve-product Lambda 函数之上,该函数借助 Amazon Bedrock、S3 Vectors 和 DynamoDB 来识别重复商品。

在本系列的第二部分,我们通过Amazon API Gateway(HTTP API)将函数暴露出去,并采用 IAM 授权,因此 k6 发起的请求需要用 AWS 凭证进行签名。

整个测试流程通过 AWS Step Functions 实现自动化:由它编排 Amazon ECS Fargate 上的 k6 执行,再调用 AWS Lambda 函数生成报告。测试脚本和结果存放在 Amazon S3 中,容器镜像则保存在 Amazon ECR 里。

全部基础设施均使用 Terraform 定义,代码托管在 GitHub 上,方案可随时复现。


架构图由作者绘制。


5. 使用案例:自动化负载测试

在这个案例中,我们将对 API 运行多种负载测试场景。为此,我们使用 Grafana k6 在 Docker 容器中发送请求并收集性能指标。测试完成后,一个基于 Python 的流程会计算结果,并生成一份 PDF 报告,其中包含由 Amazon Bedrock 提供的解读说明。


插图由作者绘制。


5.1. 代码仓库

该项目已发布在 GitHub 上:game-catalog-k6。

⚡ 在 AWS 上实现自动化 API 负载测试:Grafana k6 + Amazon Bedrock 智能报告

这是一个无服务器流水线,通过 AWS Step Functions 编排,在 Amazon ECS Fargate 上运行 Grafana k6 对 API 进行负载测试,并生成 PDF 报告,其中指标由 Amazon Bedrock 解读。所有基础设施均使用 Terraform 定义。

📝 文章: 🔗 第一部分(被测 API): 相同还是相似?基于 Amazon Bedrock 和 S3 Vectors 的 AI 商品匹配 · 代码仓库


🎯 它能做什么

  1. 运行负载测试:在 ECS Fargate 容器中用 k6 执行可配置场景(冒烟、负载、压力、尖峰)。
  2. 存储每次运行:每次测试都保存在独立的 S3 文件夹中,包含结果以及所用场景的完整副本。
  3. 生成 PDF 报告:指标由代码计算,Amazon Bedrock 只负责解读,其引用的数字会与计算结果进行校验。

关于阈值设定……


项目结构包括 k6 脚本、测试场景、报告生成器,以及用 Terraform 定义的基础设施。
game-catalog-k6/
├── Dockerfile, entrypoint.sh
├── search.js, sigv4.js
├── scenarios/
├── queries.json
├── report/
│   └── config/
├── terraform/
└── build-and-push.sh

我们的目标是让这套方案可以直接复用于测试其他 API,无需改动底层基础设施或报告生成流程。为此,只需配置三个要素:


5.2. 为另一个 API 配置测试

1. 确定目标 API:api_id

本例中使用 Amazon API Gateway(HTTP API)并结合 IAM 授权,服务 URL 的结构如下:

https://<api-id>.execute-api.us-east-1.amazonaws.com

API标识符可以在AWS管理控制台中找到,路径是API Gateway→你的API→API details。
要配置项目,我们在terraform/terraform.tfvars中指定它:

api_id = "<api-id>"

Terraform 会用这个标识符来构造 API URL,并配置必要的权限,让 k6 容器能通过 IAM 签名请求调用该 API。


2. 定义请求:queries.json

确定了要测试的 API 之后,接下来就要明确要发送哪些请求。
我们的 API 通过 POST /search 接受文本搜索。为了定义测试期间执行的请求,我们使用 queries.json 文件,其中包含多个英文和西班牙文的视频游戏搜索词。

[
  {"query": "fifa 14 ps3 digital code", "lang": "en"},
  {"query": "fifa 14 ps3 codigo digital", "lang": "es"},
  {"query": "gta vice city ps2", "lang": "en"},
  {"query": "el mario kart de la wii", "lang": "es"}
]

如果 API 要求的请求结构不同,还需要相应调整 search.js 中的请求体。


3. 配置负载:scenarios

定义好要请求什么之后,接下来要确定负载如何施加。为此,我们在 scenarios/ 目录下使用 JSON 文件,每个文件都有各自的配置。

每个 JSON 文件对应一种不同的负载测试场景:

通过这些文件,我们可以配置虚拟用户数量、测试时长、负载模式以及性能阈值。
例如,smoke.json 的内容如下:

{
  "name": "smoke",
  "description": "1 user for 1 minute: checks that the API works before adding load.",
  "queries_file": "queries.json",
  "endpoint": "/search",
  "think_time_seconds": 1,
  "executor": {
    "executor": "constant-vus",
    "vus": 1,
    "duration": "1m"
  },
  "thresholds": {
    "http_req_failed": ["rate<0.01"],
    "http_req_duration": ["p(95)<5000"]
  }
}

主要参数如下:


5.3. 用 Terraform 部署基础设施

配置文件就绪后,我们就可以用 AWS CloudShell 部署整套方案,CloudShell 已预装运行 Terraform 和构建 Docker 镜像所需的工具。

1. 安装 Terraform(仅首次需要)

AWS CloudShell 默认没有 Terraform。我们可以把它下载到主目录,这样即使跨会话也能保留:

curl -sLo /tmp/terraform.zip https://releases.hashicorp.com/terraform/1.9.8/terraform_1.9.8_linux_amd64.zip
mkdir -p ~/bin && unzip -o /tmp/terraform.zip -d ~/bin
echo 'export PATH="HOME/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
terraform version

2. 搭建基础设施

git clone https://github.com/RominaElenaMendezEscobar/game-catalog-k6.git
cd game-catalog-k6/terraform
echo 'api_id = "<api-id>"' > terraform.tfvars
terraform init
terraform apply \
  -target=aws_ecr_repository.k6 \
  -target=aws_ecr_repository.report
../build-and-push.sh

terraform apply

部署分三步进行:先创建 Amazon ECR 仓库,再构建并推送容器镜像,最后部署其余资源。

Terraform 会创建所需的基础设施,包括 Amazon ECS Fargate、AWS Step Functions、AWS Lambda、Amazon S3,以及 IAM 角色和权限配置。同时,它还会把 k6 要用的测试场景和查询上传到 Amazon S3。


5.4. 运行负载测试

基础设施部署完成后,就可以通过 AWS Step Functions 启动测试执行,只需指定要运行的场景即可。
例如,要执行load.json:

aws stepfunctions start-execution \
  --state-machine-arn "$(terraform output -raw state_machine_arn)" \
  --input '{"scenario": "load", "label": "baseline"}'


Screenshot by the author. AWS Management Console.

状态机编排了三个步骤:


Screenshot by the author. Amazon S3 bucket showing the files and results generated by the automated load testing pipeline.

k6 生成的文件(RunLoadTest):


5.5. 报告生成

测试完成后,流水线会处理 k6 的结果,并生成一份 PDF 报告,其中既有计算出的各项指标,也包含 Amazon Bedrock 给出的解读。
这一阶段我们使用以容器镜像形式部署的 AWS Lambda 函数,因为需要用到多个 Python 库:pandas 用于数据处理,matplotlib 用于生成图表,fpdf2 用于生成 PDF 文档。

传统的 ZIP 部署方式解压后最多只能 250 MB,而 AWS Lambda 的容器镜像可以做到 10 GB。这样一来,把代码及其依赖打包成可复现的环境就轻松多了,同时还能保留无服务器的执行模式。

下面这张信息图总结了这种做法的主要优势。


作者绘制,基于 AWS Lambda 文档。

容器镜像通过 Dockerfile 构建并推送到 Amazon ECR,随后 Terraform 会配置 AWS Lambda 函数来使用这个镜像,整体流程如下图所示。


作者绘制,基于 AWS 文档。

生成的 PDF 报告示例可以通过以下链接查看:
github.com 上的 report.pdf


作者使用 Python、Grafana k6 和 Amazon Bedrock 生成的报告。

报告共分多页,各页按以下章节组织:

需要强调的是,所有指标都是用 Python 代码基于 k6 的测试结果计算出来的。Amazon Bedrock 只负责解读这些数值并生成文字分析,另外还有一道验证环节,用来核对生成文本中提到的数字是否准确。


6. 结论

本文从一个问题出发:并发量不断攀升时,API 的表现会如何变化?为了回答这个问题,我们搭建了一条自动化压测流水线,可以在不同负载场景下评估 API 性能并分析结果。

这个实践让我们把一些 站点可靠性工程(SRE)理念落到了实处:先明确要度量服务的哪些方面(SLI),再确定可接受的服务水平(SLO),最后用 Grafana k6 把这些目标转化为测试中可度量的阈值。

除了跑压测,还需要解读大量性能数据。为此我们引入了 生成式 AI 来辅助分析,生成一份总结关键发现的报告,读者无需深入掌握每个指标也能看懂。要强调的是,指标由代码计算,AI 只负责解读,采集到的数据与生成的结论之间保持了清晰的边界。

另一个值得一提的方面是方案的可复用性。只需更换 API、查询语句和压测场景,同一条流水线就能用来评估其他服务。此外,每次执行的配置和结果都会保留下来,既保证了可追溯性,也方便日后对比。

当然,这个 MVP 还有不少局限和改进空间:

归根结底,目标不只是搞清楚 API 能承受多少请求,而是建立一套可复现的流程,让我们能够度量其行为表现、识别潜在的性能退化,并评估每次变更之后性能的演变趋势。


参考资料

——

广告 广告
🧑‍💻

zhirenhun

一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。

ai aws testing programming