Dapr Workflows 性能测试指南:基于 k6 与 K8s 的并发压测方案全解析
【免费下载链接】daprDapr is a portable runtime for building distributed applications across cloud and edge, combining event-driven architecture with workflow orchestration.项目地址: https://gitcode.com/GitHub_Trending/da/dapr
导读
本文围绕 Dapr 仓库中的 tests/perf/workflows/README.md 展开,完整讲解 Dapr Workflows 性能测试套件的设计思路与运行机制。测试由 Go 测试框架驱动、k6 施加负载,覆盖恒定虚拟用户数、恒定迭代数、最大并发、延迟工作流与不同负载大小等常见模式。读完本文,你将掌握每个测试场景的 VU/迭代组合、sum_series_wf/sum_parallel_wf/state_wf/delay_wf等被测工作流的构造方式、App 与 Sidecar 资源监控的采集方法,以及如何利用tests/perf/report将 k6 JSON 报告渲染成可视化图表。
测试目标与整体架构
该测试套件的目标是:在 Kubernetes 集群上部署perf-workflowsapp应用及其 Dapr Sidecar,通过 k6 向工作流应用发送 HTTP 请求,评估 Dapr Workflows 在常见负载模式下的性能表现。测试结果不仅包含 k6 自身的延迟与吞吐指标,还同步采集 App 与 Sidecar 的 CPU/内存使用量及重启次数,最终汇总成一张摘要表,并输出图表到 tests/perf/report/charts/v1.16.3/workflows/。
整个套件由三部分协作完成:
- Go 测试驱动:workflow_test.go 负责部署应用、准备 k6 环境、执行压测并采集资源数据;
- k6 脚本:test.js 定义各类压测场景(VU 数、迭代数、执行器与超时时间);
- 报告渲染:tests/perf/report 下的
charts.go将 gotestsum 的 JSON 报告转换为 PNG 图表。
术语表(Glossary)
| 术语 | 含义 |
|---|---|
| VU(Virtual User) | 同一时刻并发运行的工作流数量 |
| Iterations | 工作流运行的总次数 |
| Req_Duration | 完成一次工作流运行所花费的时间 |
| Sidecar | Dapr Sidecar 进程 |
测试计划:部署与公共流程
部署拓扑
所有测试共享同一套部署拓扑:在 Kubernetes 集群上部署单实例的perf-workflowsapp(镜像名为perf-workflowsapp,应用端口与 Ingress 端口均为 3000),并启用 Dapr Sidecar。资源请求/限制通过AppDescription结构体中的App*与Dapr*字段配置,具体数值定义在 workflow_test.go 的TestMain中:
| 字段 | 值 |
|---|---|
DaprCPULimit | 1.0 |
DaprCPURequest | 0.5 |
DaprMemoryLimit | 2Gi |
DaprMemoryRequest | 1Gi |
AppCPULimit | 2.0 |
AppCPURequest | 1.0 |
AppMemoryLimit | 2Gi |
AppMemoryRequest | 1Gi |
Replicas | 1 |
此外,测试还定义了一个scaledAppName(perf-workflowsapp-scaled),以scaledReplicas = 3副本部署,用于多实例场景下验证工作流与活动跨实例分布的表现。
所有场景的公共流程
- 使用 k6 向工作流应用发送 HTTP 请求;
- 在开始加压之前初始化工作流运行时;
- 收集 k6 指标,以及 App/Sidecar 的资源使用量与重启次数,写入摘要表;
- 测试结束后将指标汇总至 tests/perf/report/charts/v1.16.3/workflows/ 下的图表。
每次子测试的核心执行流程封装在testWorkflow()函数中(workflow_test.go):
- 若
restart为 true,先通过tr.Platform.Restart(testAppName)重启应用以清空上一次运行的内存与状态; - 获取应用的外部 Ingress URL;
- 调用
utils.HealthCheckApps(externalURL)确认应用健康; - 调用
http://<externalURL>/start-workflow-runtime初始化工作流运行时(对多副本应用循环调用scaledReplicas * 3次,确保所有实例都已初始化),随后 sleep 5 秒; - 构造 k6 运行配置
K6RunConfig(目标 URL、场景名、工作流名、工作流输入、通过率检查表达式),调用runk6test()执行压测; - 对于负载大小测试(
payloadTest为 true),额外将输入字节数换算为 KB 输出到摘要表; - 通过
addTestResults()采集资源数据(见下文)并写入摘要表,最后table.Flush()落盘。
资源与指标采集
addTestResults()(workflow_test.go)通过tr.Platform提供的三个方法采集:
GetAppUsage(testAppName):应用 Pod 的内存(MB)与 CPU(m)使用量;GetSidecarUsage(testAppName):Sidecar 的内存与 CPU 使用量;GetTotalRestarts(testAppName):应用重启总次数。
同时将 k6 汇总指标写入摘要表,包括:VUs Max、Iterations Count、HTTP 请求时长(Req Duration,ms)、HTTP 请求等待时长(Req Waiting,ms)与迭代时长(Iteration Duration,ms)。
k6 场景定义详解
test.js 定义了完整的场景库。每个场景使用shared-iterations执行器,即固定 VU 数共享固定总量的迭代,所有迭代完成后场景结束:
| 场景名 | VUs | Iterations | maxDuration |
|---|---|---|---|
t_30_300 | 30 | 300 | 200s |
t_60_300 | 60 | 300 | 380s |
t_90_300 | 90 | 300 | 380s |
t_350_1400 | 350 | 1400 | 1000s |
t_110_440 | 110 | 440 | 450s |
t_80_800 | 80 | 800 | 420s |
t_500_10000 | 500 | 10000 | 3600s |
场景名遵循t_<workflowCount>_<iterations>的命名约定。运行时会通过__ENV.SCENARIO环境变量选择唯一启用的场景(enabledScenarios[__ENV.SCENARIO])。
脚本通过 k6 环境变量接收配置:
TARGET_URL:工作流运行接口地址(http://<app>/run-workflow);SCENARIO:场景名,如t_30_300;WORKFLOW_NAME:要运行的工作流名;WORKFLOW_INPUT:工作流输入(数字或负载大小);RATE_CHECK:通过率阈值表达式,如rate==1,作为 k6 的checksthreshold 生效。
压测主流程execute()将workflow_name与workflow_input封装为 JSON,向${TARGET_URL}/${iterationInTest}发起 HTTP POST 请求,并以响应状态码 2xx 作为通过检查(check)。teardown()阶段会调用 Dapr Sidecar 的http://127.0.0.1:${DAPR_HTTP_PORT}/v1.0/shutdown接口触发优雅关闭。
五大测试场景逐一解析
测试函数均通过//go:build perf构建标签隔离,仅在-tags=perf下编译,并使用testWorkflow()通用执行器驱动。各测试传入rateChecks矩阵(如rate==1)作为每次运行的 k6 通过率要求。
TestWorkflowWithConstantVUs:恒定 VU 数
被测工作流:sum_series_wf,包含 5 个链式(串行)活动,每个活动执行数值计算并把结果返回给工作流。
场景设计:
- 输入:
["100"] - 场景:
["t_30_300", "t_30_300", "t_30_300"](30 VU、300 总迭代) - 同一场景连续运行 3 次,不重启应用(
restart=false),用于观察多次连续运行下延迟与资源使用的稳定性(workflow_test.go)。
每次运行结束后记录 k6 延迟与吞吐指标、App/Sidecar 的 CPU/内存使用量,以及总重启次数。
TestWorkflowWithConstantIterations:恒定迭代数、递增 VU
被测工作流:同样是sum_series_wf(5 个链式数值计算活动)。
场景设计:
- 输入:
["100"] - 场景:
["t_30_300", "t_60_300", "t_90_300"](总迭代恒定为 300,VU 从 30 递增到 90) - 每次子测试运行前重启应用以清空状态(
restart=true),从而隔离"在相同总工作量下,增大 VU 数对延迟与资源使用的影响"(workflow_test.go)。
TestSeriesWorkflowWithMaxVUs:串行工作流高并发压测
被测工作流:sum_series_wf,5 个链式活动,以更高的 VU 数对串行工作流施压。
场景设计:
- 输入:
["100"] - 场景:
["t_350_1400"](350 VU、1400 迭代) - 校验所有工作流实例均成功完成,并记录 App/Sidecar 资源使用量与延迟指标(workflow_test.go)。
TestParallelWorkflowWithMaxVUs:并行工作流高并发压测
被测工作流:sum_parallel_wf,包含 5 个并行执行的活动,其结果由工作流聚合——即经典的扇出/扇入(fan-out/fan-in)模式。
场景设计:
- 输入:
["100"] - 场景:
["t_110_440"](110 VU、440 迭代) - 重点考察负载下扇出/扇入行为的性能表现,同样记录 k6 指标与资源使用量(workflow_test.go)。
TestWorkflowWithDifferentPayloads:不同负载大小
被测工作流:state_wf,执行状态操作,内部由 3 个活动组成:
- 活动 1:将指定大小的数据保存到配置的状态存储(state store);
- 活动 2:读回已保存的数据;
- 活动 3:删除该数据。
工作流以数据大小作为输入,并将该大小的字符串作为负载传给活动。
场景设计:
- 场景恒定为
["t_30_300"],负载大小取["10000", "50000", "100000"]字节; - 对每种负载大小:运行相同的 k6 场景,记录延迟、吞吐与 App/Sidecar 资源使用,将有效负载大小输出到摘要表,并在每次运行之间重启应用(workflow_test.go)。
多实例与延迟工作流补充场景
除 README 列出的五大场景外,workflow_test.go 还实现了三个扩展场景,与上述测试共用同一套testWorkflow()执行框架:
TestSeriesWorkflowMultiInstance / TestParallelWorkflowMultiInstance
针对 3 副本的scaledAppName部署运行sum_series_wf(t_30_300)与sum_parallel_wf(t_110_440),验证工作流与并行活动的扇出/扇入跨多个 Dapr 实例分布时的表现(workflow_test.go)。
TestDelayWorkflowsAtScale
延迟工作流压测:运行delay_wf,输入"5000"表示延迟毫秒数(5 秒),场景为t_500_10000(500 VU、10000 迭代,maxDuration 3600s),考察大量工作流同时处于"等待/延时"状态时的运行时稳定性(workflow_test.go)。这也是t_500_10000场景在 test.js 中单独存在的用途。
如何运行 Workflows 性能测试
性能测试的构建与运行入口集中在 tests/dapr_tests.mk:
PERF_TEST_APPS中包含workflowsapp,即性能测试应用清单(tests/dapr_tests.mk);PERF_TESTS中包含workflows(tests/dapr_tests.mk);- Makefile 通过
genPerfTestRun模板为每个性能测试生成test-perf-<name>目标(tests/dapr_tests.mk),运行方式为:
make test-perf-workflows该目标要求先满足check-e2e-env与test-deps前置条件,内部使用gotestsum以-tags=perf ./tests/perf/workflows/...编译执行,并生成 JSON/JUnit 格式的测试输出(--jsonfile、--junitfile),超时上限为 2 小时、-count=1禁用测试缓存。整体链路perf-build-deploy-run则串联init-build-deploy → setup-test-components → build-perf-app-all → push-perf-app-all → test-perf-all(tests/dapr_tests.mk)。
执行环境依赖DAPR_TEST_NAMESPACE、DAPR_TEST_TAG、DAPR_TEST_REGISTRY等环境变量指定目标集群与镜像仓库;若要单独挑选某个性能测试,可设置DAPR_PERF_TEST环境变量(tests/dapr_tests.mk)。
结果可视化:从 JSON 报告到图表
图表分类与平均规则
性能测试会重复运行同一场景(如TestWorkflowWithConstantVUs/[T_30_300]:_运行 3 次),tests/perf/report 下的charts.go会:
- 归一化子测试名,剥离
:_/:_#NN后缀,使同一逻辑测试的所有运行共享同一 key(如TestWorkflowWithConstantVUs_T_30_300); - 若同一逻辑测试有多次运行,则按指标逐项求平均,生成带
_avg后缀的平均图表,并额外生成*_duration_comparison.png比较各次运行的延迟差异; - 若只有一次运行,则直接生成不带
_avg的图表。
图表类型
针对每个测试,会生成以下图表(示例见 tests/perf/report/charts/v1.16.3/workflows/):
- 时长分解图(
*_avg_duration_breakdown.png/*_avg_duration_low.png):X 轴为百分位min/med/avg/p90/p95/max,Y 轴为秒;折线来自 k6 指标http_req_connecting、http_req_tls_handshaking、http_req_sending、http_req_receiving、http_req_blocked、http_req_waiting、http_req_duration、iteration_duration与http_req_failed。全范围图展示整体(含延迟工作流的长时间http_req_waiting),低延迟图则动态缩放到 0~N 秒窗口以观察短耗时阶段。 - 性能摘要图(
*_avg_summary.png):柱状展示成功率(checks.rate * 100)、失败率与 VUs(vus_max.values.max),回答"该场景是否通过、驱动测试需要多少虚拟用户"。 - 吞吐图(
*_avg_throughput.png):迭代/秒作为标题,柱状展示接收数据速率(data_received.values.rate / 1024,KB/s)与发送数据速率(data_sent.values.rate / 1024,KB/s)。 - 数据量图(
*_avg_data_volume.png):按总量自动选择单位(<1MB 用 KB、≥1GB 用 GB、否则用 MB),柱状展示整个测试生命周期的收发总字节数,便于对比不同负载大小或不同时长的场景。 - 运行间时长对比图(
*_duration_comparison.png):X 轴为 Run 1/2/3…,Y 轴为延迟(ms),折线为每次运行的 p50(中位数)与 p95(尾延迟),用于判断运行稳定性:折线平坦说明性能一致,出现尖峰或趋势则说明运行间存在波动。
本地生成图表
charts.go读取 gotestsum JSON 报告(支持直接读取.gz压缩包)并输出 PNG 到charts/<version>/<api>/:
cd tests/perf/report go run . -input data/v1.18.0/test_report_perf.json.gz -version v1.18.0常用参数:-input(报告路径,默认./test_report_perf.json)、-version(charts/下的输出子目录,默认master)、-infra(运行基础设施描述,CI 传入 tests/test-infra/perf-infra-description.txt 以保证结果可比)、-manifest(额外输出 docs 站点使用的 manifest JSON)。设置CHARTS_DEBUG=1可查看测试分类的详细输出。每个 API 的 README 顶部还会生成"Throughput per resource"表:各场景的迭代/秒、App 与 Sidecar 的 CPU/内存消耗,以及每 CPU 核心、每 GB 内存的迭代数(app + sidecar 合并),这是跨场景、跨版本比较效率的核心指标。
结果归档与版本管理策略
按 tests/perf/report/charts/README.md 的说明,性能结果的事实来源(source of truth)是 CI 运行产生的 gotestsum JSON 报告,而非渲染后的 PNG:
- 每个版本的压缩报告提交在
tests/perf/report/data/<version>/test_report_perf.json.gz; - 渲染图表作为
perf-charts-<version>.zip发布到对应版本,同时将图表与manifest.json推送到perf-charts分支的<minor>/目录(如v1.18/); - 默认分支不提交新版本的完整图表集(每个版本数 MB 且 PNG 无法事后重新生成),因为 JSON 报告可以随时用当前图表代码重新渲染。
小结
Dapr Workflows 性能测试套件是一套完整、可复现的压测方案:以 Go 测试编排生命周期、以 k6shared-iterations场景控制并发模型、以摘要表与图表沉淀结果。通过本指南,你可以按需扩展possibleScenarios或新增测试函数,复现并对比不同版本、不同基础设施下 Dapr Workflows 的串行链、并行扇出/扇入、状态读写与延迟场景的性能表现。若需深入底层实现,可继续阅读 pkg/runtime/wfengine 下 Dapr Workflows 引擎源码,以及 tests/e2e/workflows/workflow_test.go 中对应的端到端功能验证。
【免费下载链接】daprDapr is a portable runtime for building distributed applications across cloud and edge, combining event-driven architecture with workflow orchestration.项目地址: https://gitcode.com/GitHub_Trending/da/dapr
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考