如何提升reqwest库的请求性能?实测与ureq性能差距达60倍
提升reqwest请求性能的方案
核心原因分析
你看到的性能差距主要来自两个关键点:
reqwest::get()每次调用都会新建一个Client实例,而Client的初始化包含连接池、DNS解析器、TLS上下文(即使是HTTP请求,默认Client也会带TLS支持)等开销,这部分在首次请求时尤为明显。- 异步运行时(tokio)的首次启动调度也会产生少量额外开销,而ureq是同步库,不存在这部分开销。
优化方案
1. 复用reqwest Client实例
这是最关键的优化,reqwest的Client被设计为可复用的,它会维护连接池,彻底避免重复初始化的开销。修改你的测试代码如下:
use tokio::time::Instant; use reqwest::Client; const URL: &str = "http://localhost:3000/health"; #[tokio::main] async fn main() { // 提前创建Client,复用整个程序生命周期 let client = Client::new(); { let now = Instant::now(); client.get(URL).send().await.unwrap(); println!("reqwest (reused client): {:.3?}", now.elapsed()); } { let now = Instant::now(); ureq::get(URL).call().unwrap(); println!("ureq: {:.3?}", now.elapsed()); } }
复用Client后,首次请求的开销会大幅降低,后续请求的性能会和ureq接近,甚至在并发场景下更优。
2. 针对HTTP请求禁用TLS支持
如果你只需要发送HTTP请求,可以创建不带TLS的Client,进一步减少初始化开销:
let client = Client::builder() .no_tls() .build() .unwrap();
3. 并发场景下的优化
在高并发/并行场景下,reqwest的异步模型优势会体现出来,但需要注意:
- 始终复用同一个Client实例,它会自动管理连接池,避免频繁创建连接。
- 调整Client的连接池配置,比如增大单主机最大空闲连接数:
let client = Client::builder() .pool_max_idle_per_host(50) .build() .unwrap(); - 使用tokio的任务调度批量处理请求,避免阻塞异步任务执行。
优化后的性能表现
复用Client后,首次reqwest请求的耗时会降到和ureq同一量级(几百微秒);在并发场景下,reqwest的异步模型能更好地利用系统资源,性能会超过同步的ureq。
内容的提问来源于stack exchange,提问作者Gaëtan Lehmann
相关产品推荐
相关产品推荐

