Rust是目前最优雅而且热门的编程语言之一,性能上可以比肩C、编译时安全、没有GC的累赘、异步和范型支持,注定这是将来流行的语言。一般认为Rust是一个很好的系统语言,但实际上Rust在各个领域都做的不错,今天我们就来说说Rust的Web框架。
概述
截至年7月,Rust生态系统中的主要Web框架有:actix-web、rocket、tide和warp。那么问题来了:如果要用Rust构建一个生产环境用的API,应该选择哪框架呢?
本文我们就来解答这个问题,我们将从几个方面对上述的各个框架予以说明:包括全面性(功能全面)、社区与采纳度、同步和异步(及其选择的future运行时)、文档教程和示例以及API和人机工程学。
当然虫虫历来奉行这样的理念那就是没有绝对的选择:不同的环境(和个人好恶)可能会导致选择不同的架构。
全面性
actix-web,tide和warp都是瘦web框架:他们只提供基本的HTTPWeb服务器,路由逻辑,中间件基础设施,基本的构建模块和抽象,从而解析、操作和响应HTTP请求。
rocket框架则与他们相反:它旨在一栈撸,对最常见的需求都可以通过rocket中的组件来提供,随要随取,开箱即用。另外它也提供了扩展机制,开发人员可以使用hook扩展用例。
rocket发内置了和ORM集成,可以管理和配置流行数据库(例如Postgres,Redis,Memcache等)。
与其他语言的Web框架进来对比的话:
actix-web,tide和warp更像是Python语言的Flask或JS中的ExpressJavascript但是没有提供现成的配置管理系统或ORM集成。需要有开发者手动自定义构建API,并需要引入所需的功能库,自己处理图片样式等;
rocket则更接近于Python的Django或PHP的Symphony框架:拥有一个稳定而强大的核心,附带一组高质量组件,可满足构建坚固的Web应用程序时的日常需求。rocket要在宽度和范围上与同行匹敌,还有很长的路要走,但这绝对是一个良好的开端。
当然,这是截止目前各框架的情况,各个框架可能也会不断地调整改善。比如actix-web已经在慢慢积累更多的功能(从安全到会话管理),在GitHub下actix组织的actix-extras仓库收集了相关的生态体系。
另外需要说明的是,用瘦Web框架开发,也并非就是从零开始要自己动手构建所有内容,毕竟有社区的生态体系,我们需要弄的也是别人需要的,很多已经前人帮我都做好了,我们无需重复造轮子,只需拿来用就好了。
社区与采纳度
针对四个web框架,我们浏览Rustcrates库中的统计数字如下:
构架总下载量日下载量
actix-webk
rocketk
warpk
tide47k
由于各个框架出现的早晚有别,总下载量不能客观反映框架的流行程度,但是日下载量可以很好地衡量一个框架的目前的流行程度。我们考虑社区规模和流行程度主要考虑以下因素:
具有规模应用的框架,有更多人帮我们趟过它的坑,所以其稳定性也会更好。
规模越,该框架的支持crates的数量也越多;
框架用的人多,其使用教程,问题解决方案和使用经验也会越多,遇到问题更容易得到解决。
对瘦框架来说,支持crates数量也是框架可实用的关键。我搜索框架名称时查看在crates.io的搜索结果数,可以反应各个框架的社区规模的影响:
构架搜索结果
rocket
actix-web
warp57
tide20
尽管搜索结果中的这些crates并非都会与搜索的框架相关,他们中也有一些可能是过时或者无法使用的。但是这个结果确实能反应一个框架的了流行程度和实用操作性。比如:
如果需要将Prometheus的指标添加到的API中,则可以使用actix-web-prom或rocket-prometheus在几分钟之内手动搞定,两者都有数千次下载量。如果你选择warp或tide框架,则这些工作都需要自己开始编写和集成;
如果要添加分布式跟踪,则可以使用actix-web-opentelemetry。如果选择任何其他框架,则需要自己手动实现。
同步与异步
Rust1.39版本(-11-07)中引入了async/await语法,改变了Rust异步编程的体验。当然Rust生态系统追赶并采用async/await异步还需要一些时间,但是可以公平地说,处理IO受限工作负载的brates现在都是是异步优先的(例如reqwest)。那么Web框架方面的情况呢?
actix-web和warp在0.2.x中开始支持async/await,而tide中async/await支持基于其nightlyrust编译器。
rocket,仍然会公开一个同步接口。async/await支持预计将在其0.5发行版中提供,目前尚不支持异步编程。
如果要实现一个对性能严格要求的,大流量web应用程序,则最好选择异步Web框架。
如果不是上面这种情况,那么尽管缺少异步支持,选择rocket也应该不是啥问题。
future运行时
Rust的异步编程是建立在其Futuretrait之上的:Future公开了poll一种必须调用的方法,以允许Future同步更新。可以将Rust的futur视为惰性的:除非进行poll,否则无法保证它们会执行完毕。与其他语言所采用的推模型相比,
异步运行时实际上是项目的依赖项,以brates形式引入,这为我们提供了极大的灵活性:确实可以实现自己的运行时,以针对用例的特定要求进行优化或者仅根据情况选择最合适的运行时。
从表面上看,听起来很棒,但现实却很痛苦:目前,运行时之间的互操作性还很差。混合运行时可能会很痛苦,通常会导致无法分流、检测或解决的问题不直接。
尽管大多数库不应直接依赖于运行时,而应依赖futures库公开的接口,但由于历史包(例如tokio,长期以来是生态系统中唯一可用的运行时),实际需要(例如,一个框架必须能够产生任务)或缺乏标准化。
因此,选择一个异步Web框架超出了框架本身的范围:正在选择一个由brates组成的生态系统,这突然使依赖于不同异步运行时的库变得更加麻烦。
当前的事务状态还很不理想,但是如果从现在开始要编写异步Rust,那么建议在异步运行时进行做慎重的选择。
目前在Rust中可用的两个主要通用异步运行时为tokio和async-std。
tokio已经存在了很长一段时间,并且已经广泛用于生产中。尽管这会导致更大,更复杂的API,但是它是相当可调的。
async-std是一年前发布的,和async/await稳定发布时间差不多。它提供了出色的人性化设计,同时为配置扩展留下了更少的空间。
crates搜索中,两者的统计数据如下:准:
运行时下载总量日下载量
tokiok30k
async-stdk4千
四个web框架的对两者的选择如下:
构架运行时
actix-webtokio
rocket(0.5.x)tokio
tideasync-std
warptokio
文档,教程和示例
必须深入源代码以了解某项工作原理是一件很意义的事情,但只应该一种选择,而不是必须的。在大多数情况下,要依靠记录良好的框架,包括有关使用模式的简单示例。
良好的文档,教程和功能齐全的示例对任务至关重要,特别是团队中一个或多个成员都不是经验丰富的Rust开发人员的时候。
Rust的生态体系将文档为最重要的部分(只需运行cargodoc--open即可自动生成项目文档),这也是Rust社区本身文化的一部分。库作者通常会认真对待文档,Web框架也不例外。在docs.rs上可以找到非常详尽的内容,并在需要时提供上下文示例。
rocket和actix-web在各自的网站上提供高级文档指南,所有框架都将大量示例作为其代码库的一部分。
项目文档的教程之外的大多是一些随时间的积累:actix-web和rocket很容易找到的材料(文章,讲座,workshop),而warp和tide的材料则较为有限。在另一面,大量的材料可能会存在过时的情况,这些针对老版本的材料可能会引起误解,这也是初学者常见的困惑之一。
这就是虫虫不建议大家使用搜索引擎搜索材料,而是尽可能先去学习官方文档。
总结
年今天面对这些Web框架,如何选择呢?
7月开始,我建议actix-web选择是否要在Rust中编写生产API。
首先针对actix-web:
它已广泛用于生产;依靠tokio作为异步运行时,从而最大程度地减少与异步生态系统中最流行的包的兼容性问题的可能性;拥有大量成熟的插件以及最大的社区。
尽管它的某些API绝对不是最符合人性化,但考虑到所有因素,这带来的不便肯定很小。
当然如果都按部就班,不愿意尝试,Rust框架就无法百花齐放,繁荣昌盛。其他web框架也优势明显
tide并warp使用异步Rust突破了人性化极限;
用rocket可以最大程度上享受其功能方面的优势,但是它采用了async/await以及用nightlyRust编译器进行移植。
当然最好的框架是不用框架,是用自己的框架,如果你心有余,力所及,去创建一个自己的Rust框架也是一个非常好的选择,如果你有这方面的打算或者已经做了这方面的工作,请at虫虫,如果下次介绍Rust框架,我将予以优先介绍。