时间总是比想象中过的快,接触Rust的时间不知不觉也已经满了一整个年头了。
回顾去年,我觉得最大的收获莫过于在Rust后端编程领域的学习所得,于是就想写一些文章来做一个详尽的总结。
在这篇文章,也是这个系列的第一篇,我会分享一下我所接触到的Rust Web相关的依赖组件,方便各位再自己尝试的时候快速做出选择。

❓ 为什么Rust Web编程是值得推荐的

我们都大致的知道Rust在性能和内存安全方面的卓越特性,不过更具体一些来讲,这个问题的答案我觉得可以列为不仅限于以下几点:

  • 拥有目前理论最高的性能上限(与C++不相上下),高效、内存占用少
  • 出色的工程化设计,无论是小型的微服务还是大型项目。Rust都能做到快速构建并妥善地组织
  • 拥抱开源的生态,Rust的Web框架多数都采用了最新的设计思路
  • Web编程相比很多其他领域上手曲线并不陡峭,并且还能快速吃到Rust带来的红利
  • 功能覆盖率已经达到较高水平,Rust Web编程已经是可以使用在一些非专业场景下的了

Rust在有这样一些优点的情况下,缺少的就是一个完备的学习流程,帮助大家快速入门Web后端编程。
这也是我决定要写这篇文章的另一个原因。

📋 自查清单

如果你是一名初学者,可以参考以下的自查清单,一方面方便定位一些前置知识,一方面确保能够进行后续的学习。

|
- [ ]

有一个Rust的开发环境

- [ ]

| 基本完成《The Rust Programming Language》前10章的学习 | |
- [ ]

| 了解HTTP请求的基本知识 |

💾 依赖组件

Rust有足够多的依赖(dependencies)来构成一个完整的Web后端。
其中重要的组件提供一些核心的功能,其他组件则提供一些辅助的功能。

主要组件的选择

最主要的两类组件分别是Web框架SQL执行器,这两类组件在社区中是有多种选择的,就像Python有django、flask…一样。
我会一一介绍这些在社区中比较主流组件,并给出我对它们的评价。

Web框架

Github stars由高到低

  • Rocket
    • 一个很早就有了的Web框架,也是框架中功能最齐全的,自带错误处理HTTP模板等功能
    • 我个人并没有尝试过这个框架,原因是它先前不支持异步,并且只支持Rust的nightly版本
    • 不过现在Rocket已经推出了最新的0.5.0-rc,支持异步,也支持stable版本的rust,同时Rocket的官方教程写的也是非常的全面,罗列了各种功能的使用方法,喜欢一步到位的朋友可以选择Rocket
  • Actix-web
    • 大约是两年前,Actix-web在TechEmpower屠榜轰动一时,中途也经历了不少风波,如今这个高性能的Web框架还是存活了下来,有了一个较为庞大的用户群体,也有了不少附属的插件
    • 你不用担心有Actix-web做不了的事情,相比较Rocket,Actix-web缺的可能只有一个成体系的教程了。不过相对的,你获得了Actix-web强大的Rocket不能比拟的性能
    • Actix-web推出4.0版本已经有快半年的时间了,不过一直处于beta版本。4.0版本对我来说最大的吸引力是新增了对tokio 1.0生态的支持,毕竟很多基于tokio的组件(如Mongodb-driver…)是不兼容1.0以下的版本的,这对先前的Actix-web是有些限制的
  • Warp
    • Tokio官方指定的Web框架,由于Actix-web的unsafe风波和Rocket一直以来不是特别给力的性能,Warp也就成为了早期一些企业的唯一选择
    • Warp也是一个比较轻量的框架,感觉比较适合做微服务,内容不是很多,就是基于hyper做了一个包装,通过Filter的概念来管理路由,这种概念在代码里表示起来是比较直观的
    • Warp没有middleware的概念,而在Actix-web当中一些middleware还是比较好用的
    • Warp的有些部分个人觉得使用起来有那么一些别扭,比如and_then的异步执行块,这也使得Warp使用的并不是目前主流的await的形式
  • Tide
    • 基于Async-std运行时的Web框架,设计方面参考了先前的一些其他框架(如Actix-web的middleware)
    • 总体来说算是一个比较好用的框架,但是亮点不足,没有一个特别的优点能说服人们去选择它
    • 表面上是一个比较完备的框架,但我跟社区大神交流过之后得知,Async-std在网络方面完成度还是比较低的,这可能是Tide在性能方面也并不突出的原因之一
    • 另外Tide和Async-std的维护更新频率远没有Tokio生态来的频繁,这点其实有些不太乐观的表现
  • Ntex

    • Actix创始人Nikolay Kim又回来了,Ntex为了性能优先同样是使用了unsafe,不过这次不像Actix-web那样有很高的关注度,Nikolay Kim也可以安心完成他想做的事情了
    • 目前Ntex已经在TechEmpower当中全面超越了Actix-web,虽然各项提升的并不明显,但是每项的领先说明了,Ntex确实是做过改进的
    • 由于一些其他的客观因素,Ntex想要真正的发展起来,被社区所接纳可能还需要很长时间。这个项目值得关注的原因,我觉得还是Nikolay Kim本人,他一定是想把Ntex做成他心目中最完美的样子的,我们可以拭目以待

      SQL执行器

      Github stars由高到低
  • Diesel

    • Rust非常好用的ORM框架,可以通过函数式编程对数据库操作进行组装,我自己的项目就在使用Diesel,写多了都忘记怎么写SQL了
    • Diesel目前的性能应该仅次于直接使用数据库驱动,本身不支持异步,但是有了r2d2连接池以后,可以将连接分配给某个线程,然后用异步运行时进行管理(Actix-web借鉴了这个思路提供了web::block,来提高与Diesel的契合度)
    • Diesel的Postgres驱动用的好像是实验版本,执行效率上比其他执行器更优秀
  • SQLx
    • 支持异步和SQL检查的执行器,足够的安全可靠,不想用ORM的话SQLx还是比较值得尝试的
    • 0.5版本的连接池一直有些问题,高并发的时候会卡死,当时我测试的时候拿了一个大神的修复版本才把测试跑通下来…
    • 就算没有连接池的bug,0.5版本的执行效率也是比较差的。不过作者很早就在Discord里分享了0.6版本的性能提升,总体来说还是值得关注的,等0.6版本出了可以再跑跑看测试
  • Rbatis

    • 国人写的一个ORM框架,功能蛮多的,支持的数据库种类也是最多的,对喜欢尝鲜的人来说还是值得一试的,不过里面有多少坑就不得而知了
    • Rust的中国社区和外界沟通其实还是比较少的,所以Rbatis的Contributor很少,用户也比较少,总的来说就是可能比较难火
    • 我没用过,原因是我有段时间对async-std生态的东西特别的抗拒(Tide和SQLx跑测试的时候都还是有些跌眼镜的),Rbatis作为第三者后来就没有再试了,现在想想还是挺可惜的

      其他需要知道的组件

      序列化与反序列化

  • Serde

    • 选择Rust写Web另一大原因:Rust序列化和反序列化的效率极高
    • Serde支持各种数据格式,其中就包含了常用的JSON、TOML、YAML、Bincode等
    • 运用Serialize和Deserialize的Derive宏,可以快速使你的数据能够被序列化和翻序列化,一般需求使用起来非常的方便

      自定义错误类型

  • Thiserror

    • 利用Derive宏可以快速地定义错误类型的枚举以及对应的显示方法
    • 在Web编程中,可以用Thiserror来自定义错误处理
  • Anyhow

    • Anyhow实现的Result可以上抛所有的错误类型,如果你只是想要一个通用的错误上抛类型,并不想花费精力在定义错误类型上,可以试试这个组件

      启动参数

  • StructOpt

    • 利用Derive宏结合结构体,可以快速的定义应用的启动参数
    • 可以用来配置数据源、日志级别等
    • 除了命令行参数以外,支持读取环境变量

      日志

  • Log

    • Rust官方提供的依赖,帮助你快速地打log
    • 需要搭配其他依赖才能完成打印输出,我用的是env_logger,在环境变量里配置一个日志的等级,相应的日志就会输出了。具体有哪些依赖是可用的可以点链接进去看,这里就不多做介绍了

      正则表达式

  • Regex

    • 方便做一些验证的工作

      加密函数集合

  • Hashes

    • 支持MD2/4/5、SHA1/2/3等各种加密算法,整合度高,使用只需要装Digest+任意算法库即可,只要学会用怎么使用Digest不管是什么算法操作起来都是一样的

      全局变量

  • Lazy_static

    • 有的时候没有全局变量还是会比较麻烦的,比如说想要缓存一些数据在后台的时候,Lazy_static提供了定义全局变量的方法

      特殊的数据类型

  • Chrono

    • 支持各种时间类型的存储、转换、生成等操作,可以和Diesel等数据库组件搭配使用,支持序列化、反序列化
  • Uuid
    • Uuid的存储、生成,可以和Diesel等数据库组件搭配使用,支持序列化、反序列化

结语

介绍组件的初衷是:对于主要的组件我并不想对组件的选择给出一个过于绝对或者说明确的结论;对于其他的组件,我也是一步步入门而来,我也清楚如果没有一个大致的了解,新手很难主动会去自行找到这些东西。
授人与鱼不如授人与渔,希望这篇文章不仅仅只是一个参考,也能帮大家打开一个新的眼界。

如果硬要我在主要组件里选择两搭配的话,我会选择Actix-web+Diesel,这是一个足够高效也足够好用的组合。我也计划在后续的文章里分享一些我使用Actix-web+Diesel实践的一些技巧和心得。

最后,也希望喜欢这篇文章的朋友可以帮忙点个赞 🧡
有不准确或者可以补充的地方也麻烦高手们在评论区提点了 🙏