异步 Rust 的演进:从 Tokio 基础到高层应用开发
免责声明:本文是使用 AI 辅助写作和通信工具创建的。在它的帮助下,这次内容丰富且细致的直播的核心话题被便捷地提炼成了紧凑的博客文章格式。
在又一次 JetBrains 直播中,Vitaly Bragilevsky 与 Tokio 的创建者 Carl Lerche 一起,就异步 Rust 的演变进行了深入对话。Tokio 已成为 Rust 中高性能网络的事实上的异步运行时,为从后端服务到数据库的所有内容提供支持。在讨论中,他们探讨了异步 Rust 多年来如何成熟、Tokio 背后的架构决策、开发者今天面临的常见挑战,以及生态系统下一步的发展方向。如果你错过了现场直播,可以在 JetBrains TV 上观看完整录像。下面,你会找到对话中关键问题和见解的结构化回顾。
Q1. 什么是 TokioConf,你为什么决定组织它?
TokioConf 是首个致力于 Tokio 生态系统的会议,在俄勒冈州波特兰举行。今年标志着 Tokio 首次发布十周年,这是将社区聚集在一起的自然时刻。使用代码 jetbrains10 可享受普通入场票10%的折扣(不包括任何附加项目)。 购买 TokioConf 门票
Tokio 和 Rust 已成为基础设施级网络软件的基础技术,包括数据库和代理。会议旨在反映这种成熟度和增长。虽然名称突出了 Tokio,但范围包括 Rust 中更广泛的异步和网络主题。
"Tokio 和 Rust 已成为如今公司构建基础设施级网络软件的默认方式之一。"
Q2. 当人们听到"异步 Rust"时,他们应该想象什么?
异步 Rust 不仅仅关乎性能。虽然处理高并发是一个关键优势,但异步编程也改进了开发者构建事件驱动系统的方式。
与传统的线程方法相比,超时、取消和管理多个进行中任务在异步 Rust 中变得显著更容易。Rust 中的异步利用了所有权模型和 Drop,实现了安全和干净的取消模式。
"异步既是性能,也是一种良好管理大量进行中逻辑线程的方式。"
Q3. Tokio 是如何开始的?为什么 Rust 需要它?
Tokio 是从早期在 Rust 中实验非阻塞 I/O 演变而来的。最初,Rust 只有阻塞套接字 API,构建高效网络系统需要底层抽象。这一历程从 Mio(epoll 绑定)到 Future trait,再到 async/await。Async/await 是使 Rust 中异步编程符合人体工程学的一个重要里程碑。
"async/await 最终被设计的方式实际上相当令人印象深刻。"
语言团队成功地以当时不明显的方式实现了内存安全和零成本抽象。
Q4. Rust 能有类似 Java 虚拟线程的东西吗?
Rust 在 1.0 版本之前实际上有绿色线程和协程,但为了保留零成本抽象和 C 级性能特征,它们被移除了。绿色线程的堆栈管理开销和复杂性与当时 Rust 的设计目标冲突。
"Rust 实际上是从轻量级虚拟线程和协程开始的。"
这样的特性是否可能回归是一个开放问题,但今天的 Rust 异步模型根本不同。
Q5. 异步 Rust 中的取消是如何工作的?
Rust 中的取消是通过 Drop 实现的。当你丢弃一个 future 时,它的清理逻辑会自动运行。
如果 future 直接拥有一个套接字,它会立即关闭。如果套接字由另一个任务拥有(例如在 Hyper 中),取消信号通过通道级联并触发清理。
然而,异步函数可以在任何点被丢弃,开发者必须防御性地编写代码以正确处理这种情况。
Q6. 为什么 Tokio 成为了主导的异步运行时?
Tokio 成为事实上的标准主要是由于生态系统动力。像 Hyper 这样的早期 crate 建立在 Tokio 上,一旦那个基础稳固,切换运行时就需要令人信服的理由。
其他运行时也存在(特别是对于嵌入式或专用上下文),但对于通用服务器端开发,Tokio 的生态系统深度使其成为默认选择。
"确实没有不使用 Tokio 的好理由。"
Q7. io_uring 呢?它是未来吗?
io_uring 可以提供好处,特别是对于批处理文件系统操作。然而,对于网络工作负载,现实世界的收益通常有限。它比 epoll 更复杂,历史上也有更多的安全问题。也就是说,当你有明确的用例时,Tokio 允许混合使用 io_uring 特定的 crate。
"我还没有看到在 Tokio 底层用 io_uring 替换套接字带来真正的性能好处。"
Q8. Tokio 中最重要的设计决策是什么?
Tokio 有意避免重新发明调度模式。相反,它采用了来自 Go 和 Erlang 的经过验证的策略,包括工作窃取调度器。
理念是提供:
- 良好的默认值,
- 强大的性能,
- 高级调优的逃生舱口。
目标是使 Tokio 对大多数开发者来说足够容易,同时在需要时仍能实现性能优化。
Q9. 异步 Rust 中的常见错误是什么?
最大的问题来自协作调度。任务只在 .await 时让出,所以没有等待的长 CPU 密集型工作可能会使运行时停滞。Tokio 提供运行时指标来帮助检测此类问题。理解调度器如何工作对于避免尾部延迟问题至关重要。
"因为异步是协作调度,你必须确保足够频繁地让出回运行时。"
Q10. 调试异步 Rust 的最佳方法是什么?
调试异步系统通常涉及:
- 追踪,
- 运行时指标,
- 异步回溯,
- 传统调试器。
卡住的任务和高尾部延迟仍然是最难诊断的问题。更好的静态分析和 linting 工具未来可以显著改善这一领域。
"最大的陷阱归结为开发者意外取消了某些东西并且没有适当地处理取消。"
Q11. 什么是 Toasty,你为什么要构建它?
Rust 已经成熟为系统和基础设施语言,但更高级的 Web 应用程序工具仍然欠发达。Toasty 旨在通过构建高效、符合人体工程学的数据建模和查询层来探索这一空间。目标不仅仅是性能,而是开发者的人体工程学——同时仍然为高级用例保留逃生舱口。
Q12. Rust 能进入高级 Web 框架吗?
Rust 由于其基础设施优势,已经在许多组织中站稳了脚跟。随着内部 Rust 生态系统的增长,对更高级工具的需求增加。缺失的是符合人体工程学、有主见的框架,优先考虑生产力。长期愿景不是取代现有生态系统,而是将 Rust 的触角向上扩展到全栈开发。
"我确实认为有一种方法可以用 Rust 构建高效和符合人体工程学的库,专注于易用性。"
结束语
Rust 已牢固确立自己是许多基础设施级系统的最佳选择。下一个前沿是更高级的应用程序开发。Tokio 解决了异步基础设施,现在生态系统正在向生产力和全栈能力发展。
如果你感兴趣:
- 在 Tokio GitHub 上探索 Toasty
- 加入 Tokio Discord
- 参加在俄勒冈州波特兰举行的 TokioConf
观看我们之前与 Herbert Wolverson 的直播,探索你想了解关于 Rust 的一切