恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Dapr 性能测试编写指南:基于 Fortio 与 k6 构建可观测、可复现的压测用例

  • 首页
  • 资讯中心
  • /
  • Dapr 性能测试编写指南:基于 Fortio 与 k6 构建可观测、可复现的压测用例

相关资讯

HC-SR501与ESP32中断驱动精准人体感应实战 2026/9/12 19:00:20
Bun 运行时原理与实战:TS 开发、包管理与 HTTP 服务一体化 2026/9/12 19:00:20
背包客认证系统:数字化解决户外经验验证难题 2026/9/12 19:00:20

最新资讯

AWS EB动态配置EC2环境变量实战指南
轻奢美甲品牌特许经营模式解析与数字化运营
GPT-5.1 Thinking框架:AI辅助论文写作的技术突破
大模型长文本处理:上下文并行与Ring Attention技术解析
Python质控小程序在传染病报告信息审核中的应用
回溯算法解析:全排列问题与LeetCode实战

今日推荐

MATLAB仿生优化框架:长鼻浣熊算法多策略融合实现
【JAVA毕设源码分享】基于 JavaWeb 的校园一卡通管理系统的设计与实现 基于 JavaWeb 的校园卡业务管理系统(程序+文档+代码讲解+一条龙定制)
【JAVA毕设源码分享】基于 Java 的图书馆借阅管理平台的搭建与实现 基于 Java 的图书馆综合管理系统(程序+文档+代码讲解+一条龙定制)

本周热门

超人会飞不算本事:系统稳定依赖清晰规则与边界设计
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论
基于CNN的调制信号识别:MATLAB实现时频图分类实战

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

Dapr 性能测试编写指南:基于 Fortio 与 k6 构建可观测、可复现的压测用例

发布时间:2026/9/12 19:05:20
Dapr 性能测试编写指南:基于 Fortio 与 k6 构建可观测、可复现的压测用例 Dapr 性能测试编写指南基于 Fortio 与 k6 构建可观测、可复现的压测用例【免费下载链接】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/docs/writing-perf-test.md 展开系统讲解如何为 Dapr 编写性能测试perf test。你将掌握如何判断一个功能是否适合编写压测用例、如何在 Fortio恒定 QPS 型负载与 k6脚本化可编程负载之间做出选择、如何搭建被测应用与压测端perf-tester / k6 自定义镜像、如何收集结果并基于真实 QPS、延迟百分位数与资源消耗做断言以及如何注入故障disruptor、把指标推送到 Prometheus 并排查 k6 常见错误。全文以仓库真实源码tests/perf、tests/runner/loadtest为佐证所有代码均可对照当前仓库直接阅读。写作前提动手编写 perf test 之前请先按 tests/docs/running-perf-tests.md 配置好本地测试环境Kind/Minikube 集群、Dapr 开发环境、镜像仓库与命名空间否则无法实际运行下述用例。第一步评估被测目标The Test Target编写性能测试前首先要确认目标功能是否可测有些功能不需要中间应用可以直接向daprd发起调用并收集结果例如输出型绑定output binding——直接打 daprd 的 HTTP/gRPC 接口即可有些功能必须有应用参与才能测例如任何与 Actor 相关的特性此时就需要一个自定义测试应用作为 Actor 宿主。若需要自定义测试应用请参照仓库 e2e 测试文档 tests/docs/writing-e2e-test.md 的做法创建并优先检查tests/apps目录下已有的应用如actorjava、actorfeatures、service_invocation_http等是否可复用——仓库明确说明这些应用可以无需额外改动直接复用。第二步确定负载形态与压测工具选型负载形态load shape决定了压测类型也决定了选用哪种压测工具。Dapr 目前内置两种工具定位适合场景负载特征FortioQPS 型测试per-tester合成负载、压力测试恒定目标 QPS记录执行时间直方图并计算百分位数如 p99k6脚本化负载测试k6-operator复杂场景编排、自定义指标通过 JavaScript DSL 自由塑造负载形态Fortio 的核心语义Fortio 以指定的 QPS 运行记录执行时间直方图并计算百分位数例如 p99即 99% 的请求耗时小于该值单位秒。它可以按固定时长运行、按固定调用次数运行或持续到被中断在恒定目标 QPS 下或按每连接/线程的最大速率运行。Dapr 使用打过补丁的 Fortio 版本与性能测试应用一起构建该镜像命名为perf-tester——在部署测试基础设施时会频繁见到这个名字。从源码 tests/runner/loadtest/fortio.go 可以看到NewFortio的默认testerImage就是perf-tester默认numHealthChecks为 60 次健康检查。k6 的核心语义k6 与 Fortio 最大的区别在于可脚本化用 JavaScript DSL 编写脚本由 k6-operator 在云端Kubernetes 集群内执行。同一份 JS 测试文件可以轻松组合出不同类型的负载形态并且除了默认指标外还能添加自定义指标。第三步用 Fortio 编写 QPS 型性能测试3.1 目录与构建标签所有性能测试位于tests/perf目录。为测试新建一个文件夹并在其中创建.go文件。不要忘记添加构建标签确保这些文件不会被编入 dapr 正式二进制//go:build perf // build perf仓库中的每个 perf 测试文件如 tests/perf/actor_activation/actor_activation_test.go、tests/perf/state_get_http/state_get_http_test.go都以这两行标签开头正是它们把性能测试与常规构建隔离。3.2 TestMain部署目标应用并等待就绪性能测试与 e2e 测试共用同一套基础设施runner。首先要写TestMain负责部署被测应用并等待其健康var tr *runner.TestRunner func TestMain(m *testing.M) { utils.SetupLogs(my_test) serviceApplicationName : target-app clientApplicationName : fortio-tester testApps : []kube.AppDescription{ { AppName: serviceApplicationName, DaprEnabled: true, ImageName: perf-actorjava, Replicas: 1, IngressEnabled: true, MetricsEnabled: true, AppPort: 3000, DaprCPULimit: 4.0, DaprCPURequest: 0.1, DaprMemoryLimit: 512Mi, DaprMemoryRequest: 250Mi, AppCPULimit: 4.0, AppCPURequest: 0.1, AppMemoryLimit: 800Mi, AppMemoryRequest: 2500Mi, Labels: map[string]string{ daprtest: serviceApplicationName, }, }, { AppName: clientApplicationName, DaprEnabled: true, ImageName: perf-tester, Replicas: 1, IngressEnabled: true, MetricsEnabled: true, AppPort: 3001, DaprCPULimit: 4.0, DaprCPURequest: 0.1, DaprMemoryLimit: 512Mi, DaprMemoryRequest: 250Mi, AppCPULimit: 4.0, AppCPURequest: 0.1, AppMemoryLimit: 800Mi, AppMemoryRequest: 2500Mi, Labels: map[string]string{ daprtest: clientApplicationName, }, PodAffinityLabels: map[string]string{ daprtest: serviceApplicationName, }, }, } tr runner.NewTestRunner(mytest, testApps, nil, nil) os.Exit(tr.Start(m)) }各字段说明AppName/ImageName/Replicas应用名、镜像名与副本数IngressEnabled: true为应用创建 Ingress供压测端从集群外访问MetricsEnabled: true开启指标采集供后续资源消耗统计与 Prometheus 推送AppPort应用监听端口本例被测应用 3000压测端 3001DaprCPULimit/DaprCPURequest/DaprMemoryLimit/DaprMemoryRequestDapr sidecar 的资源限制与请求量AppCPULimit/AppCPURequest/AppMemoryLimit/AppMemoryRequest应用容器的资源限制与请求量PodAffinityLabels将压测端 pod 调度到与被测应用相同/相邻节点daprtest标签亲和降低网络跳数对延迟测量造成的噪声。该示例部署两个应用target-app被测目标与fortio-tester压测发起端。3.3 测试驱动配置参数并下发负载接下来创建测试驱动函数向 fortio 压测端下发命令再由压测端把负载转发给被测应用。首先配置测试参数func TestActorActivate(t *testing.T) { p : perf.Params( perf.WithQPS(500), // 期望的每秒查询数Query Per Second perf.WithConnections(8), // HTTP 连接数 perf.WithDuration(1m), // 测试时长 perf.WithPayload({}), // 测试负载 ) }这些参数决定了针对目标功能的负载形态。从源码 tests/perf/test_params.go 可以看到完整的参数体系与默认值函数 / 字段含义默认值WithQPS(qps)→QPS目标每秒请求数1WithConnections(n)→ClientConnections客户端连接数1WithDuration(d)→TestDuration测试时长支持1m、10s等 Go 时长写法1mWithPayloadSize(kb)→PayloadSizeKB随机负载大小KB0WithPayload(s)→Payload测试负载内容TargetEndpoint被测端点序列化后需手动设置—StdClient是否使用标准客户端—Grpc/Dapr是否走 gRPC、Dapr 能力描述如capabilitystate,targetnoop—参数优先级Params()内部会把手动传入的 option 与从环境变量解析的 option 合并且环境变量优先级最高useEnvVar在 append 列表中位于最后覆盖手动设置。对应环境变量为DAPR_PERF_QPS、DAPR_PERF_CONNECTIONS、DAPR_TEST_DURATION、DAPR_PAYLOAD、DAPR_PAYLOAD_SIZE解析失败时静默忽略toStrParam返回 no-op。3.4 调用压测端并收集结果endpoint : target-app-endpoint p.TargetEndpoint endpoint p.StdClient false body, err : json.Marshal(p) daprResp, err : utils.HTTPPost(fmt.Sprintf(%s/test, fortio-tester-app-endpoint), body)即把TestParameters序列化为 JSONPOST 到压测端应用的/test端点压测端内部执行 Fortio返回 JSON 结果源码见 tests/runner/loadtest/fortio.go 的Run方法json.Marshal(f.params)后HTTPPost(f.testerAppURL/test, body)。最后反序列化结果并做断言var daprResult perf.TestResult err json.Unmarshal(daprResp, daprResult)perf.TestResult的结构定义在 tests/perf/test_result.go关键字段包括ActualQPS实际吞吐量DurationHistogram执行时间直方图Min/Max/Avg/StdDev及Percentiles数组按 0、1、2、3… 索引对应 50th/75th/90th/99th 等百分位RetCodes按状态码统计的请求数Num200/Num204/Num400/Num500Sizes/HeaderSizes响应体与响应头大小分布Exactly、SocketCount、AbortOn等执行细节。基于这些指标即可断言实际 QPS、延迟百分位数等是否达标。参考 tests/perf/actor_activation/actor_activation_test.go 的真实断言模式percentiles : map[int]string{2: 90th, 3: 99th} for k, v : range percentiles { daprValue : daprResult.DurationHistogram.Percentiles[k].Value t.Logf(%s percentile: %sms, v, fmt.Sprintf(%.2f, daprValue*1000)) } // 典型断言 require.Equal(t, 0, daprResult.RetCodes.Num400) require.Equal(t, 0, daprResult.RetCodes.Num500) require.Equal(t, 0, restarts) require.True(t, daprResult.ActualQPS float64(p.QPS)*0.99) require.True(t, daprResult.DurationHistogram.Percentiles[2].Value*1000 15) // p90 15ms require.True(t, daprResult.DurationHistogram.Percentiles[3].Value*1000 35) // p99 35ms该文件还演示了完整的结果输出链路GetAppUsage/GetSidecarUsage/GetTotalRestarts采集资源消耗与重启次数通过summary.ForTest(t)...Flush()落盘utils.LogPerfTestSummary输出汇总。3.5 基线对比模式Baseline对于需要衡量 Dapr 自身开销的场景如状态读取仓库采用基线 Dapr双跑模式见 tests/perf/state_get_http/state_get_http_test.go// 基线测试直连 noop 能力gRPC p.Grpc true p.Dapr capabilitystate,targetnoop p.TargetEndpoint fmt.Sprintf(http://localhost:50001) baselineResp, err : utils.HTTPPost(fmt.Sprintf(%s/test, testerAppURL), body) // Dapr 测试经 sidecar HTTP 状态 API p.Grpc false p.Dapr p.TargetEndpoint fmt.Sprintf(http://127.0.0.1:3500/v1.0/state/inmemorystate/abc123) daprResp, err : utils.HTTPPost(fmt.Sprintf(%s/test, testerAppURL), body)随后逐百分位计算新增延迟added latencyfor k, v : range percentiles { daprValue : daprResult.DurationHistogram.Percentiles[k].Value baselineValue : baselineResult.DurationHistogram.Percentiles[k].Value latency : (daprValue - baselineValue) * 1000 t.Logf(added latency for %s percentile: %sms, v, fmt.Sprintf(%.2f, latency)) }并通过utils.PushPrometheusMetrics(daprMetrics, testLabel, inmemory)把基线延迟、Dapr 延迟、新增延迟、sidecar/应用 CPU 与内存、实际吞吐等推送到 Pushgateway供 Grafana 可视化详见 tests/docs/running-perf-tests.md 的Optional: Visualize Performance Test Metrics一节。第四步用 k6 编写脚本化性能测试4.1 目录约定与两个必需函数在测试驱动.go文件同目录创建一个.js文件建议命名为test.js。k6 压测 pod 与 Dapr sidecar 同在一个 pod 内k6.go中通过注入 sidecar 注解dapr.io/enabled、dapr.io/app-id实现见 tests/runner/loadtest/k6.go 的k8sRun。k6 脚本至少需要实现两个函数teardown关闭 Dapr sidecar确保 Job 成功结束handleSummary把结果以 JSON 形式输出供测试框架消费。const DAPR_ADDRESS http://127.0.0.1:${__ENV.DAPR_HTTP_PORT}/v1.0; // dapr 环境变量自动注入 export function teardown(_) { const shutdownResult http.post(${DAPR_ADDRESS}/shutdown); check(shutdownResult, { shutdown response status code is 2xx: shutdownResult.status 200 shutdownResult.status 300, }); } export function handleSummary(data) { return { stdout: JSON.stringify(data), }; }DAPR_HTTP_PORT等环境变量由 sidecar 注入脚本直接读取即可。警告k6 使用的 JavaScript 运行时非常受限——它基于 dop251/goja目前遵循 ECMAScript 5.1()。展开运算符...等 ES6 特性不可用也不能直接使用 npm如需引入模块必须先用 webpack 或其他打包工具把模块打成单个 JS 文件。4.2 驱动端并行度、日志与运行驱动端有一系列可配置参数从并行度到禁用日志WithParallelism(p)设置用于本次测试的 pod 数量。注意负载形态保持不变虚拟用户数会按并行度平分——例如目标 1000 req/s、并行度 2则两个 pod 各发 500 req/sloadtest.EnableLog()默认 k6 pod 日志是关闭的排查问题时可以启用但启用后测试汇总解析会失败测试合入 master 前必须移除。创建 k6 负载测试结构体并交由平台执行k6Test : loadtest.NewK6(./test.js, loadtest.WithParallelism(1)) require.NoError(t, tr.Platform.LoadTest(k6Test))platform.LoadTest(test)会阻塞直到测试成功结束耗时取决于测试场景。参考 tests/perf/actor_id_scale/actor_id_scale_test.go 的完整用法NewK6(./test.js, loadtest.WithParallelism(5), loadtest.WithRunnerEnvVar(ACTOR_TYPE, actorType))运行前defer k6Test.Dispose()清理资源。4.3 收集结果与断言summary, err : loadtest.K6ResultDefault(k6Test)每个 pod每个并行度单元对应一组指标结构通过.RunnersResults属性访问。测试应当基于阈值决定成败因此除 runner 结果外还提供了.Pass标志用于断言require.True(t, summary.Pass, fmt.Sprintf(test has not passed, results %s, string(bts)))K6ResultDefault返回K6TestSummary[K6RunnerMetricsSummary]其中K6RunnerMetricsSummary定义在 tests/runner/loadtest/k6.go涵盖iterations、http_req_duration趋势、http_req_failed比率、checks、vus/vus_max、data_received/data_sent等标准指标以及按expected_response区分的有/无预期响应延迟。自定义指标使用自定义指标时可用loadtest.K6ResultT——它是一个泛型函数允许把 k6 结果反序列化到你提供的任意结构体上。4.4 测试故障注入可通过 xk6-disruptor 为测试添加故障注入使用其全部能力延迟、错误注入等。注意这是外部项目需在 k6 镜像中预置相应扩展。4.5 Prometheus 指标推送设置以下环境变量即可把 k6 指标发送到远程 Prometheus 服务器便于跨时间的对比分析K6_PROMETHEUS_REMOTE_URL K6_PROMETHEUS_USER K6_PROMETHEUS_PASSWORD4.6 故障排查k6 退出码速查运行 k6 时错误以退出码形式报告错误码原因255编译错误Compile Error137内存溢出OOM107运行时错误Runtime Error第五步运行、选测与产出图表衔接运行文档编写完成后通过 Makefile 目标运行详见 tests/docs/running-perf-tests.md# 运行全部 perf 测试 make test-perf-all # 只运行指定测试DAPR_PERF_TEST 为空格分隔的应用名列表 export DAPR_PERF_TESTactor_id_scale workflows make test-perf-allDAPR_PERF_TEST中的名称取自 tests/dapr_tests.mk 的PERF_TESTS列表当前包含actor_activation等全部 perf 测试目录名而测试应用镜像列表见同文件PERF_TEST_APPS含tester即 Fortio 压测端、k6-custom即 k6 压测端。生成性能图表时从任意一次 perf 运行的gotestsumJSON 报告出发cd tests/perf/report go run . -input path-to-report.json[.gz] -version output-folder结语一条完整的 perf test 编写检查清单评估可测性目标功能能否直接打 daprd还是需要一个中间应用参考tests/apps下的现成应用选择负载形态恒定 QPS 压力 → Fortioperf-tester复杂脚本化场景、自定义指标 → k6。Fortio 路线tests/perf/name/下新建带//go:build perf标签的.go文件 →TestMain部署目标应用与压测端 →perf.Params(...)配置 QPS/连接数/时长/负载 → POST/test→ 反序列化perf.TestResult→ 按ActualQPS、百分位延迟、RetCodes、重启次数断言。k6 路线同目录放置test.js必须实现teardown与handleSummary→loadtest.NewK6(./test.js, ...)配置并行度与 runner 环境变量 →tr.Platform.LoadTest(k6Test)→loadtest.K6ResultDefault(k6Test)取结果、用.Pass断言。锦上添花基线对比模式衡量 Dapr 自身开销PushPrometheusMetrics Grafana 模板tests/grafana/grafana-perf-test-dashboard.json可视化xk6-disruptor 注入故障k6 退出码255/137/107辅助排障。按照这条路径你就能在 Dapr 仓库中产出与现有tests/perf各用例风格一致、可复现、可观测的性能测试。【免费下载链接】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),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号