Rust 异步编程深入指南
为什么 Rust 需要异步编程
Rust 的异步编程模型建立在 Future trait 之上,提供了零成本抽象的执行器(executor)和反应器(reactor)。
Future trait 核心
rust
pub trait Future {
type Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}poll 方法被反复调用,直到返回 Poll::Ready。
async/await 语法糖
rust
async fn fetch_data(url: &str) -> Result<String, Error> {
let response = reqwest::get(url).await?;
let body = response.text().await?;
Ok(body)
}async fn 会自动返回一个实现了 Future 的匿名类型。
常见模式
1. 并发请求
rust
let (user, posts) = futures::join!(fetch_user(), fetch_posts());2. 超时控制
rust
let result = tokio::time::timeout(
Duration::from_secs(5),
async_operation()
).await?;3. 选择器
rust
tokio::select! {
_ = timeout => println!("timeout"),
val = receiver.recv() => println!("got: {}", val),
}运行时选择
| Runtime | 特点 | 适用场景 |
|---|---|---|
| Tokio | 功能最全,生态丰富 | 网络服务、复杂异步应用 |
| async-std | 标准库风格 API | 学习、简单项目 |
| smol | 轻量级 | 嵌入式、资源受限 |
性能对比
在 10k 并发连接的基准测试中:
- Tokio:~120k 请求/秒
- async-std:~95k 请求/秒
- 同步:~45k 请求/秒
异步带来的吞吐量提升显著。
踩坑指南
Pinning 问题:
Pin<Box<dyn Future>>在dyn Future场景下必须使用Box::pin()。
Send + Sync:跨线程任务必须满足这两个 trait,否则编译报错。
阻塞操作:在异步上下文中调用同步阻塞函数会导致整个执行器卡死。
小结
Rust 异步编程学习曲线陡峭,但掌握后能写出高性能的并发程序。建议从小项目开始,逐步深入。