性能测试规范
本文引用的文件
- bench/README.md
- bench/k6_short.js
- bench/k6_stream.js
- bench/run_host_regression.sh
- src/engine_runtime.v
- src/worker_backend_runtime_test.v
- admin/ui/app.js
目录
引言
本规范面向 vhttpd 的性能测试与基准测试,覆盖指标定义、压力测试工具使用(k6)、基准回归流程、内存与并发分析方法、以及优化建议。文档基于仓库内现有脚本与运行时实现进行说明,确保可复现与可落地。
项目结构
与性能测试直接相关的目录与文件: - bench:k6 压测脚本与主机回归脚本 - src:引擎运行时与队列/工作进程管理逻辑 - admin/ui:观测面板展示部分指标
graph TB
subgraph "基准测试"
R["run_host_regression.sh"]
K1["k6_short.js"]
K2["k6_stream.js"]
end
subgraph "服务端"
E["engine_runtime.v"]
T["worker_backend_runtime_test.v"]
end
subgraph "观测"
A["admin/ui/app.js"]
end
R --> K1
R --> K2
K1 --> E
K2 --> E
E --> T
E --> A
图表来源 - bench/run_host_regression.sh:1-130 - bench/k6_short.js:1-44 - bench/k6_stream.js:1-52 - src/engine_runtime.v:1-361 - src/worker_backend_runtime_test.v:1-427 - admin/ui/app.js:656-675
章节来源 - bench/README.md:1-158 - bench/run_host_regression.sh:1-130 - bench/k6_short.js:1-44 - bench/k6_stream.js:1-52 - src/engine_runtime.v:1-361 - src/worker_backend_runtime_test.v:1-427 - admin/ui/app.js:656-675
核心组件
- k6 短请求基准脚本:定义 VU 增长阶段、阈值(失败率、延迟分位)与断言,用于快速回归。
- k6 流式基准脚本:针对 SSE/text 流场景,配置更长超时与更宽松的阈值,验证流式吞吐与稳定性。
- 主机回归脚本:一键构建、启动服务、健康检查、执行两类 k6 用例、优雅停止并校验无僵尸 worker。
- 引擎运行时:提供队列容量/超时、等待/拒绝/超时计数、池大小等关键指标;维护 inflight/served 计数与最大请求数触发排空重启。
- 观测面板:聚合 HTTP 请求/错误、路由、WebSocket、运行时长等指标,便于定位瓶颈。
章节来源 - bench/k6_short.js:11-30 - bench/k6_stream.js:12-31 - bench/run_host_regression.sh:18-130 - src/engine_runtime.v:98-110 - src/engine_runtime.v:234-249 - src/engine_runtime.v:293-360 - admin/ui/app.js:656-675
架构总览
从端到端视角,基准测试由 shell 编排,驱动 k6 对目标路径发起请求或建立长连接,服务端通过引擎运行时选择后端执行器与 worker 池,返回响应或流式数据。
sequenceDiagram
participant U as "用户/CI"
participant S as "run_host_regression.sh"
participant H as "vhttpd(引擎)"
participant W as "Worker 池"
participant K as "k6 脚本"
U->>S : 执行回归脚本
S->>H : 启动服务(含参数/端口/池大小)
S->>H : 健康检查 /bench/health
S->>K : 运行短请求基准
K->>H : GET 短路径
H->>W : 选择 worker/入队
W-->>H : 处理完成
H-->>K : 响应
S->>K : 运行流式基准
K->>H : GET 流路径(SSE/text)
H->>W : 流式处理
H-->>K : 持续输出
S->>H : SIGINT 优雅停止
S->>S : 校验无遗留 worker
图表来源 - bench/run_host_regression.sh:56-130 - bench/k6_short.js:32-43 - bench/k6_stream.js:33-51 - src/engine_runtime.v:140-155
详细组件分析
指标定义与采集
- 响应时间:k6 的 http_req_duration 百分位(p95/p99),在短请求与流式脚本中分别设置阈值。
- 吞吐量:由 k6 报告汇总(RPS),结合 VU 曲线与阶段策略评估。
- 资源利用率:通过系统监控(CPU/内存/IO)与内核态统计(队列深度、等待/拒绝/超时计数)综合判断。
- 错误率:k6 的 http_req_failed 比率;服务端队列满/超时也会产生拒绝与超时计数。
- 队列与池状态:队列容量、当前等待数、超时/拒绝累计、池大小、生命周期模式等。
章节来源 - bench/k6_short.js:25-29 - bench/k6_stream.js:26-30 - src/engine_runtime.v:98-110 - src/engine_runtime.v:234-249 - admin/ui/app.js:656-675
压力测试工具与脚本
- 变量约定:统一以 VHTTPD_* 前缀命名,兼容旧名。
- 短请求基准:ramping-vus 阶段化加压,阈值要求失败率极低且 p95/p99 满足 SLA。
- 流式基准:针对 SSE/text 两种模式,延长超时与放宽阈值,断言包含事件片段或有效负载。
- 推荐对比矩阵:固定 tokens 变间隔(隔离传输开销)、固定间隔变 tokens(验证线性扩展)。
章节来源 - bench/README.md:3-15 - bench/README.md:59-100 - bench/README.md:102-158 - bench/k6_short.js:1-44 - bench/k6_stream.js:1-52
基准回归流程(一键回归)
- 构建与准备:按需构建 vhttpd 与依赖,检测 k6 是否安装。
- 启动与就绪:以指定 host/port/pool_size 启动,轮询 /bench/health 直至就绪。
- 执行基准:依次运行短请求与流式基准。
- 优雅退出与清理:发送 SIGINT,等待进程退出,校验无遗留 php-worker 子进程。
- 日志与事件:保留 stdout 与事件日志,便于问题回溯。
flowchart TD
Start(["开始"]) --> Build["构建/准备依赖"]
Build --> StartServer["启动 vhttpd(含参数)"]
StartServer --> Health["健康检查 /bench/health"]
Health --> |成功| RunShort["运行短请求基准"]
Health --> |失败| Fail["输出日志并退出"]
RunShort --> RunStream["运行流式基准"]
RunStream --> GracefulStop["SIGINT 优雅停止"]
GracefulStop --> Verify["校验无遗留 worker"]
Verify --> |通过| Done(["结束"])
Verify --> |未通过| Leak["报告泄漏并退出"]
图表来源 - bench/run_host_regression.sh:18-130
章节来源 - bench/run_host_regression.sh:1-130
队列与 Worker 行为(并发与背压)
- 队列容量与超时:当队列满时直接拒绝;排队等待超过超时则返回“队列超时”。
- 等待/拒绝/超时计数:分别统计,便于区分拥塞类型。
- 最大请求数与排空:达到 max_requests 后标记 draining,空闲后自动重启槽位。
- inflight/served 计数:精确跟踪每个 worker 的请求处理情况。
classDiagram
class EngineRuntime {
+metrics() EngineRuntimeMetrics
+request_started(socket_path)
+request_finished(port, socket_path)
+request_released(socket_path)
+select_socket_queued_for_state(...)
}
class EngineRuntimeMetrics {
+queue_waits_total
+queue_rejected_total
+queue_timeouts_total
+queue_depth
+pool_size
+backend_mode
+queue_capacity
+queue_timeout_ms
+stream_dispatch
+lifecycle
}
class ManagedWorker {
+inflight_requests
+served_requests
+draining
+socket_path
}
EngineRuntime --> EngineRuntimeMetrics : "读取/上报"
EngineRuntime --> ManagedWorker : "更新计数/状态"
图表来源 - src/engine_runtime.v:98-110 - src/engine_runtime.v:234-249 - src/engine_runtime.v:293-360
章节来源 - src/worker_backend_runtime_test.v:111-175 - src/worker_backend_runtime_test.v:177-246 - src/engine_runtime.v:293-360
观测与诊断
- 观测面板聚合:HTTP 请求/错误、路由数量、WebSocket 会话、运行时长等。
- 队列与池信息:通过运行时 metrics 暴露队列深度、容量、超时、池大小等。
- 事件日志:回归脚本输出事件日志,辅助定位异常。
章节来源 - admin/ui/app.js:656-675 - src/engine_runtime.v:234-249 - bench/run_host_regression.sh:29-34
依赖关系分析
- 回归脚本依赖 k6 与 vhttpd 二进制,依赖环境变量控制目标地址、路径、流模式与池大小。
- k6 脚本依赖目标服务的 /bench/health 与流接口,断言响应状态与内容。
- 引擎运行时依赖 worker 后端与 executor 接口,负责调度、队列与生命周期。
graph LR
Shell["run_host_regression.sh"] --> K1["k6_short.js"]
Shell --> K2["k6_stream.js"]
K1 --> API["/bench/health 与业务路径"]
K2 --> Stream["/bench/stream (sse/text)"]
API --> ER["engine_runtime.v"]
Stream --> ER
ER --> WB["worker 后端/队列"]
图表来源 - bench/run_host_regression.sh:56-130 - bench/k6_short.js:32-43 - bench/k6_stream.js:33-51 - src/engine_runtime.v:140-155
章节来源 - bench/README.md:1-158 - src/engine_runtime.v:1-361
性能考量
- 指标基线:为短请求与流式场景分别设定 p95/p99 与失败率阈值,纳入 CI 门禁。
- 场景矩阵:按“固定 tokens 变间隔”和“固定间隔变 tokens”两组对比,分离传输开销与扩展性。
- 队列与池:关注 queue_capacity、queue_timeout_ms、queue_waiting_requests、pool_size 的变化趋势。
- 背压与降级:队列满拒绝与超时是重要信号,需结合应用层重试/熔断策略。
- 资源利用:结合系统级 CPU/内存/IO 与内核队列指标,定位热点路径。
[本节为通用指导,不直接分析具体文件]
故障排查指南
- 服务未就绪:健康检查失败时查看 stdout 日志,必要时检查 Unix domain socket 支持与 worker 命令路径。
- 队列超时/拒绝:若频繁出现“队列超时/队列满”,应提升 pool_size 或增大 queue_capacity/timeout。
- 僵尸进程:回归脚本会校验无遗留 php-worker,若发现泄漏,检查优雅停止与 worker 生命周期。
- 流式异常:确认流模式与路径参数一致,检查服务端流处理与客户端断言条件。
章节来源 - bench/run_host_regression.sh:72-88 - bench/run_host_regression.sh:104-130 - src/worker_backend_runtime_test.v:111-175
结论
本规范将 k6 压测、回归脚本与引擎运行时指标有机结合,形成可重复、可度量、可回归的性能工程体系。通过明确的指标定义、场景矩阵与自动化回归,能够快速发现性能退化并定位瓶颈。
[本节为总结,不直接分析具体文件]
附录
- 变量约定与示例:详见基准 README 中的统一命名与示例命令。
- 推荐对比矩阵:见“Group A/B”组合,便于隔离传输开销与验证线性扩展。
- 回归脚本用法:支持跳过 k6 仅验证生命周期,或自定义端口与池大小。
章节来源 - bench/README.md:3-15 - bench/README.md:102-158 - bench/run_host_regression.sh:40-57