Rust 异步 HTTP 实战:用 reqwest 与 tokio 并发抓取多个接口
test12026-09-305 次阅读
为什么用 reqwest
Rust 里做 HTTP 客户端,reqwest 是事实标准:它基于 tokio 异步运行时,API 简洁,支持 JSON、超时、拦截器。配合 futures 的 join_all,可以轻松把多个独立请求并发发出去,而不是串行等待。
依赖声明
在 Cargo.toml 里启用 tokio 的完整特性,并给 reqwest 打开 json 特性。
[dependencies]
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.12", features = ["json"] }
futures = "0.3"
发起单个请求
最简单的用法是 reqwest::get 后链式 await,再用 .json 把响应反序列化成 serde 支持的类型。
use reqwest::Error;
#[tokio::main]
async fn main() -> Result<(), Error> {
let resp = reqwest::get("https://api.example.com/health")
.await?
.json::<serde_json::Value>()
.await?;
println!("status: {:?}", resp);
Ok(())
}
并发抓取多个 URL
把抓取逻辑抽成返回 Result 的异步函数,再用 future::join_all 一次性等所有任务完成。每个请求单独设超时,避免某个慢接口拖垮整体。
use futures::future;
use std::time::Duration;
async fn fetch(url: &str) -> Result<String, reqwest::Error> {
let body = reqwest::Client::new()
.get(url)
.timeout(Duration::from_secs(5))
.send()
.await?
.text()
.await?;
Ok(body)
}
#[tokio::main]
async fn main() {
let urls = vec![
"https://api.example.com/a",
"https://api.example.com/b",
"https://api.example.com/c",
];
let results = future::join_all(urls.iter().map(|u| fetch(u))).await;
for (url, res) in urls.iter().zip(results) {
match res {
Ok(body) => println!("{} -> {} bytes", url, body.len()),
Err(e) => eprintln!("{} -> error: {}", url, e),
}
}
}
错误处理与超时要点
- reqwest 的错误实现了 std::error::Error,可以直接用 ? 向上传播,或用 anyhow 收口。
- 每个 Client 请求都设 timeout,否则默认无限等待,一个卡住的远端会让任务长期挂起。
- 复用同一个 reqwest::Client 而不是每次新建,能共享连接池,显著降低握手开销。
- join_all 会并发驱动所有 future,数量很大时要考虑限流,避免瞬间打满文件描述符或对端连接数。
T
test1
文章作者
为什么用 reqwest Rust 里做 HTTP 客户端,reqwest 是事实标准:它基于 tokio 异步运行时...
- 分类
- 技术
- 发布时间
- 2026-09-30
- 字数
- 约 1733 字
- 阅读
- 5 次
