首页/新闻资讯/正文详情

Artillery 自定义插件开发实战:以 artillery-plugin-hello-world 为例剖析插件接口与扩展机制

发布时间:2026/9/25 2:50:25 来源:云帆数科 栏目:资讯中心
Artillery 自定义插件开发实战:以 artillery-plugin-hello-world 为例剖析插件接口与扩展机制
性能测试接口测试CLI【免费下载链接】artilleryThe complete load testing platform. Everything you need for production-grade load tests. Serverless distributed. Load test with Playwright. Load test HTTP APIs, GraphQL, WebSocket, and more. Use any Node.js module.项目地址https://gitcode.com/gh_mirrors/ar/artillery点击查看免费下载本指南以仓库内 examples/artillery-plugin-hello-world 示例插件为主线完整讲解 Artillery 的插件接口v1/v2 两种形态、插件包的命名与加载约定、如何读取测试脚本配置、如何为所有场景挂载自定义请求钩子beforeRequest、如何通过事件机制上报自定义计数器以及插件的清理钩子cleanup。读完本文你将具备从零编写一个可被 Artillery 自动发现、加载并生效的 Node.js 插件的能力并理解插件从解析到实例化的底层调用链。一、这个示例插件展示了什么artillery-plugin-hello-world是一个刻意保持“最小可用”的 Artillery 插件其 README 明确列出了它要演示的四件事Artillery 的插件接口长什么样一个骨架级barebones插件是如何构建起来的如何在插件内部读取测试脚本test script的属性如何为场景挂载自定义 hook从而在压测过程中做一些“有趣”的事。换句话说它不依赖任何外部服务也不实现复杂的指标采集而是把插件开发的最小完整闭环——定义、加载、配置读取、钩子注入、事件上报、清理——一次性走通是理解 Artillery 扩展体系的最佳入门样本。二、插件的两种形态v1 构造函数与 v2{ Plugin }导出从 Artillery 的插件加载源码 packages/artillery/lib/load-plugins.ts 可以看到插件包在加载时会按导出形状被识别为不同版本v1 插件模块直接导出一个构造函数typeof PluginExport function实例化时接收script.config和事件总线v2 插件模块导出一个对象其中含Plugin构造函数typeof PluginExport.Plugin function实例化时接收完整的script、事件总线与运行选项。本示例采用 v2 形态在 index.js 中通过一行代码完成导出module.exports.Plugin ArtilleryHelloWorldPlugin;在本地运行器 packages/artillery/lib/platform/local/worker.ts 中两种形态的实例化方式对应为// v1传 script.config result.plugin new result.PluginExport(script.config, stubEE); // v2传整个 script result.plugin new result.PluginExport.Plugin(script, stubEE, options);从源码结构看v2 之所以能拿到整个script是为了让插件有更大的自由度去修改脚本对象例如注入处理器函数而 v1 只拿到配置部分。本示例使用的 v2 接口正是当前主推的形态。三、插件包命名与加载路径约定Artillery 默认会到 Node.js 的包查找路径中寻找插件包且要求包名带artillery-plugin-前缀——因此hello-world插件对应的包名必须是artillery-plugin-hello-world这一点同时体现在 package.json 的name字段与加载逻辑中。加载顺序在 load-plugins.ts 中定义得非常明确先按裸包名bare specifier从标准node_modules解析用户安装的副本优先其次查找 Artillery 内置包目录最后才尝试ARTILLERY_PLUGIN_PATH环境变量中冒号:分隔的各个路径。let requirePaths [, BUILTIN_PACKAGES_DIR]; if (process.env.ARTILLERY_PLUGIN_PATH) { requirePaths requirePaths.concat(process.env.ARTILLERY_PLUGIN_PATH.split(:)); }因此当你在开发插件、尚未把包发布安装到node_modules时用ARTILLERY_PLUGIN_PATH指向上级目录即可让 Artillery 找到它。原文档在 README 中也明确提示了这一点ARTILLERY_PLUGIN_PATH正是为“开发中的插件”提供的额外查找位置。除路径外还可以通过环境变量ARTILLERY_PLUGINSJSON 字符串附加额外的插件配置详见 load-plugins.ts 中的loadPluginsConfig实现。四、剖析插件实现构造函数里做了什么打开 index.js整个插件只有三部分构造函数、一个处理器函数、一个cleanup钩子。下面逐段拆解。4.1 保存 script 与 eventsfunction ArtilleryHelloWorldPlugin(script, events) { this.script script; this.events events; // ... }构造函数接收两个参数script完整的测试脚本对象即 YAML 解析后的configscenarios结构events一个 EventEmitter插件可以订阅stats新一批指标产生时触发、done所有虚拟用户完成时触发事件也可以用它发出自定义指标。从 worker.ts 的调用来看v2 插件实例化时传入的正是完整script、事件桩stubEE与options。注释中还特别说明v1/v2 插件不会从每个 runner 实例直接订阅stats/done而是在launch-platform层统一订阅聚合后的结果避免插件收到未聚合的零散事件。4.2 读取插件自身的配置const pluginConfig script.config.plugins[hello-world]; this.greeting pluginConfig.greeting || hello, world;插件可以直接访问script.config.plugins[hello-world]拿到自己在测试脚本中的配置块并给出默认值兜底。这正是原文档所说的“如何检查测试脚本属性”——配置、target、phases 等一切脚本内容对插件都是可见的例如debug(target is:, script.config.target);4.3 向所有场景注入 beforeRequest 钩子script.config.processor script.config.processor || {}; script.config.processor.pluginHelloWorldBeforeRequestHook (_req, _vuContext, events, next) { console.log(this.greeting); events.emit(counter, greeting_count, 1); return next(); }; script.scenarios.forEach((scenario) { scenario.beforeRequest scenario.beforeRequest || []; scenario.beforeRequest.push(pluginHelloWorldBeforeRequestHook); });这段代码做了三件事正是插件“动手术”的典型手法在script.config.processor对象中注册一个自定义函数Artillery 的处理器机制该函数的签名符合beforeRequest钩子约定接收请求对象_req、虚拟用户上下文_vuContext、events事件总线以及next回调调用next()表示钩子结束、继续后续流程遍历script.scenarios把钩子名追加到每个场景的beforeRequest列表末尾——由此实现对所有场景生效无需用户在 YAML 里逐个声明。HTTP 引擎在 packages/artillery/lib/core/engine_http.ts 中会在每次请求发出前依次执行这些beforeRequest处理器包括场景级与请求级这也是“在请求前打印问候语”之所以能落地的底层机制。4.4 上报自定义计数器钩子内部通过events.emit(counter, greeting_count, 1)上报一个名为greeting_count的自定义计数器。控制台报告器 packages/artillery/lib/console-reporter.ts 会读取report.counters并按名称排序打印最终在测试报告尾部以greeting_count: N的形式呈现无需任何额外配置即可看到插件产生的新指标。4.5 清理钩子 cleanupArtilleryHelloWorldPlugin.prototype.cleanup (done) { debug(cleaning up); done(null); };Artillery 在退出前会调用每个插件的cleanup给插件一次冲刷在途数据、写盘等收尾机会。在 packages/artillery/lib/launch-platform.ts 与 packages/artillery/lib/platform/local/worker.ts 中都有对plugin.cleanup的调用且在done回调中传入错误对象null表示无错。本示例只打印一条调试日志实际插件常在此处刷新缓存、关闭连接或写报告文件。五、配套的测试脚本与运行方式示例自带的 test.yml 是验证插件的完整测试脚本config: target: http://asciiart.artillery.io:8080 phases: - arrivalRate: 1 duration: 10 plugins: hello-world: greeting: Hello world! scenarios: - flow: - get: url: /要点解读config.plugins.hello-world.greeting是插件的配置块会被插件构造函数读取并覆盖默认问候语phases以每秒 1 个新虚拟用户的速率持续 10 秒场景只有一个 HTTPGET /请求用于触发beforeRequest钩子。在示例目录下运行注意需先安装 Artillery 本体示例插件作为本地包由ARTILLERY_PLUGIN_PATH指向ARTILLERY_PLUGIN_PATHpwd/.. DEBUGplugin:hello-world artillery run test.yml命令说明ARTILLERY_PLUGIN_PATHpwd/..把插件包所在目录示例的上级目录即examples/其中包含名为artillery-plugin-hello-world的包目录加入插件查找路径DEBUGplugin:hello-world开启debug库中该插件命名空间的调试输出对应 index.js 中的require(debug)(plugin:hello-world)artillery run test.yml以本地模式运行测试。运行后终端会依次出现插件初始化时的调试信息如target is:与cleaning up、每条请求前的问候语打印以及报告尾部由插件上报的greeting_count计数器见上文两张截图。loadPlugins的单元测试 packages/artillery/test/unit/load-plugins.test.js 与 CLI 测试 packages/artillery/test/cli/custom-plugin.test.js 均演示了通过ARTILLERY_PLUGIN_PATH加载本地插件这一方式的自动化验证。六、插件的加载与初始化调用链把上面的零散证据串起来一个插件从被识别到生效的完整链路是解析插件规格loadPluginsConfig合并脚本内的config.plugins与环境变量ARTILLERY_PLUGINSload-plugins.ts按序查找包依次在裸包路径、内置包目录、ARTILLERY_PLUGIN_PATH中require.resolve再通过import()加载兼容 CJS 与 ESM见 load-plugins.ts识别版本按导出形状判定 v1/v2load-plugins.ts实例化在本地 worker 中按版本调用构造函数worker.ts在平台层如 Fargate/Lambda 场景则先给一个深拷贝的dummyScript做事件订阅注册避免在分发阶段就修改真实脚本对象launch-platform.ts钩子生效插件修改script.config.processor与各scenario.beforeRequestHTTP 引擎在每次请求前执行这些处理器engine_http.ts指标呈现插件通过events.emit(counter, ...)上报的计数器由控制台报告器汇总打印console-reporter.ts退出清理cleanup被依次调用launch-platform.ts。值得一提的是平台层在初始化时给 v1/v2 插件传递的是深拷贝的 dummyScript源码注释明确指出如果让插件直接操作真实脚本对象并在其中附加处理器会导致派发 worker 时失败launch-platform.ts——这是插件开发中容易踩坑、但示例这种“单机运行”场景不会触发的细节。七、在此基础上还能做什么原文档在 README 的 “Learn more” 一节推荐了更多成熟插件作为参考这些参考实现大多已在当前仓库中开源可以直接对照阅读packages/artillery-plugin-publish-metrics向 Datadog、Prometheus、CloudWatch、New Relic、Splunk、Mixpanel 等后端发布指标展示了订阅stats事件做指标转发的能力packages/artillery-plugin-expect在测试中对响应做断言展示了在请求层面深度拦截与校验的模式packages/artillery-plugin-apdex基于响应时间计算 Apdex 评分展示了利用聚合指标派生新指标的做法packages/artillery-plugin-metrics-by-endpoint按端点拆分指标展示了结合 URL 模板场景的处理方式packages/artillery-plugin-fake-data生成随机测试数据展示了在脚本中注入数据生成能力packages/artillery-plugin-slack测试结束后推送通知展示了订阅done事件的典型用法。此外Artillery 的官方扩展 API 文档与《创建自定义插件》博客是深入了解插件机制的权威补充资料原文已给出链接此处不再罗列外部地址。核心要点可以归纳为插件接口 Node.js 生态“任何需求几乎都有对应的 npm 包”是 Artillery 扩展能力的双引擎——你的插件完全可以调用任意 Node.js 模块来完成指标入库、消息通知、数据加工等任何定制逻辑。八、小结通过artillery-plugin-hello-world这个最小示例我们完整走通了 Artillery 插件开发的全部关键环节能力示例中的落点源码依据v2 插件导出module.exports.Pluginindex.js、worker.ts读取脚本配置script.config.plugins[hello-world]index.js注入全局钩子改写scenario.beforeRequestindex.js、engine_http.ts自定义指标events.emit(counter, ...)index.js、console-reporter.ts退出清理prototype.cleanupindex.js、launch-platform.ts开发期加载ARTILLERY_PLUGIN_PATHload-plugins.ts对任何希望扩展 Artillery 的团队或个人而言这个示例提供了可复制的最小骨架定义{ Plugin }导出 → 读取配置 → 注入处理器 → 上报指标 → 实现清理。后续只需按需求替换业务逻辑就能把它升级为功能完备的生产级插件。赞分享性能测试接口测试CLI【免费下载链接】artilleryThe complete load testing platform. Everything you need for production-grade load tests. Serverless distributed. Load test with Playwright. Load test HTTP APIs, GraphQL, WebSocket, and more. Use any Node.js module.项目地址https://gitcode.com/gh_mirrors/ar/artillery点击查看免费下载相关推荐深入解析 Artillery 自定义引擎开发以 artillery-engine-example 为例掌握引擎 API 与实战接入深入解析 Artillery 自定义引擎开发以 artillery engine example 为例掌握引擎 API 与实战接入 导读 本指南以仓库内 ar性能测试接口测试CLIEclipse Theia 无头插件Headless Plugin与自定义插件 API 实战以 plugin-gotd 示例插件为例Eclipse Theia 无头插件Headless Plugin与自定义插件 API 实战以 plugin gotd 示例插件为例 本篇技术指南围绕 EIDE代码编辑器开发工具前端桌面应用插件系统后端AI 应用Kubebuilder 插件扩展实战从自定义 Plugin 接口到构建专属 CLIKubebuilder 插件扩展实战从自定义 Plugin 接口到构建专属 CLI Kubebuilder 不仅是开箱即用的 CRD 脚手架工具更提供了一套开发者工具代码生成CLI云原生后端上一篇SymPy 特殊函数专题指南从 Dirac Delta 到超几何函数的内置特殊函数库下一篇Rails Girls Guides终极翻译指南搭建跨文化交流的编程教育桥梁创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

react-map-gl 入门指南:为 Mapbox GL JS 与 MapLibre GL JS 打造的 React 组件套件
react-map-gl 入门指南:为 Mapbox GL JS 与 MapLibre GL JS 打造的 React 组件套件

前端UI组件 【免费下载链接】react-map-gl React friendly API wrapper around MapboxGL JS 项目地址: https://gitcode.com/gh_mirrors/re/react-map-gl 点击查看 免费下载 react-map-gl 是一套专为 React 设计的开源组件库,它把 mapbox-gl 与 maplibr… · 2026/9/25 2:50:25

Spyder 内置教程全解:从运行首个 Python 程序到调试、绘图与代码规范实战
Spyder 内置教程全解:从运行首个 Python 程序到调试、绘图与代码规范实战

开发工具IDE代码编辑器 【免费下载链接】spyder Official repository for Spyder - The Scientific Python Development Environment 项目地址: https://gitcode.com/gh_mirrors/sp/spyder 点击查看 免费下载 Spyder(Scientific Python Development Env… · 2026/9/25 2:50:25

RocketRide llm_perplexity 节点深度解析:把 Perplexity Sonar 搜索增强大模型接入 AI 流水线
RocketRide llm_perplexity 节点深度解析:把 Perplexity Sonar 搜索增强大模型接入 AI 流水线

【免费下载链接】rocketride-server High-performance AI pipeline engine with a C core and 50 Python-extensible nodes. Build, debug, and scale LLM workflows with 13 model providers, 8 vector databases, and agent orchestration, all from your IDE. Includes VS C… · 2026/9/25 2:50:25

Agent-Native系统架构落地指南:从AI调用到智能体编排
Agent-Native系统架构落地指南:从AI调用到智能体编排

1. 为什么我开始认真对待"agent-native"这个词大概从去年下半年开始,我发现自己和团队在做AI应用时,陷入了一种很别扭的状态:产品经理给的需求还是老一套的"用户点击-后端处理-返回结果"逻辑,只是把中间某个环… · 2026/9/25 3:27:14

UWP CommandBar 命令栏控件新特性实战:基于 Windows-universal-samples 的 XamlCommanding 示例深度解析
UWP CommandBar 命令栏控件新特性实战:基于 Windows-universal-samples 的 XamlCommanding 示例深度解析

示例工程 【免费下载链接】Windows-universal-samples API samples for the Universal Windows Platform. 项目地址: https://gitcode.com/gh_mirrors/wi/Windows-universal-samples 点击查看 免费下载 XamlCommanding 是 Windows-universal-samples 仓库中专门用于… · 2026/9/25 3:27:13

mikro-orm 命名策略(Naming Strategy)实战指南:表名、列名、索引名的映射规则与自定义实现
mikro-orm 命名策略(Naming Strategy)实战指南:表名、列名、索引名的映射规则与自定义实现

后端 【免费下载链接】mikro-orm TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases. 项目地址: https://gitcode.com/gh_mir… · 2026/9/25 3:27:13

react-native-skia 视图快照实战:用 makeImageFromView 将任意原生 View 捕获为 SkImage
react-native-skia 视图快照实战:用 makeImageFromView 将任意原生 View 捕获为 SkImage

图形学移动开发跨平台UI组件 【免费下载链接】react-native-skia High-performance React Native Graphics using Skia 项目地址: https://gitcode.com/gh_mirrors/re/react-native-skia 点击查看 免费下载 react-native-skia(shopify/react-native-ski… · 2026/9/25 3:27:13

WPScan 插件版本检测实战:以 formgimp CHANGELOG 夹具解析 Change Log 动态发现机制
WPScan 插件版本检测实战:以 formgimp CHANGELOG 夹具解析 Change Log 动态发现机制

网络安全漏洞扫描渗透测试应用安全CLI 【免费下载链接】wpscan WPScan WordPress security scanner. Written for security professionals and blog maintainers to test the security of their WordPress websites. Contact us via contactwpscan.com 项目地址: ht… · 2026/9/25 3:27:13

BentoML BentoCloud 金丝雀部署实战:多版本并行、流量路由与灰度发布完整指南
BentoML BentoCloud 金丝雀部署实战:多版本并行、流量路由与灰度发布完整指南

模型推理服务人工智能后端大模型MLOpsLLMOps 【免费下载链接】BentoML The easiest way to serve AI apps and models - Build Model Inference APIs, Job queues, LLM apps, Multi-model pipelines, and more! 项目地址: https://gitcode.com/gh_mirrors/be/BentoM… · 2026/9/25 3:27:07

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码