解读 oha 完整 CHANGELOG:从 0.4.1 到 1.16.0 的 HTTP 压测工具版本演进

原创2026-10-13 17:28:391,845 阅读
文章标签:性能测试CLI

解读 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 异步运行时的原生线程数。三处源码证据相互印证:

  1. 字段声明为 std::num::NonZeroUsize(src/main.rs),从类型层面就排除了 0 值;
  2. 运行时构建(src/main.rs):
let rt = tokio::runtime::Builder::new_multi_thread()
    .worker_threads(opts.worker_threads.get())
    .enable_all()
    .build()
    .unwrap();
  1. 测试用例 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,对应 vsock feature 与 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 的能力边界为前提:

  1. 常规安装:cargo install oha(依赖 make/cmake);包管理器路径包括 Arch 的 pacman -S oha、macOS 的 brew install oha、Windows 的 winget install hatoo.oha,均可在 README.md 中核对;
  2. TLS 后端选择:默认 rustls;需要系统证书库语义时改用 cargo install --no-default-features --features native-tls oha;
  3. 实验性协议:HTTP/3 必须 --features http3 且依赖 rustls,VSOCK 必须 --features vsock;
  4. 性能取向:追求极致性能可参考 README 的 PGO 流程(bun run pgo.js,前置 cargo install cargo-pgo);容器化部署直接使用官方镜像或 docker build -t hatoo/oha:latest . 本地构建;
  5. 脚本化集成:需要 JSON/CSV 结构化结果时用 --output-format json|csv 配合 -o 落盘,JSON 结构以 schema.json 为准;补全脚本用隐藏的 oha --completions <shell> 生成(见 4.5 节);
  6. 版本能力核对:若你的场景依赖 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 中每条带编号的变更都能在实现中找到对应落点,这份文档与代码库保持高度一致,是理解各版本能力边界的第一手资料。

登录后查看全文
oha