这篇文章原本是Zero to Production的一部分,用来解释我们选择技术背后的原因。它最终变得如此之大,成为了自己的文章!
如果您要开始在Rust中构建一个新的可投入生产的API,您应该选择哪一个?
当涉及到以下问题时,我将分析每个Web框架所处的位置:
最后,我会提出我的建议。值得一提的是,没有绝对的选择:不同的环境(和品味)可能会让你做出不同的选择。
Actix-web、Tend和WARP都是轻薄的Web框架:它们为您提供HTTP Web服务器、路由逻辑、中间件基础设施以及用于解析、操作和响应HTTP请求的基本构建块和抽象。
Rocket采取了一种不同的方法-它的目标是包括电池:最常见的需求应该由火箭本身提供的开箱即用的功能来满足,如果您的用例需要,可以使用挂钩来扩展Rocket。因此,Rocket发布了一个易于使用的集成来管理几个流行数据库(例如Postgres、Redis、Memcache等)的连接池,这就不足为奇了。以及它自己的配置系统在火箭-Conrib中,这是一个存放在火箭自己的储存库中的辅助板条箱。
Actix-web、浪潮和WARP在本质上更接近Python中的Flask或Javascript中的Express-它们可能有些固执己见,但它们并不提供配置管理系统或ORM集成。您负责构建您认为合适的API,将所有必要的板条箱和图案带到画面中;
Rocket更接近Python中的Django或PHP中的Symphony:一个稳定而坚实的核心,带有一组高质量的树内组件,可以满足您构建可靠Web应用程序时的日常需求。要想在广度和范围上赶上同行,火箭还有很长的路要走,但它肯定有了一个良好的开端。
当然,这是目前情况的快照,但情况正在根据维护人员的意图不断变化-例如,在Actix GitHub组织的保护伞下,Actix-web在Actix-Extras中慢慢积累了越来越多的支持功能(从安全到会话管理)。此外,使用轻薄的Web框架并不会强迫您在框架不能满足您的需求时立即从头开始编写所有内容:您可以利用其周围社区构建的生态系统来避免在每个项目上重复发明轮子。
数字可能会误导人,但它们是一个很好的谈话起点。看看crates.io,我们有:
总下载量明显受到框架存在时间的影响(例如,Actix-web:0.1.0是在2017年底发布的!)。虽然每天的下载量是衡量当前人们对它的兴趣程度的一个很好的标准。
多年的持续生产使用使得您不太可能成为第一个发现重大缺陷的人。其他人哭是为了让你笑(大多数时候);
它与你在苦苦挣扎时可能找到的教程、文章和帮手的数量相关。
第二点对于超薄框架尤其重要。通过在搜索框架名称时查看crates.io上弹出的结果数量,您可以再次感受到社区大小的影响:
所有这些板条箱都是相关的吗?不太可能。它们中会有相当一部分是过时的或未经证实的吗?一定。
尽管如此,在开始一个项目之前,快速查看一下您所知道的功能以了解您将需要的功能是一个好主意。让我们快速举例说明我们在Zero to Production构建的电子邮件时事通讯实现中将依赖的功能:
如果您需要将普罗米修斯的指标添加到您的API中,您可以使用Actix-web-PROM或Rocket-Prometheus在几分钟内上手,两者都有数千的下载量。如果你使用翘曲或潮汐,你将不得不从头开始写积分;
如果您想添加分布式跟踪,Actix-web-opentelemeter将为您提供支持。如果您选择任何其他框架,则必须重新实现它。
这些功能中的大多数都不是很难实现的工作,但随着时间的推移,这些工作(特别是维护)会变得复杂。您需要睁大眼睛选择您的框架,了解它将需要的承诺级别。
Rust在1.39版本中引入了Async/Await语法--在异步编程的人机工程学方面改变了游戏规则。整个Rust生态系统花了一些时间才赶上并采用它,但公平地说,现在处理IO绑定工作负载的板条箱通常被认为是异步优先的(例如,reqwest)。
那么Web框架呢?Actix-web在其0.2.x版本中采用了异步/等待,与WARP相同,而浪潮在稳定之前使用异步/等待,这依赖于Nightly Rust编译器。相反,Rocket仍然公开同步接口。异步/等待支持预计将作为其下一个0.5版本的一部分,自去年夏天以来一直在酝酿之中。
您是否应该排除Rocket作为一个可行的选择,因为它还不支持异步编程?那得看情况。如果您正在实现一个具有严格性能要求的应用程序来处理大量流量,那么选择异步web框架可能会更好。如果不是这样,火箭缺乏异步支持不应该是你主要关心的问题之一。
异步/等待并不都是阳光和玫瑰。Rust中的异步编程构建在Future特性之上:Future公开一个Poll方法,必须调用该方法才能使将来取得进展。你可以认为Rust的未来是懒惰的:除非进行投票,否则不能保证他们会执行到完成。与其他语言1采用的推模型相比,这通常被描述为拉模型,当涉及到性能和任务取消时,这有一些有趣的含义。
不过,请稍等片刻--如果期货是懒惰的,并且Rust没有在其标准库中提供运行时,那么谁负责调用Poll方法呢?BRON-自带运行时!异步运行时实际上是项目的依赖项,作为板条箱引入。这为您提供了极大的灵活性:您确实可以实现自己的运行库,这些运行库经过优化以满足您的用例的特定需求(请参阅Fuchsia项目或堡垒的参与者框架),或者根据您的应用程序的需要简单地根据具体情况选择最合适的运行库。这在理论上听起来很棒,但实际情况却没有那么吸引人:目前运行时之间的互操作性很差;混合运行时可能会很痛苦,通常会导致无法直接分类、检测或解决的问题。虽然大多数库不应该直接依赖于运行时,而是依赖于未来机箱公开的接口,但由于历史包袱(例如Tokio在很长一段时间内是生态系统中唯一可用的运行时)、实际需要(例如框架必须能够生成任务)或缺乏标准化(例如正在进行的关于AsyncRead/AsyncWrite特征的讨论-参见此处和此处),情况往往并非如此。因此,选择一个异步web框架超越了框架本身:您选择了一个板条箱生态系统,突然间使得依赖不同的异步运行时使用库变得更加麻烦。
目前的情况并不理想,但是如果您现在编写的是异步Rust,我建议您在编写异步运行时要慎重选择。
目前在Rust中可用的两个主要通用异步运行时是Tokio和Async-STD。Tokio已经存在了相当长的一段时间,它已经看到了广泛的生产用途。它是相当可调的,尽管这会产生更大、更复杂的API表面。Async-STD大约在一年前发布,大约在异步/等待稳定的时候发布。它提供了很好的人体工程学,而留给配置旋钮的空间较小。
必须钻研源代码来理解某些东西是如何工作的,这可能很有趣(也很有教育意义!),但这应该是一种选择,而不是必须的。在大多数情况下,我宁愿依赖于记录良好的框架,包括相关使用模式的重要示例。如果您是团队的一员,好的文档、教程和功能齐全的示例对于任务至关重要,特别是如果一个或多个团队成员不是经验丰富的Rust开发人员。
Rust的工具将文档视为一级概念(只需运行Cargo doc--open即可获得项目的自动生成文档!)。它逐渐成为铁锈社区自身文化的一部分。图书馆作者通常会认真对待它,Web框架也不例外:你可以在docs.rs上找到相当全面的东西,在需要的地方还会提供上下文相关的例子。Rocket和Actix-web在各自的网站上提供高级指南,所有框架都维护丰富的示例集合作为其代码库2的一部分。
项目文档之外的教程主要是年龄的函数:在Actix-web和Rocket上很容易找到材料(文章、演讲、研讨会),而提供的内容在一定程度上受到了更多的限制。另一方面,Actix-web和Rocket的一些功能可能针对的是较老的版本,这给人们留下了混淆的空间。
嗯,很难给出一个听起来合理客观的关于API设计的意见。当谈到我们所认为的令人愉快的API时,我们都有非常不同的品味,没有什么可以代替快速的杂乱无章,来真正感受一下使用某个Web框架是什么样子。
如果你时间不多,你可以看看做好的例子:actix-web的例子,warp的例子,浪潮的例子和火箭的例子。
如果您对扭曲和潮汐感兴趣,Image Decay as a service提供了对它们的API的深入分析。
从2020年7月开始,如果您正在用Rust编写生产API,我建议您选择Actix-web。
依赖Tokio作为其异步运行时,从而将与异步生态系统中最流行的板条箱的兼容性问题的可能性降至最低;
虽然它的一些API绝对不是最符合人体工程学的(我看着你,Transform Character),但从各方面考虑,不便肯定是微不足道的。
另一方面,如果没有人愿意押注于一项前景光明但验证程度较低的技术,铁锈本身就不会有今天的地位:
潮汐和翘曲正在推动使用异步生锈在人体工程学方面可能实现的极限;
即将发布的火箭将是大规模的,因为它采用了异步/等待,以及从夜间到稳定的Rust编译器的迁移。
这就是说,它的名字来自于哪股浪潮,整个铁锈异步生态系统的前进方向。一年后再来看另一篇综述!
感谢o0igition0o和vertexcique花时间审阅了本文的草稿。
如果您想在本博客发布新文章时收到通知,请订阅电子邮件时事通讯。
请查看异步/等待的发行说明以了解更多详细信息。在Rust LATAM 2019上的无船演讲是关于这个主题的另一个极好的参考。如果你更喜欢书而不是演讲,那就去看看“200行生锈”中解释的期货吧。[返回]