Tokio 概览
Tokio 作为主流 async 运行时的定位:执行器、I/O、定时器、任务与何时引入。
#concept
#growing
#dev
#rust
[!info] related notes
Tokio 概览
这个概念为什么出现
标准库定义了 Future,但没有完整的生产级网络运行时。
Tokio 提供多线程执行器、异步 I/O、定时器、同步原语与生态(hyper 等)基础。
[!abstract] 一句话理解 Tokio 是 Rust 主流 async 运行时:驱动 Future、提供 async I/O 与工具;async 语法本身不提供调度、网络驱动或生产运维能力。
最小可运行示例
场景:并发等待两个定时器
在 Cargo 二进制项目中执行 cargo add tokio@1 --features macros,rt-multi-thread,time,然后替换 src/main.rs:
#[tokio::main]
async fn main() -> Result<(), tokio::task::JoinError> {
let worker = tokio::spawn(async {
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
"worker-done"
});
tokio::time::sleep(std::time::Duration::from_millis(5)).await;
println!("main-progress");
println!("{}", worker.await?);
Ok(())
}
执行 cargo run,依次输出 main-progress 与 worker-done;输出顺序来自打印和 join 的位置,不保证两个计时器在指定毫秒精确唤醒。
结合场景再看三个关注点
- 运行时是依赖不是语言内置
- feature 可裁剪 减体积
- 与 hyper/axum/tonic 生态衔接
核心概念与准确模型
| 组件 | 作用 |
|---|---|
| Runtime | 调度任务 |
tokio::spawn | 任务并发 |
tokio::io / net | 异步 I/O |
sync | 异步锁/channel |
time | 睡眠/间隔/超时 |
多线程运行时可并行调度;current_thread 在调用 block_on 的线程推进任务,不能把并发直接理解为并行。tokio::spawn 通常要求 Future 及输出满足 Send + ‘static;不满足 Send 的本地任务可考虑 LocalSet。
设计动机
- 生产可用的异步栈
- 性能与功能平衡
- 社区事实标准之一
边界与误区
- 在 async 中调用阻塞 std I/O 会占用工作线程;可用 spawn_blocking 承载有限阻塞任务,但已开始的阻塞任务通常不能 abort,CPU 工作还需限制并发
- 运行时嵌套不当
- 版本与 feature 不匹配
[!warning] 常见误区:所有 Rust 项目都要 Tokio CLI/CPU 工具可能不需要。
工程实践
- 显式 features
- 统一超时/取消
- 指标:任务排队、I/O
- 优雅关闭:停止准入、协作通知、等待任务,超时后才取消;丢弃 JoinHandle 仅分离任务,不会自动中止
本节总结
- Tokio = 执行器 + async 设施
- 服务开发常用底座
- 先懂 Future 再绑运行时
自测题
- 没有 Tokio 能写 async fn 吗?
spawn与直接 await 的差异?
参考答案
- 能写,但需要某个执行器来跑。
- spawn 并发调度;直接 await 在当前任务内顺序推进。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Tokio 官网 | 生态 | 总览 |
| Tokio tutorial | 文档 | 入门 |
| docs.rs/tokio | API | 模块 |