Artillery 是一款开源的 Node.js 负载测试工具,可通过简洁的 YAML 脚本向你的 API 持续发起高并发请求。你可以定义压测阶段与请求流程,执行 artillery run script.yml 后,查看延迟百分位、请求速率和错误数量等关键性能指标。本文将带你完成 Artillery v2 的安装、真实测试脚本编写、压测执行、v2 版本结果采集方式,以及如何集成到 CI 持续集成流程中。
什么是 Artillery 以及何时使用它
Artillery 会创建虚拟用户(VU)来访问你的接口,并评估系统在持续流量压力下的承载能力。虚拟用户本质上是模拟出来的客户端,它会像真实调用方一样,按照场景顺序依次执行每一步请求。
当你需要定位系统扩容策略或排查性能瓶颈时,Artillery 就非常适合。例如:在每秒 50 次请求时,p95 延迟是多少?系统会在什么到达率(arrival rate)下开始报错?API 在连续五分钟高负载下能否稳定运行,还是会出现性能下降甚至服务降级?
Artillery 的优势在于其声明式配置方式。你只需要在 YAML 中描述负载模型,无需手动编写复杂的并发循环代码。它能够在任何支持 Node.js 的环境中运行,因此同一份压测脚本既能在本地电脑执行,也能无缝用于 CI/CD 流水线。
当然,Artillery 只是众多 API 负载测试工具中的一种。如果你正在评估方案,这篇 top load testing tools roundup 和这篇 load testing software comparison 还对 k6、JMeter、Gatling 等工具的优缺点做了对比分析。
安装 Artillery (v2)
它在 npm 上的包名就是 artillery,当前主流大版本为 v2。你可以先通过 npm 全局安装,再检查版本是否正确。
npm install -g artillery@latestartillery version
建议使用最新的 Node.js LTS 版本。Artillery 可运行在 Windows、macOS 和 Linux 系统上。
如果你不希望全局安装任何依赖,也可以使用 npx 直接按需执行。
npx artillery@latest run script.yml
编写 Artillery 测试脚本
Artillery 的测试脚本是一个包含两个顶层部分的 YAML 文件。config 用于定义目标地址和负载特征,scenarios 用于描述每个虚拟用户的操作步骤。
下面是一个完整示例:它会先进行预热,再逐步爬升到峰值,最后保持稳定持续的负载。
config:target: "https://api.example.com"phases:- name: "Warm up"duration: 60arrivalRate: 5- name: "Ramp to peak"duration: 120arrivalRate: 5rampTo: 50- name: "Sustained load"duration: 300arrivalRate: 50maxVusers: 500# Inline variables (or use a CSV via config.payload)variables:productId:- "1001"- "1002"scenarios:- name: "Browse and create order"flow:- get:url: "/v1/products/{{ productId }}"- post:url: "/v1/orders"json:productId: "{{ productId }}"quantity: 2
理解 config 部分
config.target 是所有请求的基础域名或主机地址。场景中的每个步骤都会把自身的 url 拼接到这个基础地址之后。
config.phases 是一个按顺序执行的负载阶段数组。最常用的字段包括:
duration:阶段持续时间,单位为秒,也可以使用更易读的字符串格式,例如"5m"。arrivalRate:每秒新启动的虚拟用户数量。rampTo:在该阶段内,将到达率从arrivalRate线性提升到指定值。arrivalCount:在整个阶段内均匀分配固定数量的虚拟用户,而不是按每秒速率生成。maxVusers:并发运行中的虚拟用户上限。name:显示在压测输出结果中的阶段名称标签。
这里有一个常见但容易混淆的细节:阶段中的 duration 控制的是 Artillery 持续生成虚拟用户的时长,而不是整场测试的实际总时长。如果某个虚拟用户在阶段结束前刚好启动,而它的请求流程还需要继续执行,那么整个测试会等它完成后才真正结束。
理解 scenarios 部分
scenarios 是一个数组。每个测试场景都包含一个 flow,也就是虚拟用户要执行的有序步骤列表。可选字段包括 name 与 weight(权重),其中 weight 用于指定 Artillery 选择某个场景的相对概率。
Flow 中的步骤使用 HTTP 动词作为键名,例如:get、post、put、delete 和 patch。每个步骤都支持 url,而请求体通常放在 json 下。双大括号语法 {{ productId }} 用于引用变量,实现参数化请求。
从 CSV 文件驱动请求
对于简单的冒烟测试,直接硬编码参数通常已经足够。但若想更真实地模拟线上流量,推荐通过 config.payload 从 CSV 文件加载测试数据。每个虚拟用户会读取其中一行,列名会自动映射成变量名。
config:target: "https://api.example.com"payload:path: "./users.csv"fields:- "email"- "password"phases:- duration: 120arrivalRate: 20scenarios:- flow:- post:url: "/login"json:email: "{{ email }}"password: "{{ password }}"
运行测试
脚本准备好之后,就可以正式执行 API 压力测试了。最基础的命令非常直接,本质上就是让 Artillery 按照脚本内容发起请求。
artillery run script.yml# Override target without editing the script:artillery run --target https://staging.example.com script.yml# Pass variables as JSON:artillery run -v '{ "productId": ["1001","1002"] }' script.yml
有几个常用命令行参数值得掌握。--target(或 -t)可覆盖 config.target,这样你就能用同一份脚本切换压测测试环境、预发布环境或生产环境。--environment(或 -e)用于选择 config.environments 中的命名配置块。--config(或 -c)可以从单独文件加载配置。--insecure(或 -k)则用于在测试环境中跳过自签名证书的 TLS 校验。
查看结果
在压测运行过程中,Artillery 大约每 10 秒会输出一次聚合指标。测试结束后,你会看到一份汇总报告。最值得重点关注的指标包括:
- 请求速率:实际运行过程中达到的每秒请求数(RPS)。
- 延迟百分位:包括 p50(中位数)、p95 和 p99 响应时间。尤其是 p95,通常更能反映用户在高负载下的真实体验。
- 错误计数:失败请求、超时以及非 2xx 响应,并按错误类型进行分类统计。
请重点观察尾延迟,而不是只看平均值。平均值有时看起来很正常,但 p99 可能已经悄悄上升到数秒。如果错误只在持续压测阶段出现,那么你很可能已经找到了系统的饱和点或瓶颈位置。关于 API 性能测试中应关注哪些指标及其背后的原因,可以进一步参考这篇 API 性能测试指南。
在 Artillery v2 中生成报告
Artillery 各版本之间的报告能力发生过变化,因此很多旧教程已经不再适用。旧文章通常会建议你先运行 artillery run --output report.json,再执行 artillery report report.json 生成 HTML 报告。现在前者依然可用,但后者已经失效。
--output 参数仍然可以输出机器可读的 JSON 结果文件。
# Write machine-readable JSON results (still supported):artillery run --output report.json script.yml
artillery report 命令,也就是过去用于把 JSON 转换为 HTML 的工具,已经从 Artillery CLI 中移除。官方文档明确说明它“已不再受支持,并已从 Artillery CLI 中删除”。由于 HTML 报告相关代码长期无人维护,因此这一功能被废弃并最终彻底移除,而且官方也没有重新加入的计划。换句话说,不要再执行 artillery report report.json;在当前的 v2 版本中它不会生效。
目前,更推荐以下三种方式。
第一种,自己解析 JSON 结果。这特别适合 CI 自动化场景,因为你往往需要基于性能阈值做断言。例如,使用 jq 提取整体 p95 延迟:
jq '.aggregate.summaries["http.response_time"].p95' report.json
第二种,使用 Artillery Cloud 提供的托管仪表盘。这是旧版 HTML 报告的官方替代方案。执行命令时传入 --record 与你的 API key 即可。
artillery run --record --key $ARTILLERY_CLOUD_API_KEY script.yml
第三种,借助 publish-metrics 插件或 OpenTelemetry,把性能指标推送到你现有的监控平台中,这样延迟、吞吐量和错误率就可以直接出现在与你生产环境一致的监控大盘里。
在 CI 中运行 Artillery
由于 Artillery 本质上只是一个 Node.js CLI 工具,因此它很容易集成到各种持续集成与持续交付流水线中。下面是一个 GitHub Actions 工作流示例:它会安装 Artillery、执行压测脚本,并把 JSON 报告作为构建产物上传保存。
name: Load teston: [workflow_dispatch]jobs:artillery:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with:node-version: "lts/*"- run: npm install -g artillery@latest- run: artillery run --output report.json script.yml- uses: actions/upload-artifact@v4with:name: artillery-reportpath: report.json此示例通过手动触发运行。由于重度压力测试需要耗时数分钟并消耗实际带宽,因此通常是按需或通过定时任务触发,而不是在每次提交时都运行。一旦生成了 JSON 报告,你可以添加一个 `jq` 步骤,在 p95 超过设定指标时使该任务失败。## Apifox 的定位:功能测试与 CI 门禁Artillery 解答的是“API 能否承受得起如此大的流量?”这是负载与性能测试。与此同时,还有一个截然不同的问题:“在代码修改后,API 是否依然返回正确的响应?”这就是功能测试和回归测试的范畴,也正是 [Apifox](https://apifox.com/?ref=apifox.com) 的用武之地。Apifox 是一个集设计、调试、mock、文档和自动化测试于一体的全流程 API 平台。它的测试场景将接口分组为包含 if、for 和 foreach 等条件的逻辑步骤,以便你可以校验响应 body、状态码和数据契约。你可以在 CI 中通过 Apifox CLI 运行这些测试场景,以便在代码修改后对合并请求进行准入拦截。请明确两者的界限。Apifox 确实包含了性能测试功能,但其最大支持 100 个虚拟用户。这足以发现明显的回归问题,但并不能在高并发场景下替代 Artillery。对于大规模、分布式、基于代码建模的负载测试,Artillery 才是正确的工具。在我们关于“不用 Python 进行 API 压力测试”的文章中也提到了这一坦诚的定位,而 Apifox 100 个虚拟用户功能的具体机制可以在《Apifox 中的 API 性能测试》中找到。因此,建议结合使用这两者。使用 Artillery 进行大规模负载测试;在 CI 中使用 Apifox CLI 运行功能测试和回归检查,以便在发布前发现异常行为。Apifox CLI 可通过 npm 安装,且 `apifox run` 仅支持使用参数标志(flag-only)。
bash
Apifox CLI: functional/regression run in CI (flag-only, no positional file)
npm install -g apifox-cli apifox run --access-token $APIFOXACCESSTOKEN -t -e -r cli,junit --out-dir ./apifox-reports ```
-t 参数表示测试场景 ID,-e 是必填的环境 ID,而 -r cli,junit 会同时输出终端结果和可供 CI 系统读取的 JUnit XML 报告。想了解更详细的操作步骤,可参考 Apifox CLI 教程;若你关注流水线设计思路,也可以查看这些“API 测试的 CI/CD 最佳实践”。
如果你希望在执行 Artillery 负载测试的同时,再通过功能测试和契约测试来把控 CI 准入质量,那么不妨免费下载 Apifox,并搭建你的第一个自动化测试场景。
常见问题解答
什么是 Artillery 负载测试?
Artillery 负载测试,是指借助开源 Artillery 工具来模拟大量并发虚拟用户访问 API。你可以在 YAML 脚本中定义负载模型与请求流程,再通过延迟百分位、请求速率和错误率等指标,评估系统在高压场景下的性能表现与稳定性。
Artillery 是免费且开源的吗?
是的。Artillery CLI 核心组件是免费且开源的,通过 npm 上的 artillery 包发布。同时,它也提供付费的托管服务 Artillery Cloud,用于展示和分析测试结果。不过即使不使用云服务,你仍然可以在本地环境和 CI 流程中完成完整的 API 负载测试。
如何运行 Artillery 负载测试?
首先执行 npm install -g artillery@latest 完成安装,然后准备一份 YAML 压测脚本:在 config 中定义目标地址与压测阶段,在 scenarios 中描述具体请求流程。脚本准备完成后,运行 artillery run script.yml 即可开始测试。压测期间,Artillery 大约每 10 秒输出一次实时指标,结束后会提供一份汇总结果,便于你分析 API 性能瓶颈。
如何生成 Artillery 报告?
你可以运行 artillery run --output report.json script.yml 来保存 JSON 结果文件。过去用于生成 HTML 报告的 artillery report 命令已从 CLI 中移除。现在更推荐使用 jq 等工具解析 JSON,或者通过 --record --key 上传到 Artillery Cloud,也可以利用 publish-metrics 或 OpenTelemetry 插件导出指标到监控平台。
Artillery 对比 k6 或 JMeter:应该选择哪一个?
这三类工具都可以胜任大规模负载测试。Artillery 基于声明式 YAML 和 Node.js,特别适合已经深度使用 JavaScript/Node.js 生态的团队。k6 采用 JavaScript 脚本编写方式,更偏向代码优先。JMeter 则是经典的 GUI 驱动工具,基于 Java,并拥有成熟的插件生态。Gatling 与 JMeter 的比较也更深入讨论了这些差异。实际选择时,建议优先考虑你团队熟悉的脚本方式、运行环境以及 CI 集成需求,再结合功能测试工具一起构建完整的质量保障体系。
开发必备:API 全流程管理神器 Apifox
在介绍完上面的 Artillery 内容后,还想额外推荐一个对开发团队同样非常实用的效率工具 —— Apifox。它集 API 文档、接口调试、设计、测试、Mock 和自动化测试于一体,是提升接口研发协作效率的热门选择。
如果你正在进行 API 开发,不妨体验一下 Apifox 友好的界面与完整能力。它兼容 Postman 和 Swagger 数据格式,导入迁移非常方便,即使是刚接触 API 管理的新手也能快速上手,点击这里即可注册使用。

值得一提的是,除了个人开发者和普通团队协作场景之外,对于有高安全合规要求、或需要在内网环境中部署协作平台的企业,Apifox 也提供了可深度定制的私有化部署方案。
