oha:带实时 TUI、支持 HTTP/3 的 Rust 压测工具
压测
Rust
HTTP
TUI
开源
性能
2026/10/15
·
阅读时间: 大约 9 分钟
oha:带实时 TUI、支持 HTTP/3 的 Rust 压测工具

压测工具并不少见——本博客之前就写过 Go 生态的 vegeta。oha(读作おはよう)的存在价值不在”又一个发压工具”,而在三个老工具没做好的点上:实时 TUI 仪表盘、对 HTTP/2 乃至 HTTP/3 的一等支持、以及为避免测量失真而内置的延迟校正。它由 hatoo 用 Rust 编写,异步运行时用 tokio,TUI 用 ratatui,明确宣称灵感来自 rakyll/hey。
一、它和 hey / vegeta 到底差在哪

很多人知道 hey 但没用透。oha 在兼容 hey 默认参数的同时,把现代 HTTP 语义补齐了:
- HTTP/2 是一等公民:
-p控制 HTTP/2 上单连接的并行请求数,总并发是c × p; - HTTP/3:通过
--features http3开启(基于 Hyper 团队的 H3 库); - 实时 TUI:压测过程中屏幕上动态画吞吐和延迟直方图,默认 16fps,可用
--fps调;vegeta 要靠事后plot出图,hey 则根本没有交互界面; - 多种输出:text / json / csv / quiet,JSON schema 还单独定义在
schema.json,方便接后续分析。
二、被低估的两个”真实压测”开关
oha README 里 Tips 一节其实是它最有价值的部分——作者直接给了一条”更接近真实用户”的推荐命令:
oha <-z 或 -n> -c <并发连接数> -q <QPS> --latency-correction --disable-keepalive <目标>两个开关各有讲究:
--disable-keepalive:真实用户不会拿同一个 TCP 连接反复请求同一个 URL。默认开着 keep-alive 压出来的延迟,低估了真实建连开销;--latency-correction:这是专门对抗 Coordinated Omission Problem(协同遗漏)的。当压测端自己成为瓶颈、发不出去请求时,被漏掉的请求会让统计出来的延迟偏乐观;开启后校正这个偏差。注意它只在设了-q(限速)时才生效。
这里有个和 hey 的语义差异必须说清楚:oha 的 -q 是全局总 QPS,而 hey 的 -q 是每个 worker 各自的 QPS。从 hey 迁过来的人如果照抄参数,实际压力会差好几倍。
三、Rust/tokio 带来的工程细节
--no-tui更快:因为不开实时采集就省掉了聚合开销;README 进一步指出,当--no-tui且既没设-q也没设--burst-delay时,路径最快;- PGO 构建:官方提供 Profile-Guided Optimization 的产物(
cargo-pgo),把压测机自身开销再压低; - 并发模型:默认 tokio worker 线程数等于物理 CPU 核数,可用
--worker-threads覆盖; - 动态流量:
--rand-regex-url用 rand_regex 按正则生成 URL(如http://127.0.0.1/[a-z][a-z][0-9]),--urls-from-file从文件读一组 URL 随机打——后者特别适合拿 access log 还原真实流量分布。
四、关键参数与边界
| 维度 | 官方描述 |
|---|---|
| 默认 | -n 200 请求、-c 50 连接 |
| HTTP 版本 | 0.9/1.0/1.1/2 稳定;3 为实验特性 |
| 限速 | -q 全局 QPS;--burst-delay/--burst-rate 突发 |
| 输出 | text / json / csv / quiet |
| 签名 | 内置 AWS SigV4(--aws-sigv4) |
| 运行时 | Rust + tokio,PGO 可选 |
五、官方自曝的局限(重要)
作者没有回避问题,README 里写得很直白:
- HTTP/3 仍是实验特性:官方原话是”只要 H3 库还在实验阶段,oha 的 HTTP/3 就保持实验状态”,且目前依赖 rustls 做 TLS;
- HTTP/2 下不支持重定向(
-r)、也不支持--disable-keepalive——这两个语义在 HTTP/2 多路复用模型里本就不适用; - 动态 scheme/host/port 配合 keep-alive 目前工作不正常,
--rand-regex-url场景要注意; - 作者自谦:“我是 tokio 新手,请求调度还有优化空间”——性能上限不必吹得太满。
输出侧也值得一提:默认 text 是一份人类可读的统计摘要,而 --output-format json 会吐结构化结果,其 schema 被单独固化在仓库的 schema.json 里。这意味着你可以把 oha 的结果喂给后续脚本做趋势对比,或用 csv 格式把每个请求的耗时落表再离线分析;--db-url 甚至能把成功请求直接写进一个 sqlite 文件。再加上 --stats-success-breakdown 可以按状态码把成功/失败拆开算延迟直方图——这些都是把”压测”从一次性命令变成可积累实验数据的配套能力,也是它比 hey 这种”跑完打印一段就结束”的工具更适合反复用的原因。
六、客观分析:优势与局限
优势:
- 实时可视:边压边看 TUI,定位”是吞吐上不去还是延迟飘了”比事后出图快;
- 现代协议覆盖:HTTP/2 调
-p、实验性 HTTP/3,是老 Go 工具没有的; - 测量方法论自觉:延迟校正、关 keep-alive、限速语义,说明作者懂压测失真;
- Rust 单二进制分发:brew/winget/pacman/Docker 都有,压测机上不用装运行时。
局限:
- HTTP/3 不能当生产依据:实验特性,测出来的 HTTP/3 数字别直接写进结论;
- TUI 本身有开销:要极致施压时得
--no-tui; - 不做分布式压测:oha 是单机发压,要打超大规模还得叠加 vegeta 那种多机编排或 k6。
七、适合谁
- 想在终端里边压边看曲线、又需要测 HTTP/2 服务的工程师;
- 对”压测数字是否可信”敏感、想要延迟校正的人;
- 想尝鲜 HTTP/3 端点性能的人。如果你要的是可复现的分布式基准、或者已经在 vegeta/k6 流水线里跑顺了,oha 更适合作为本地快速冒烟和实时观察的补充,而非替代。