Convex Backend 压测指南:使用 LoadGenerator 对自托管 Convex 实例进行基准测试 数据库后端【免费下载链接】convex-backendThe open-source reactive database for app developers项目地址https://gitcode.com/gh_mirrors/co/convex-backend点击查看免费下载导读本文基于 self-hosted/advanced/benchmarking.md 及仓库中开源的压测工具 LoadGenerator位于 crates/load_generator编写完整讲解如何对自托管self-hosted的 Convex Backend 实例执行负载测试与性能基准测试。读完本文你将掌握LoadGenerator 的整体架构与工作流程、面向自托管实例的两步压测流程部署 ScenarioRunner 函数 运行 LoadGenerator、各类内置 workload 配置的字段含义以及如何编写自定义压测场景与自定义 Convex 函数从而量化评估自托管实例的函数延迟、吞吐量与整体稳定性。注意LoadGenerator 是专用于 Convex 生态的压测工具若你的目标是更通用的 HTTP 层压测可结合本文思路自行扩展本文聚焦仓库中已验证的官方流程。一、LoadGenerator 是什么LoadGenerator 是 Convex 开源仓库中自带的压测与基准测试工具定位是评估 Convex 在不同负载模式下的性能表现。根据 crates/load_generator/README.md它可以测量三方面核心指标函数延迟Function latencyquery / mutation / action / HTTP action 等请求的响应时延吞吐量Throughput在给定速率每秒请求数或并发线程数下后端能承受的处理能力整体稳定性Overall system stability长时间高负载下系统是否出现错误率飙升、内存泄漏或功能异常。工作流程LoadGenerator 的完整工作链路编号遵循原文档如下Provisioning实例准备自动创建provision一个 Convex 实例或直接指向一个已存在的实例下发场景Sending scenarios将预定义或自定义的压测场景发送给 ScenarioRunner收集指标Collecting metrics从已执行的场景中收集性能指标函数执行耗时、事件等生成统计报告Generating reports生成包含延迟指标p50 / p95 / p99 等的详细统计报告可选上报监控系统将指标发送到生产监控系统如 Datadog实现长期观测。架构图原文档给出了如下的组件协作关系LoadGenerator 是中枢它向 ScenarioRunner 发送压测场景ScenarioRunner 再以 query / mutation 的形式访问 Backend被测的 Convex 后端反向地ScenarioRunner 把执行产生的事件Events回传给 LoadGenerator由其生成 Stats Report同时 LoadGenerator 的指标可被 Metrics Collector如 Datadog、Prometheus采集。┌──────────┐ │ Stats │ │ Report │ ┌────────────────┐ ┌───────────────────┐ ┌───────────────┐ └──────────┘ │ │ │ │ queries, │ │ ▲ │ │ Scenarios │ │ mutations │ │ └─────────┬───│ LoadGenerator │──────────▶│ ScenarioRunner │──────────▶│ Backend │ ┌──────────────┐ │ │ │◀──────────│ │◀──────────│ │ │ │ │ │ │ Events │ │ │ │ │ Metrics │ │ └────────────────┘ └───────────────────┘ └───────────────┘ │ Collector │◀─┘ │(e.g. Datadog)│ │ │ └──────────────┘从源码实现看这一架构在 crates/load_generator/src/main.rs 中有明确对应run_workload函数会以node dist/scenario-runner.js --deployment-url backend_url --admin-key admin_key --load-generator-port port --scenarios json的方式直接 spawn 一个 ScenarioRunner 子进程注意源码注释说明必须直接 spawnnode而不能用npm start否则子进程无法从父进程被可靠 kill参见 npm issue #4603LoadGenerator 自身则通过 axum 启动一个 HTTP/WebSocket 服务/sync路由接收 ScenarioRunner 推送回来的事件事件经EventProcessor汇总到Stats在压测时长结束后生成统计报告。二、快速开始运行 LoadGenerator查看帮助在仓库根目录convex目录下执行cargo run -p load_generator --bin load-generator -- --help即可看到全部命令行参数说明。若需要 tracing 日志在命令前加上环境变量RUST_LOGinfo cargo run -p load_generator --bin load-generator -- --help预配置的工作负载仓库的Justfilecrates/load_generator/Justfile预置了多套运行方式核心差异在 provisioner实例供给方self-hosted面向自托管后端本文重点见下一节dev/dev-quick/dev-conductor面向本地开发环境绕过 Big Brain 直接连本地进程dev-bb连本地 Big Brainprod连生产 Big Brain需要设置CONVEX_OVERRIDE_ACCESS_TOKEN环境变量来自 1Password 的密钥。所有预置 workload 命令都带有--stats-report --once --duration 60dev-quick为 10 秒即运行 60 秒、打印统计报告后退出一次。例如just dev light等价于在仓库根目录cargo run --release -p load_generator --bin load-generator \ -- crates/load_generator/workloads/light.json --duration 60 \ --provisioner open-source-release --stats-report --once主要命令行参数结合 crates/load_generator/src/main.rs 中Config结构体的 clap 定义常用参数如下参数说明默认值--workload path位置参数workload 配置文件路径运行时解析为Workload结构必填--duration secsLoadGenerator 运行秒数超时后关闭连接、结束场景必填--stats-report结束后打印统计报告含延迟分位数关闭--once只运行一轮 workload 后退出不加则循环运行关闭--interface/--portHTTP/WebSocket 服务绑定的网卡与端口0.0.0.0/8010--metrics-addrPrometheus 指标导出地址如0.0.0.0:9100无--provisioner name实例供给方open-source-release等与--existing-instance-url互斥二选一必填--existing-instance-url指向已存在实例自托管场景使用需配合 admin key无--existing-instance-admin-key已存在实例的 admin key无--existing-project-slug复用已存在项目配合 provisioner 使用无--skip-build跳过 ScenarioRunner 的构建turbo build关闭--skip-actions-deploy跳过部署 node actions避免在生产创建过多 AWS Lambda关闭--use-preview-deployments预览部署压测模式配合--num-preview-deployments、--num-preview-deployment-pushes关闭三、对自托管 Convex 进行压测核心流程原文档给出的自托管压测流程分两步务必按顺序执行。第 1 步将 ScenarioRunner 函数推送到自托管后端cd npm-packages/scenario-runner npx convex deploy --admin-keyyour-admin-key --urlyour-backend-url强烈警告原文档原文强调不要对生产实例执行此操作这一步会替换掉你的函数deploy会整体覆盖该项目的函数代码。请使用仅用于测试的独立 Convex 后端。第 2 步针对自托管后端运行 LoadGeneratorcd ../../crates/load_generator just self-hosted crates/load_generator/workloads/your-workload.json \ --existing-instance-url your-backend-url \ --existing-instance-admin-key your-admin-keyjust self-hosted展开后的完整命令为来自 Justfilecargo run --release -p load_generator --bin load-generator \ -- --stats-report --once --duration 60 \ crates/load_generator/workloads/your-workload.json \ --existing-instance-url your-backend-url \ --existing-instance-admin-key your-admin-key即以 release 模式构建运行持续 60 秒结束后输出统计报告。从 main.rs 看当同时提供--existing-instance-url与--existing-instance-admin-key时会走run_workload(None, backend_url, admin_key, ...)分支直接对指定实例施压否则走 provisioner 自动供给分支生产供给还会加入最长 30 秒的随机 jitter 避免多实例同时抢占。关于 rate 与线程两种模式详见 main.rs 的Mode枚举rate每秒请求数以固定速率发送请求如 workloads/prod.jsonbenchmark线程数以指定数量的线程连续发请求每个线程串行等待上一个请求响应后才发下一个用于测量后端在最大并发下的极限能力如 workloads/benchmark_query.json。运行期间的内部行为压测启动后LoadGenerator 会依次执行对应 main.rs 的run_workload调用wait_for_http_health等待后端 HTTP 健康检查通过最多重试 2 次、每次间隔 250ms并读取backend_version作为指标标签执行setup按 workload 中的num_rows默认 500与num_vector_rows默认 0向后端写入初始数据构建并 spawn ScenarioRunner 子进程传入部署 URL、admin key、load-generator 端口与场景 JSONLoadGenerator 启动 HTTP/WebSocket 服务在--duration指定的时长内持续接收事件时长结束后向所有 WebSocket 连接发送 Closekill 掉 ScenarioRunner 子进程再等待 10 秒让后端处理完剩余日志事件若指定--stats-report则打印统计报告随后调用fail_if_too_many_errors()——如果错误过多进程以非零状态退出方便 CI 判断压测是否通过。四、workload 配置文件详解workload 是 JSON 文件结构定义在 main.rsstruct Workload { name: String, scenarios: VecScenarioConfig, num_vector_rows: u64, // 初始 setup mutation 写入的向量行数 num_rows: u64, // 初始 setup mutation 写入的消息行数默认 500 }顶层字段字段说明nameworkload 名称会作为指标标签load_description格式为{name}_{duration}sscenarios场景数组每个场景含name、场景专有参数、以及rate或benchmark模式num_vector_rows初始化时写入的向量搜索行数prod.json中为 200num_rows初始化时写入的消息行数默认 500内置场景类型Scenario枚举main.rs支持以下场景覆盖了从普通函数到订阅、搜索、向量搜索、快照导出、HTTP action 的完整能力面场景name字段说明RunFunctionpath模块:函数名、fn_typequery/mutation/action按路径调用 ScenarioRunner 中的 Convex 函数是最通用的场景ObserveInsertsearch_indexesbool建立订阅观察插入事件可选是否涉及搜索索引Search—执行全文搜索压测VectorSearch—执行向量搜索压测SnapshotExport—触发快照导出压测CloudBackup—触发云备份流程压测prod.json中 rate 低至 0.00005ManyIntersectionsnum_subscriptions同时建立大量订阅并产生交叉失效用于压测订阅失效路径HoldSubscriptionsnum_subscriptions、hold_duration_secs、invalidation_interval_secs可选、num_invalidations可选长时间持有订阅并按间隔触发失效RunHttpActionpath、method通过 HTTP 调用 action如POST示例 1prod.json混合负载模拟生产流量workloads/prod.json 是仓库中最全面的混合负载示例模拟了生产环境常见的操作组合带搜索的查询与写入、组件components的 query/mutation、搜索索引观察、全文搜索、向量搜索、定时任务schedule、HTTP action、快照导出与云备份。片段如下{ name: prod, scenarios: [ { name: RunFunction, path: query_index:queryMessagesWithSearch, fn_type: query, rate: 10 }, { name: RunFunction, path: update, fn_type: mutation, rate: 2 }, { name: ObserveInsert, search_indexes: true, rate: 5 }, { name: Search, rate: 6 }, { name: VectorSearch, rate: 5 }, { name: RunHttpAction, path: streaming, method: POST, rate: 2 }, { name: SnapshotExport, rate: 0.0005 }, { name: CloudBackup, rate: 0.00005 } ], num_vector_rows: 200 }注意prod.json中SnapshotExport的 rate 为 0.0005即每 2000 秒一次、CloudBackup为 0.00005每 20000 秒一次这类低频后台任务场景主要是为了模拟真实生产环境中的偶发重操作。示例 2benchmark_query.json线程模式测极限吞吐workloads/benchmark_query.json 展示了 benchmark 模式——用benchmark字段替代rate{ name: benchmark_query, scenarios: [ { name: RunFunction, path: query_index:queryMessagesWithSearch, fn_type: query, benchmark: 80 } ] }含义启动 80 个线程每个线程串行地持续发起queryMessagesWithSearch查询测量后端的极限并发吞吐与延迟。其他内置 workload仓库 crates/load_generator/workloads 目录下还提供了针对不同目的的配置可根据压测目标选用light.json轻量混合负载含 action、搜索、云备份适合快速冒烟测试heavy.json/large.json高负载 / 大数据量压测benchmark_insert.json、benchmark_search.json、benchmark_query_and_insert.json针对单类操作的线程模式极限测试hold_subscriptions.json、many_intersections.json订阅与失效路径专项压测search.json、search_debug.json、vector_search.json搜索与向量搜索专项check_dev.json、empty.json开发/冒烟用repro_memory_leak.json内存泄漏复现场景prod_with_node_actions.json生产混合负载 node actions。五、编写自定义压测场景原文档提供了自定义场景的完整方法在 npm-packages/scenario-runner/convex 目录中自行编写 Convex 函数然后在 workload 配置中以RunFunction场景引用它。约束与步骤函数签名要求函数名不能带参数no arguments。例如query_index.ts中的queryMessagesWithSearch就符合要求将函数放进npm-packages/scenario-runner/convex/目录如新建your_module.ts导出export const yourFunction query({ handler: ... })或对应的mutation/action在 workload JSON 中配置一个RunFunction场景重新npx convex deploy推送函数再运行 LoadGenerator 并指向新的 workload 配置。自定义场景配置模板{ name: your_new_workload, scenarios: [ { name: RunFunction, path: your-new-module:your-function-name, fn_type: mutation, rate: 5 } ] }字段说明name场景名必须为RunFunction或其他内置场景名path模块名:函数名模块名即convex/下.ts文件的 basenamefn_typemutation写入、query查询或action动作三者之一需与函数实际类型一致rate每秒请求数若要用线程模式改为benchmark: 线程数。场景函数示例以仓库自带的 query_index.ts 为例其压测函数queryMessagesWithSearch是典型的带缓存击穿参数的查询通过cacheBreaker随机参数在随机 offset 处查询使请求均匀分布、避免命中缓存从而压测真实的数据库查询路径export const queryMessagesWithSearch query({ args: CACHE_BREAKER_ARGS, handler: async ({ db }, { cacheBreaker }) { // 在随机 offset 处查询均匀分布、不命中缓存 return await queryMessagesHelper( db, global, cacheBreaker, 10, messages_with_search, ); }, }); function queryMessagesHelper( db: DatabaseReader, channel: string, rand: number, limit: number, table: MessagesTable, ) { return db .query(table) .withIndex(by_channel_rand, (q) q.eq(channel, channel).gte(rand, rand), ) .take(limit); }编写自定义场景时可以参考这一模式如果你的目标是压测缓存未命中路径可以引入随机参数打破查询缓存如果目标是压测冷路径或索引路径则聚焦特定索引查询。其余场景插入、更新、搜索、向量搜索、定时调度、HTTP action 等可参考insert.ts、update.ts、search.ts、vectorSearch.ts、schedule.ts、http.ts、openclaurd.ts等现有实现。新增场景类型的扩展方式如果内置场景类型不够用需要同时修改两端遵循 npm-packages/scenario-runner/README.md 的扩展指南在 ScenarioRunner 的index.ts中把场景名加入ScenarioName并接入main控制流编写实现IScenario接口、继承Scenario基类的类放入scenarios目录并从main控制流调用在 LoadGenerator 的Scenario枚举main.rs中新增对应的场景变体。这样新增的场景就能像内置场景一样被 workload JSON 引用并施加负载。六、结果解读与指标观测统计报告加上--stats-report后压测结束会打印统计报告。报告内容由 crates/load_generator/src/stats.rs 生成核心是各类请求的延迟分位数典型如 p50 / p95 / p99与错误统计。同时fail_if_too_many_errors()会在错误过多时让进程以非零状态退出——这一点对把压测接入 CI 回归非常有用可以在每次发布前用固定 workload 对比延迟与错误率是否劣化。Prometheus 指标导出使用--metrics-addr参数可启动 Prometheus exporter如--metrics-addr 0.0.0.0:9100LoadGenerator 会在该地址暴露指标供采集代码路径为 performance_stats/exporter.rs 中的register_prometheus_exportermain.rs。采集到的指标会带上load_description{workload}_{duration}s与backend_version标签方便按 workload 与后端版本维度对比分析。指标标签从 main.rs 可见LoadGenerator 为所有指标附加的关键标签包括load_description格式workload名_时长s例如prod_60sbackend_version被测后端的版本号来自健康检查接口场景名与函数路径metrics::log_target_qps会记录每个场景的目标 QPS。有了这些标签就可以在监控系统中按后端版本、负载类型做横向对比评估新版本是否引入性能回退。七、注意事项与最佳实践综合原文档与源码进行自托管压测时建议遵守以下原则使用专用测试实例npx convex deploy会整体替换实例上的函数绝不要对生产实例执行为压测单独部署一个自托管后端。区分 rate 与 benchmark 模式需要模拟真实流量节奏时用rate每秒请求数需要测量极限并发能力时用benchmark线程数。从轻量 workload 开始先用light.json或自定义的少量场景验证链路部署、setup、事件回传、报告输出正常再逐步加大到heavy.json/prod.json级别的混合负载。关注低频后台场景SnapshotExport、CloudBackup等场景 rate 极低主要模拟生产中的偶发重操作压测时要预留足够时长让它们有机会触发。开启 metrics 导出做长期对比使用--metrics-addr暴露 Prometheus 指标按backend_version标签追踪每次发布后的性能变化。CI 集成利用--once--stats-report的一次性运行模式和错误退出机制fail_if_too_many_errors把压测作为发布前回归检查的一环。充分预热数据workload 顶层的num_rows与num_vector_rows控制 setup 阶段写入的数据量测试搜索 / 向量搜索 / 大表查询前应保证数据规模接近真实负载。参考文档索引自托管压测入口文档self-hosted/advanced/benchmarking.mdLoadGenerator 官方说明crates/load_generator/README.mdScenarioRunner 说明npm-packages/scenario-runner/README.md核心实现crates/load_generator/src/main.rs预置命令crates/load_generator/Justfile内置 workload 目录crates/load_generator/workloads压测场景函数npm-packages/scenario-runner/convex赞分享数据库后端【免费下载链接】convex-backendThe open-source reactive database for app developers项目地址https://gitcode.com/gh_mirrors/co/convex-backend点击查看免费下载相关推荐Convex Scheduling 实战基于 convex-backend 实现 5 秒自毁消息示例应用Convex Scheduling 实战基于 convex backend 实现 5 秒自毁消息示例应用 导读 本文基于 convex backend 仓库中数据库后端Convex Private Demos E2E 测试基于 Playwright 与 convex-local-backend 的本地端到端测试体系Convex Private Demos E2E 测试基于 Playwright 与 convex local backend 的本地端到端测试体系 导读 本数据库后端Convex TypeScript 与 Schema 实战基于 convex-backend 仓库的 Typescript 示例应用全解析Convex TypeScript 与 Schema 实战基于 convex backend 仓库的 Typescript 示例应用全解析 导读 本文以 co数据库后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考