当我首次决定将我们的后端技术栈从 Python 迁移到 Rust 时,这不仅仅是出于好奇心——而是源于性能、部署方面的实际痛点当我首次决定将我们的后端技术栈从 Python 迁移到 Rust 时,这不仅仅是出于好奇心——而是源于性能、部署方面的实际痛点

从 Python 切换到 Rust 的经验教训

当我首次决定将我们的后端技术栈从 Python 迁移到 Rust 时,这不仅仅是出于好奇——而是源于性能、部署成本和负载下可靠性等实际痛点。Python 的网络生态系统——尤其是 FastAPI——在生产力和快速迭代方面非常令人愉快。但随着流量增长和性能瓶颈变得明显,我想探索 Rust 能提供什么。

在本文中,我将分享我在这个过程中学到的东西:优势、陷阱,以及每个生态系统仍然闪耀的地方。

从 Python 切换到 Rust 的经验教训

性能比较:Rust (Actix-Web) 与 Python (FastAPI)

原始吞吐量和延迟

在进行基准测试时,首先让我震惊的是 Rust 和 Python 网络框架之间性能特征的巨大差异。

在各种独立基准测试中,Rust 的 Actix-Web 在原始每秒请求数和内存效率方面始终优于 FastAPI。在一项社区基准测试中,Actix-Web 每秒处理的请求比 FastAPI 多出数千个,延迟更低,内存消耗也远低于 FastAPI。

这与更广泛的观察结果一致,即 Rust 的 零成本抽象 和缺乏垃圾收集器,使其在大规模提供 HTTP 服务时效率极高。

实际影响

根据我的经验,这转化为:

  • 在压力测试中持续吞吐量更高。
  • 负载下的变化更小。
  • 与 Python 进程相比,空闲内存使用量更低。

话虽如此,基准测试只能说明部分情况:实际瓶颈通常受数据库或网络限制。对于许多应用程序,FastAPI 的性能绰绰有余,调整数据库访问或缓存比单独选择语言获得的收益更大。

ORM 差异:Diesel 与 SQLAlchemy

切换 ORM 范式是迁移中最具文化差异的部分之一。

迁移系统

在 Python 中,我们使用 SQLAlchemyAlembic 迁移——这种方法可以对比模型并自动生成迁移脚本。

在 Rust 中,我们转向了 Diesel,它采取了完全不同的立场:

  • 迁移以显式 SQL 文件的形式手动编写。
  • 没有自动对比工具。
  • 你获得了更多控制权——也承担更多责任。

这一开始令人沮丧,但手工编写迁移的纪律带来了更清晰的可审计性,在生产环境中减少了意外情况。

类型安全和编译时保证

这是 Diesel 真正改变我对数据库代码思考方式的地方:编译时的类型安全

Diesel 根据你的模式生成 Rust 类型,因此不匹配的列名或无效的查询结构根本无法编译。诸如 check_for_backend 之类的概念以及需要显式 table_name 声明意味着整个类别的常见错误在你运行查询之前就会消失。

相比之下,SQLAlchemy 只在运行时捕获许多错误。虽然这增加了灵活性,但也意味着更多地依赖测试来确保正确性。

构建和执行查询

Diesel 的查询构建器使用 Rust 的类型系统,与 SQLAlchemy 更动态的表达风格相比需要更多代码行——但权衡是编译器为你证明了很多东西。

经过一段适应期后,我开始欣赏 Rust 的明确性在重构期间导航复杂查询逻辑时的帮助。

自动 OpenAPI 生成支持

Python 在开箱即用方面仍然领先的一个领域是 API 模式生成。

FastAPI 自动生成 OpenAPI 文档,并在 /docs/redoc 上提供浏览器 UI,如 ReDocSwagger UI,使客户端和团队成员能够超级轻松地理解和探索你的 API。

Rust 的生态系统在这里正在发展。像 utoipa 这样的工具可以为 Actix-Web 生成 OpenAPI 规范,但与 FastAPI 的无缝体验相比,它们感觉更手动和分散。也有社区 crate 来提供 Swagger 或 Redoc UI,但它们需要额外的设置和注释。

我预计这一差距将继续缩小——Rust 社区正在积极努力带来可与 FastAPI 媲美的更流畅的 API 文档体验。

部署大小:编译与依赖

Rust 编译时间

Rust 的编译速度比解释型语言慢是众所周知的。在开发过程中,重建——特别是使用大型 crate 时——与重新运行 Python 脚本相比可能感觉迟钝。

但这个成本是开发时间,而不是生产时间。一旦编译,Rust 二进制文件:

  • 完全提前编译
  • 自包含(无需 virtualenv,通常没有动态依赖)
  • 在容器映像中占用空间非常小

这使部署更简单、更可预测。

Python 依赖占用空间

Python 应用程序通常带来庞大的依赖图:FastAPI 本身、uvicornpydantic(现在由于 Rust 内部而快得多)、数据库驱动程序等。

这增加了:

  • 容器大小
  • 构建复杂性
  • 依赖冲突的表面

Rust 的 Cargo 生成一个封装所有内容的二进制文件(通常),这大大简化了部署流程。

可维护性

这可能是个人成长最多的领域。

Rust 推动你走向清晰的所有权边界、显式错误处理和仔细的设计。一旦你内化了 Rust 的编译错误,编译器本身就成为防止回归的强大护栏。

相比之下,Python 的动态性在早期开发期间可能感觉毫不费力——但同样的灵活性有时会导致生产中更难诊断的错误,除非有强大的测试套件支持。

我们的 Rust 代码库在大型重构期间感觉更有弹性,这主要归功于编译器的严格性。

文档和开发者体验

FastAPI 的自动文档

FastAPI 与 OpenAPI 的集成,加上 ReDocSwagger UI,使新开发人员的入职变得极其容易。这是我在团队生产力方面看到的最大成就之一。

Rust 文档生成

Rust 的内置文档工具(cargo doc)对于代码级文档来说非常出色。它鼓励在代码旁边编写文档,Rustdoc 生成干净、可搜索的 HTML 文档。

虽然这不能开箱即用地替代一个漂亮的 /docs 端点,但它确实大大提高了以代码为中心的文档质量和可发现性。

结论

从 Python 切换到 Rust 进行后端开发并不是偏爱一种语言而不是另一种——而是与我们项目的优先级保持一致。

  • Rust 为我们提供了性能、可预测性和可靠性,适用于生产流量。
  • Python 为我们提供了开发速度和世界级的人机工程学

这两个生态系统都很强大。Rust 带来的变化是,许多在 Python 中只会在运行时出现的问题在 Rust 中被编译时捕获,减少了意外和中断。

选择 Rust 意味着投资于学习曲线——但对于性能和正确性最重要的团队,这种权衡对我们来说是值得的

作者注

本文由 Hytale Multiplayer 的创建者撰写,这是一个专注于技术文章和深入探讨游戏 Hytale 的网站,包括服务器开发、工具以及与 Minecraft 等相关生态系统的比较。如果你喜欢实用的、以工程为重点的内容,请随时在那里探索更多文章。

评论
免责声明: 本网站转载的文章均来源于公开平台,仅供参考。这些文章不代表 MEXC 的观点或意见。所有版权归原作者所有。如果您认为任何转载文章侵犯了第三方权利,请联系 [email protected] 以便将其删除。MEXC 不对转载文章的及时性、准确性或完整性作出任何陈述或保证,并且不对基于此类内容所采取的任何行动或决定承担责任。转载材料仅供参考,不构成任何商业、金融、法律和/或税务决策的建议、认可或依据。