Rust 的局限性:何时使用以及何时放弃
近年来,Rust 已成为开发者社区的宠儿,在“最受喜爱”调查中始终名列前茅,并受到 Amazon、Cloudflare 和 Google 等科技巨头的积极采用。对于许多工程经理和架构师来说,这产生了一种引力:如果行业领导者正在将其核心基础设施迁移到 Rust,那么这样做似乎是合乎逻辑的。
然而,采用新语言的决策应该基于项目需求和团队能力,而不是企业趋势。虽然 Rust 提供了无与伦比的内存安全性和性能,但它也引入了显著的摩擦,如果用于错误的项目,可能会付出高昂的代价。了解 Rust 的局限性对于避免“炒作周期”陷阱并确保工具与任务匹配至关重要。
Rust 采用过程中的摩擦点
Async Rust 的复杂性
Rust 中最显著的障碍之一是异步编程的实现。虽然 async/await 是高并发应用的一个强大工具,但它引入了一层复杂性,可能导致微妙且难以调试的性能问题。
一个常见的陷阱是用同步函数意外阻塞事件循环。在大型代码库中,这通常会导致性能不一致或潜在的拒绝服务 (DoS) 漏洞。此外,async、泛型和生命周期的交集使得 Rust 的所有权模型——本就学习曲线陡峭——变得更加难以管理。
生态系统碎片化与“贫血”的标准库
与提供“内置电池”标准库的 Go 不同,Rust 采取了更为极简主义的方法。这种哲学将提供核心功能的负担转移到了社区。
虽然这促成了了像 tokio 和 hyper 这样高质量 crate 的创建,但也导致了生态系统的碎片化。由于许多常见任务没有单一的“官方”标准,开发者经常发现自己为了实现相同的功能而引入了多个相互竞争的库。例如,一个项目最终可能会在其依赖树中包含多个不同的加密库,因为各种上游依赖各自选择了不同的原语。这不仅增加了二进制文件的大小,还扩大了供应链漏洞的攻击面。
演进速度与项目衰退
Rust 演进迅速。随着频繁的发布和“editions”的引入,该语言快速移动以完善其功能。虽然这对于语言的增长通常是有利的,但这可能会为专业项目带来维护开销。
对于那些维护可能多年不被触及的长寿命服务的团队来说,工具链和依赖项的快速更迭可能会导致“项目衰退”,即更新一个休眠的服务变得成为一项重大的工程努力。这与 Go 或 Python 等语言形成对比,后者通常为其核心平台优先考虑更慢、更稳定的发布周期。
Rust 真正擅长的领域
尽管存在这些挑战,Rust 并不是每种语言的通用替代品;相反,它是一个精密工具。在某些特定领域,Rust 的权衡是不仅可以接受,而且是有利的。
1. 跨平台应用的通用核心
Rust 在构建必须在移动端 (iOS/Android)、桌面端和 Web (通过 WebAssembly) 上运行的共享逻辑方面具有独特的地位。它在这些多样化目标平台上提供内存安全性和高效依赖管理的能力,使其成为成为“通用核心”架构的理想选择。
2. 系统编程与嵌入式开发
对于系统守护进程、低层级 OS 接口和 IoT 设备,Rust 是一个游戏规则改变者。在嵌入式领域,C 长期统治着这里,尽管其本身存在安全风险,但 Rust 提供了一种使用现代工具链编写安全、高性能代码的方法。RISC-V 的兴起和更好的硬件抽象层 (HALs) 正在使这种向生产级硬件的迁移变得更加可行。
3. 极端规模
当在 AWS 或 Cloudflare 的规模下运行时——即每一微秒的 CPU 时间和每一字节的内存都转化为数百万美元的基础设施成本时——Rust 的控制级别是不可或缺的。在这些环境中,性能增益和类型系统保证的正确性超过了生态系统的摩擦。
反方观点与社区视角
围绕 Rust 用途的讨论通常分为两派:一派重视严格的正确性,另一派重视开发速度。一些“反 Rust”情绪的批评者认为,作者对项目衰退的担忧过于夸大,并指出 Rust 的 “editions” 是专门设计用来防止破坏性变更并保持向后兼容性的。
其他人则指出,“贫血”的标准库是一个有意识的设计选择,旨在保持语言的精简,并且加密生态系统的碎片化通常是 Cargo.lock 处理可选依赖的方式所致,而不是生态系统破碎的迹象。
最终,经验丰富的从业者达成的共识是,Rust 是一个工具,而不是万能药。
"Rust 是一种编程语言。它在某些方面做得非常好,在其他方面则稍逊一筹... 人们可以使用它,因为他们喜欢它,无论是是否做对了工具与任务的匹配。"
最终结论:你应该使用 Rust 吗?
如果你的团队由 Rust 专家组成,或者你正在构建高性能系统、跨平台核心或嵌入式设备,Rust 很可能是目前最好的工具。然而,如果你正在构建一个中等规模的后端服务,其中开发速度是首要任务,且你的团队更习惯于 Go 或 Python,那么与 borrow checker 斗争以及在碎片化的 async 生态系统中穿梭的开销可能会是一个代价高昂的错误。