解读 oha 完整 CHANGELOG:从 0.4.1 到 1.16.0 的 HTTP 压测工具版本演进
解读 oha 完整 CHANGELOG:从 0.4.1 到 1.16.0 的 HTTP 压测工具版本演进
oha(おはよう)是一款用 Rust 编写的 HTTP 负载生成器,灵感来自 rakyll/hey,并内置实时 TUI 动画。本文以仓库中的 CHANGELOG.md 为主体,完整梳理该项目自 2020-07 的 0.4.1 到 2026-08 的 1.16.0 共 40 余个版本的迭代脉络,并结合 Cargo.toml(当前 version = "1.16.0",与 CHANGELOG 最新条目一致)和 src/ 下的源码实现,逐条印证关键特性的落地方式,帮助你快速判断各版本的能力边界并选择适合的构建与运行配置。
一、CHANGELOG 的阅读方式与版本约定
CHANGELOG.md 采用“倒序 + 锚点”的组织方式:
- 文件顶部是
# Unreleased区块,用于累积尚未发布的变更(当前仓库中该区块为空,说明 1.16.0 之后暂无已记录的新变更); - 每个已发布版本以
# <版本号> (<发布日期>)作为二级锚点,版本号的命名遵循语义化版本; - 每条变更附带上游 PR/Issue 编号(如
#894、#893),可用于追溯具体改动; - 存在一个特殊版本
1.0.0-rc.4.a8dcd7ca5df49c0701893c4d9d81ec8c1342f141 (2023-10-14):CHANGELOG 明确说明它是 1.0.0 的 RC 发布,版本号由当时依赖的未发布hyper版本与 commit hash 组成,且由于依赖未发布版 hyper,该版本只以二进制发布、不上 crates.io。
下面第二节先给出全量版本清单(完整继承 CHANGELOG 的每一条记录),第三节与第四节再对信息密度最高的 1.16.0 和 1.15.0 做源码级详解,最后按主题归纳几条贯穿多个版本的功能演进线。
二、全量版本清单(0.4.1 → 1.16.0)
下表逐条对应 CHANGELOG.md 中的原始条目,未做任何删减:
| 版本 | 发布日期 | 变更内容 |
|---|---|---|
| Unreleased | - | 暂无已记录变更 |
| 1.16.0 | 2026-08-23 | 支持 HTTP QUERY 方法(#894);新增 --worker-threads 选项设置 tokio worker 线程数(#893);调优 HTTP/3 客户端性能(#892);汇总输出避免使用不常见的 10s / 10m 时间刻度(#891) |
| 1.15.0 | 2026-07-11 | 默认重定向上限改为 0(#887);修复 NO_COLOR 环境变量处理(#886);输出中新增 metrics 字段(#882);连接数收敛到所需最小值(#874);支持 shell 自动补全(#861) |
| 1.14.0 | 2026-02-28 | 修复 latency_correction 的潜在 bug(#857) |
| 1.13.0 | 2026-02-07 | JSON 输出新增 first byte 统计(#844);HTTP/3 使用 IPv6 时绑定 IPv6 地址(#839);macOS 上 localhost 优先解析 IPv6(#837) |
| 1.12.1 | 2025-11-29 | 提供带更好构建缓存的官方 Docker 镜像(#830) |
| 1.12.0 | 2025-11-29 | 修复 DNS 与连接耗时统计(#816);为 --help/-h 增加颜色(#822);--disable-color 更名为 --no-color(#824);修复 --urls-from-file 复用其他 URL 的 host 与 path 的 bug(#825) |
| 1.11.0 | 2025-11-01 | n_requests 支持小数值(如 2.6k、0.001m)(#808);connect-to 改为真实 TCP 连接而非仅 DNS 缓存(#807);连接超时可配置(#805);n-requests 支持 k/m 后缀(#800);支持按行从文件读取请求体(#729 #789) |
| 1.10.0 | 2025-09-06 | 修复 HTTP/2/HTTP/3 下的 DNS 解析(#771);新增 curl 兼容的多部分表单数据 -F 选项(#755) |
| 1.9.0 | 2025-06-21 | 实验性 HTTP/3 支持(#746);数据库表已存在时允许追加写入(#742);新增 -u/--time-unit 选项(#741);新增 RequestResult.first_byte 字段测量首个响应体字节时延(#727);支持 CSV 结果输出(#725);支持小数 QPS(#724) |
| 1.8.0 | 2025-02-15 | 支持 mTLS(#687);支持 Proxy 自定义请求头(#688);--connect-to 存在多个匹配项时随机选择(#695) |
| 1.7.0 | 2025-02-01 | 支持使用 SigV4 签名调用 AWS API(#666);支持 -o 输出选项(#669) |
| 1.6.0 | 2025-01-11 | 支持从文件读取 URL 列表(#639);--no-tui 模式增加优化后的 worker(#646) |
| 1.5.0 | 2024-12-07 | 新增 --debug 选项查看实际请求/响应;颜色方案切换为按延迟阈值着色(#610,修复 #609);修复 -q 模式下卡死问题(#603);支持 HTTP 代理(#614) |
| 1.4.7 | 2024-10-26 | rustls 下缓存 HTTPS 证书 |
| 1.4.6 | 2024-08-17 | 新增 --wait-ongoing-requests-after-deadline 选项;新增 --db-url 选项将结果存入 SQLite 数据库;新增 --dump-urls 选项调试随机 URL 生成 |
| 1.4.5 | 2024-05-29 | 若干性能改进 |
| 1.4.4 | 2024-04-20 | 支持 Termux(#464) |
| 1.4.3 | 2024-04-06 | 修复 rustls 报错(#452) |
| 1.4.2 | 2024-04-06 | 修复 Size/request 打印(#447) |
| 1.4.1 | 2024-03-16 | 启用 Profile-Guided Optimization(PGO)(#268) |
| 1.4.0 | 2024-03-09 | unix socket 或 vsock 场景下不做 DNS 查询(#418);新增 HTTP over VSOCK 支持(#416) |
| 1.3.0 | 2024-02-04 | 优化 timeout(#403);错误输出更紧凑(#402);修复 TUI 布局(#401) |
| 1.2.0 | 2024-02-03 | 无参数时打印帮助信息(#378);启动时预解析 DNS 并缓存(#391);上报到达 deadline 的请求(#392);修复 macOS 崩溃问题(#384) |
| 1.1.0 | 2024-01-16 | HTTP/2 连接失败时重连 TCP(#369) |
| 1.0.0 | 2023-11-16 | 升级 hyper 依赖到 1.0.0 |
| 1.0.0-rc.4.a8dcd7ca… | 2023-10-14 | 1.0.0 的 RC 发布;支持 HTTP/2(#224 #201);rustls 成为默认 TLS 后端(#331);新增 -p 选项设置 HTTP/2 并行请求数 |
| 0.6.5 | 2023-10-09 | 修复 Apple Silicon 二进制发布(#323) |
| 0.6.4 | 2023-09-24 | 修复 -H 选项覆盖默认值的行为(#309);展示 99.90、99.99 百分位延迟(#315) |
| 0.6.3 | 2023-09-05 | 为 summary 视图增加样式与颜色(#64);新增 --stats-success-breakdown 按成功/失败状态码细分统计(#212) |
| 0.6.2 | 2023-08-12 | 支持 Burst 突发模式(#276) |
| 0.6.1 | 2023-07-12 | 修复发送 HTTP uri 的问题(#255);增加默认 User-Agent 头(#257) |
| 0.6.0 | 2023-06-24 | 支持 IDNA(#236);支持基于 rand_regex crate 的随机 URL 生成 |
| 0.5.9 | 2023-06-12 | 修复 -H Header 解析器;printer 更新(#229):Success rate 改用百分比(#228);"Latency distribution" 更名为 "Response time distribution" |
| 0.5.8 | 2023-03-25 | unix profile 下支持 --unix-socket 承载 HTTP(#220);TUI 不再强制要求 True Color(#209) |
| 0.5.7 | 2023-02-25 | 修复 --latency-correction 误将 DNS 时间计入延迟(#211);修复 -z 在 deadline 到达时取消 worker 的行为(#211);修复直方图对齐(#210) |
| 0.5.6 | 2023-02-02 | clap 升级到 4;发布 musl 静态二进制(#206);--connect-to 的 requested_host 支持 IPv6 格式(#197) |
| 0.5.5 | 2022-09-19 | TUI 视图增加颜色(#64) |
| 0.5.4 | 2022-08-27 | 支持 IPv6 host(#181);JSON 输出中 RPS 增加 min/max/average/pXX 统计(类似 bombardier)(#177);新增 JSON 输出(#169);修复 QPS 控制首 1 秒的发送速率;直方图与 hey 保持兼容(#161) |
| 0.5.3 | 2022-07-16 | connect-to 支持带方括号的 IPv6 语法 |
| 0.5.2 | 2022-04-28 | 新增 rustls feature,可替代 native-tls 构建 |
| 0.5.1 | 2022-03-29 | 修复直方图显示错误响应时间的问题(#157) |
| 0.5.0 | 2022-01-01 | 用 clap 3.0.0 替换 structopt(#131) |
| 0.4.6 | 2021-07-05 | 新增 --latency-correction,规避 Coordinated Omission Problem |
| 0.4.5 | 2021-05-04 | stdout 非 TTY 时自动设置 --no-tui |
| 0.4.4 | 2020-11-18 | 升级 resolv-conf 以支持 /etc/resolv.conf 中的 options edns0 trust-ad |
| 0.4.3 | 2020-11-12 | 新增 --connect-to 选项,按 curl 的方式覆写指定 host+port 的 DNS |
| 0.4.2 | 2020-10-06 | 提升 WSL Ubuntu 20.4 上的性能 |
| 0.4.1 | 2020-07-28 | 支持 -q 0 表示不限 QPS;修复 QPS 限流下的性能问题 |
三、1.16.0 逐条详解:方法、线程、HTTP/3 与时间刻度
3.1 支持 HTTP QUERY 方法(#894)
CHANGELOG 中这条对应 src/main.rs 中的参数定义:
#[arg(
help = "HTTP method",
short = 'm',
long = "method",
default_value = "GET"
)]
method: http::Method,
从源码结构看,-m/--method 直接以 http::Method 作为 clap 的 value parser,而 http::Method 的 FromStr 实现接受任意大写方法名,因此 oha -m QUERY http://example.com 可以直接发出非标准方法请求,无需硬编码白名单。另外 src/main.rs 还有一处联动逻辑:使用 -F 表单数据且方法仍为 GET 时会自动改写为 POST。
3.2 新增 --worker-threads 选项(#893)
该选项控制 tokio 异步运行时的原生线程数。三处源码证据相互印证:
- 字段声明为
std::num::NonZeroUsize(src/main.rs),从类型层面就排除了 0 值; - 运行时构建(src/main.rs):
let rt = tokio::runtime::Builder::new_multi_thread()
.worker_threads(opts.worker_threads.get())
.enable_all()
.build()
.unwrap();
- 测试用例 src/main.rs 验证了三个行为:未设置时默认取物理 CPU 核数(
num_cpus::get_physical());--worker-threads 4正常解析;0与-1均被拒绝。README 中的帮助文本进一步说明优先级:该选项优先于TOKIO_WORKER_THREADS环境变量,二者都未设置时回退到物理核数。
3.3 调优 HTTP/3 客户端性能(#892)
HTTP/3 客户端位于 src/client_h3.rs,其依赖链在 Cargo.toml 的 http3 feature 中声明:h3 0.0.8 + h3-quinn 0.0.10 + quinn 0.11.7(含 aws-lc-rs 加密后端)。CHANGELOG 只记录这是一次性能调优,具体改动需结合该条目对应的上游 PR 追溯;可确认的前提是 HTTP/3 在 README 中始终被标注为 experimental,且当前依赖 rustls 作为 TLS 实现。
3.4 汇总输出避免 10s / 10m 时间刻度(#891)
CHANGELOG 这条“避免不常见时间刻度”的改动落在 src/timescale.rs。该枚举包含 TenSeconds、TenMinutes 等变体,TUI 进度场景会用它们做平滑刻度,但汇总输出会跳过。源码中的文档注释直接说明了原因:
/// TimeScale::TenSeconds and TimeScale::TenMinutes are not used for summary output. Because it is looked weird to see "10 sec" or "10 min" in summary output.
同时 src/timescale.rs 中 TimeScale::TenSeconds | TimeScale::TenMinutes => None 表明这两个刻度没有对应的文本单位;单测(src/timescale.rs)还断言了各时长区间到刻度的映射(如 1.1~10.0 秒取 Second,10.1~60 秒区间在 TUI 中落到 TenSeconds,而 summary 会直接跨过它到 Minute)。
四、1.15.0 逐条详解:重定向、颜色、metrics 与 shell 补全
4.1 默认重定向上限改为 0(#887)
参数定义在 src/main.rs,帮助文本明确语义:Limit for number of Redirect. Set 0 for no redirection. Redirection isn't supported for HTTP/2.。客户端侧,连接结构体的默认值 redirect_limit: 0 见 src/client.rs;当 redirect_limit != 0 且收到重定向状态时,src/client.rs 会进入重定向处理逻辑,并沿 location 头递归跟随(src/client.rs),每跟一次 limit - 1。这意味着 1.15.0 起默认行为与 curl 的“不自动跟随”一致,需要跟随时必须显式传 -r N。
4.2 修复 NO_COLOR 环境变量处理(#886)
--no-color 选项在帮助中标注了 <a href="https://link.gitcode.com/i/3b76297cdf5394204b19f5b2eea03c0a" target="_blank">env: NO_COLOR=](空值即生效),与 [src/main.rs 的测试用例一致:
#[test]
fn test_no_color_cli_flag() {
let matches = Opts::command()
.mut_arg("no_color", |arg| arg.env(None))
.try_get_matches_from(["oha", "--no-color", "http://example.com"])
.unwrap();
assert!(matches.get_flag("no_color"));
}
从源码结构看,该修复保证 NO_COLOR 环境变量按 no-color 约定(存在即生效,不要求特定值)被正确解析,而不是只在设置具体值时生效。
4.3 输出中新增 metrics 字段(#882)
JSON 输出的结构定义在 src/printer.rs:
#[derive(Serialize)]
struct Metrics {
success_rate: f64,
requests_per_sec: f64,
latency_ms: LatencyMs,
}
#[derive(Serialize)]
#[serde(rename = "latency_ms")]
struct LatencyMs {
min: f64, mean: f64, p50: f64, p95: f64, p99: f64, max: f64,
}
metrics 作为 Result 的顶层字段与 summary 并列输出(src/printer.rs)。summary 面向完整统计,metrics 则提供一段“一眼可读”的核心指标(成功率、RPS、延迟分位),便于脚本或 Agent 直接从 --output-format json 结果中抽取。JSON 输出字段的完整约束可对照 schema.json。
4.4 连接数收敛到所需最小值(#874)
从源码结构看,这与打开文件数(ulimit -n)的跟踪直接相关:src/monitor.rs 在 TUI 启动时读取 RLIMIT_NOFILE,并周期性地通过 /dev/fd 统计当前打开文件数(src/monitor.rs)展示在界面上。可以推断,该变更让实际建立的连接数按需收敛,避免 -c 设置过大时把文件描述符耗尽,从而把“连接数”从用户猜测值变成受运行时约束管理的量。
4.5 支持 shell 自动补全(#861)
实现基于 clap_complete(依赖声明见 Cargo.toml)。src/main.rs 定义了一个隐藏的 --completions 参数,取值类型为 clap_complete::Shell;src/main.rs 在参数出现时直接向 stdout 生成对应 shell 的补全脚本后退出:
if let Some(shell) = opts.completions {
clap_complete::generate(shell, &mut Opts::command(), "oha", &mut std::io::stdout());
return;
}
即在终端执行 oha --completions bash(或 zsh/fish 等 shell 名)即可得到补全脚本,无需额外子命令体系。
五、贯穿版本史的五条功能演进线
5.1 协议线:HTTP/1 → HTTP/2 → HTTP/3
- 1.0.0-rc.4(2023-10-14):支持 HTTP/2(#224 #201),同时把
rustls设为默认 TLS 后端(#331),新增-p控制单连接上的并行请求数(README 中说明总并发为c * p); - 1.1.0(2024-01-16):HTTP/2 下 TCP 连接失败时自动重连(#369),提升长压测稳定性;
- 1.9.0(2025-06-21):实验性 HTTP/3(#746),对应该 feature 在 Cargo.toml 中的
h3/quinn依赖与 src/client_h3.rs 实现; - 1.13.0:HTTP/3 在 IPv6 场景下正确绑定 IPv6 地址(#839);
- 1.16.0:对 HTTP/3 客户端做性能调优(#892)。README 明确提示:只要上游
h3库还是实验状态,HTTP/3 支持就保持 experimental,并且依赖rustls。
5.2 URL 生成线:静态 URL → 正则随机 → 文件列表
- 0.6.0(2023-06-24):引入
rand_regex生成随机 URL(--rand-regex-url,点号不作正则解释,可用--max-repeat限制重复次数); - 1.4.6(2024-08-17):新增
--dump-urls调试随机 URL 生成; - 1.6.0(2025-01-11):
--urls-from-file从文件逐行读取真实 URL 列表(#639),适合把 access log 转成更真实的负载分布; - 1.11.0:
--connect-to从“仅 DNS 缓存”升级为真实 TCP 连接覆写(#807),并支持连接超时配置(#805)。
5.3 统计与输出线:文本 summary → JSON → CSV → metrics
- 0.5.4(2022-08-27):JSON 输出首次落地(#169 #177);
- 0.6.4:补充 p99.90/p99.99 分位(#315);
- 1.9.0:
--output-format csv逐请求输出(src/printer.rs 的print_csv负责表头与行格式);-u/--time-unit允许强制 ns/us/ms/s/m/h 单位;RequestResult.first_byte记录首个响应体字节时延; - 1.13.0:first byte 统计进入 JSON 输出——src/result_data.rs 提供
first_byte_stat,src/printer.rs 输出firstByteHistogram/firstBytePercentiles,并在details中给出firstByte的 average/fastest/slowest; - 1.15.0:顶层新增
metrics字段(见 4.3 节); - 1.16.0:summary 时间刻度规避 10s/10m(见 3.4 节)。
5.4 TLS 与认证线:native-tls → rustls 默认 → mTLS → SigV4
- 0.5.2(2022-04-28):
rustls作为 feature flag 可选构建,即 README 中的cargo install --no-default-features --features native-tls oha反选项; - 1.0.0-rc.4:
rustls成为默认后端(与 Cargo.toml 中default = ["rustls"]一致); - 1.4.7(2024-10-26):rustls 下缓存 HTTPS 证书,降低 TLS 握手开销;
- 1.8.0(2025-02-15):支持 mTLS(
--cert/--key成对指定)与--proxy-header; - 1.7.0(2025-02-01):SigV4 签名调用 AWS API(#666),对应 src/aws_auth.rs,
--aws-sigv4参数格式为aws:amz:region:service,-a可传access_key:secret_key凭证,可选--aws-session传会话令牌。
5.5 运行时、构建与分发线
- 1.4.1(2024-03-16)启用 PGO:构建脚本 pgo.js 用 bun 驱动三段流程——先启动本地负载服务器(pgo/server/src/main.rs),再
cargo pgo run -- --profile pgo -- -z 1m -c 900 --no-tui http://localhost:8888采集采样,--keep-profiles补一轮-n 1000000,最后cargo pgo optimize build;Cargo.toml 的[profile.pgo]采用opt-level = 3、lto = true、codegen-units = 1、panic = "abort"等激进的 release 配置,README 说明产物位于target/[target-triple]/pgo/oha; - 1.4.0(2024-03-09):HTTP over VSOCK(#416,对应
vsockfeature 与tokio-vsock依赖),并在 unix socket/vsock 场景跳过 DNS; - 1.6.0(2025-01-11):
--no-tui模式引入优化 worker,README“Performance”一节说明当--no-tui且未设-q/--burst-delay时会走更快实现,省去实时采集开销; - 1.12.1(2025-11-29)官方 Docker 镜像:Dockerfile 采用多阶段构建,
cargo-chef生成recipe.json做依赖缓存(chef → planner → builder 三阶段),最终运行镜像基于fedoraproject/fedora-minimal,二进制经strip后以USER 65535(非特权用户)运行; - 1.16.0(2026-08-23):
--worker-threads把 tokio 线程数从“隐式默认”变为显式可调(见 3.2 节)。
六、基于当前仓库的选型与安装建议
当前仓库 Cargo.toml 的 version = "1.16.0"、rust-version = "1.88",与 CHANGELOG 最新已发布版本一致,因此下列说明都以 1.16.0 的能力边界为前提:
- 常规安装:
cargo install oha(依赖 make/cmake);包管理器路径包括 Arch 的pacman -S oha、macOS 的brew install oha、Windows 的winget install hatoo.oha,均可在 README.md 中核对; - TLS 后端选择:默认
rustls;需要系统证书库语义时改用cargo install --no-default-features --features native-tls oha; - 实验性协议:HTTP/3 必须
--features http3且依赖 rustls,VSOCK 必须--features vsock; - 性能取向:追求极致性能可参考 README 的 PGO 流程(
bun run pgo.js,前置cargo install cargo-pgo);容器化部署直接使用官方镜像或docker build -t hatoo/oha:latest .本地构建; - 脚本化集成:需要 JSON/CSV 结构化结果时用
--output-format json|csv配合-o落盘,JSON 结构以 schema.json 为准;补全脚本用隐藏的oha --completions <shell>生成(见 4.5 节); - 版本能力核对:若你的场景依赖 mTLS/代理(需 ≥1.8.0)、SigV4(≥1.7.0)、CSV(≥1.9.0)、first byte JSON 统计(≥1.13.0)、metrics 字段与默认不跟随重定向(≥1.15.0)、
--worker-threads(=1.16.0),可对照第二节的版本清单确认目标环境安装的是否为所需版本。
七、小结
CHANGELOG.md 记录了 oha 约六年间 40 余个版本的完整轨迹:从 0.4.x 的 QPS 限流修复,到 1.0 系列完成 HTTP/2 与 rustls 默认化的架构切换,再到 1.x 系列围绕 HTTP/3 实验支持、多维输出(JSON/CSV/metrics/first byte)、AWS SigV4 与 mTLS 等企业级能力持续扩展。结合 src/main.rs、src/client.rs、src/printer.rs、src/timescale.rs 等源码可以确认,CHANGELOG 中每条带编号的变更都能在实现中找到对应落点,这份文档与代码库保持高度一致,是理解各版本能力边界的第一手资料。