Rust 不适合开发 Web API
Rust 是一门神奇的编程语言,有非常好的 CLI 工具,比如ripgrep和exa。像 Cloudflare 这样的公司正在使用并鼓励人们写Rust来运行微服务。Rust 编写的软件可能比 C++或 C 更安全、更小、更简洁。
如果我正在编写一个地理编码器、一个路由引擎、一个实时消息平台、一个数据库或一个 CLI 工具,Rust 最合适。
但去年,我试图用 Rust 写一个传统网站的纯 API 服务,Rust 就不合适了。
Rust 有大量的 Web 服务框架、数据库连接器和解析器。但搭建身份验证服务方面只有非常低层次的组件。Node.js 有passport.js,Rails 有devise,Django 有开箱即用的身份验证模型,在 Rust 中,你需要学习如何将共享 Vec 转换到底层加密库才能构建这个系统(译者注,Vec 是一个动态数组,只会自动增长而不会自动收缩。区别于 Array,Vec 具有动态的添加和删除元素的能力,并且能够以 O(1)的效率进行随机访问。Vec 的所有内容项都是生成在堆空间上的,可以轻易的将 Vec 移出一个栈而不用担心内存拷贝影响执行效率,毕竟只是拷贝栈上的指针)。有些库试图解决这个问题,比如libreauth,但它才刚刚开始开发。还有很多类似的 Web 框架问题。
SDK 呢?在主流编程语言中,你可以通过一个官方库来接入 Google 云服务、AWS 或 Stripe。这些官方库大都很棒。例如,aws-sdk-js和Stripe库的设计和维护得非常好。
Rust 就不这样,只有少许第三方库,但以这些服务的开发速度,它们真的能够提供高质量的体验吗?
有人会说好吧,X 编程语言太好了,你可以在周末自己写一个 SDK!我必须回答,不。
Rust 的生态系统在其它领域非常丰富。用于构建 CLI、管理并发性、使用二进制数据和底层解析器的 crates 令人印象深刻,非常棒。
我一直在看Nicholas Nethercote的博客,描述了 Rust 团队如何优化编译器,让它更快!
但与其它编程语言相比,用它构建网站会很慢。它比编译型编程语言 Go 慢得多,也比解释型编程语言 JavaScript、Ruby 和 Python 等慢得多。
一旦代码被编译,一切就变得非常棒了!但在我的情况下,甚至基本 API 功能都不完整,一个不复杂的系统——居然花了 10 多分钟来编译。Google代码构建的硬件配置很差,每次都会超时,我啥都编译不了。
只要不重建缓存依赖项,缓存就有意义。也许减少依赖会加快 Rust 项目编译。但就像serde,几乎所有人都使用的 JSON 和其它序列化/反序列化程序占用了大量的编译时间。我们是否应该用编译速度更快但缺乏大量文档和生态系统支持的东西来取代 serde?这种取舍非常糟糕。
Rust 让你从代码维度进行思考,这对系统编程来说非常重要。它让你思考如何共享或复制内存,思考真实但不太可能的小概率事件,并确保妥善处理它们,帮你编写各种各样的高效代码。
这些担忧都是合理的,但是对于大多数 Web 应用程序来说,它们并不是最重要的关注点,以流行的惯性思考会导致不正确的假设。
就拿 Rust 的安全性来说吧。这是它宣传语中的重要部分,这是绝对正确的:Rust 的承诺安全和底层两者兼而有之——它可以在没有垃圾收集器的情况下工作,同时防止基于内存的漏洞。当你读到“安全”的时候,想想 Rust 的竞争对手 C 吧。C 语言中的代码可以引用任意内存,很容易溢出和出错。Rust 代码可以和 C 代码一样快,但是可以保护内存访问,而不需要垃圾收集器或某种运行时检查。
但是 Rust 的内存规则并不比 Node.js 或 Python 更安全,用 Rust 编写的 Web 应用程序在系统上不会比 Python 或 Ruby 应用程序安全。带有垃圾收集器的高级编程语言通常为避免这类漏洞利用和错误而付出性能损失。不能在 JavaScript 中引用未初始化的内存,因为 JavaScript 中不进行内存间的引用。
旁注:这是在描述 Node.js 和其它系统的设计目标——它们确实偶尔会有 bug。Node.js 的缓存对象,就值得读一读。
你要是问一些人,他们会说如果使用不安全的代码,Rust 相比带有内存回收的编程语言是不安全的——包括最流行的 Web 框架 Actix(译者注,Actix 是 Rust 的 Actor 异步并发框架,基于 Tokio 和 Future,开箱具有异步非阻塞事件驱动并发能力,其实现低层级 Actor 模型来提供无锁并发模型,而且同时提供同步 Actor,具有快速、可靠,易可扩展https://actix.rs/),因为不安全代码允许原始指针的延迟。
如果你正在写一个视频游戏,暂停执行垃圾收集是不好的。如果你在编写微控制器代码,任何内存“开销”或浪费都是非常糟糕的。但是大多数 Web 应用程序可以节省一点内存开销来换取生产性能。
Rust 的其它属性面对的争议几乎一样。它的并发特性是太神奇了,如果你在做一些复杂的事情,需要快速响应,这当然很棒。但如果情况不是这样呢?至少可以说,Rust 的异步生态系统面临着很大挑战:各种不相关的领域中有着不同的异步实现,比如tokio。
相比较之下,Python 的 Tornado 和 Twisted 异步实现的很奇怪,Node.js 异步实现的很好,但语法都很丑陋。
我确信,Rust 的异步将会稳定和统一,未来会更容易操作,但我现在就要用啊。
很多人正在学 Rust,用 Rust 编写 CLI 应用程序或底层代码,并且玩得非常开心。使用 Rust 编写普通 Web 应用程序的人明显少很多。
这是技术选择中的重要部分:是否有人在使用该工具?他们大致在同一个领域吗?不幸的是,Rust 生态系统中许多令人难以置信的令人兴奋的工作与 Web 应用服务器无关。的确存在一些很有前途的 Web 框架——甚至更高层次的框架,但毫无疑问,它们市场很小。即使是主要的 Web 框架 Actix 也只有几个顶尖贡献者。
如果 Rust 以目前的速度增长,那么社区中的 Web 部分将达到一个临界值,但我认为没有足够多的人使用 Rust 作为网站的实用工具。与其它社区相比,有很多公司致力于使用现有的工具来构建 Web 应用程序,这些工具不是最前沿的,但足够将成熟技术与新技术区分开来。
这一部分不仅仅是 Rust,它还涉及 GraphQL 生态系统,Rust 参与这个生态系统就是一个例子。
N+1问题是每个构建 Web 应用程序的人都应该知道的。要点是:你有一页照片(一次查询),你要显示每张照片的作者,会有多少次查询:1,合并照片和作者,或者在检索照片后对每张照片进行查询以获取作者?或者两次,第二次查询 ids 中的 user.id,一次获取所有作者,然后重新设置他们的照片属性。
N+1 查询通常优先使用数据库解决:比如将 N+1 查询改为单个查询,会带来明显的性能优化。我们有很多方法来尝试和解决这些问题:你可以编写 SQL,并尝试使用 CTE 和 JOIN 在单个查询中完成大量工作,就像我们在 Observable 中所做的那样,或者使用像 ActiveRecord 这样的 ORM 层将 N+1 查询转换为可预测查询的快速方法。
Juniper 是一个用于 Rust 应用程序的 GraphQL 服务。GraphQL 基本上都是由前端应用程序定义查询,而不是后端。给它一系列可以查询的东西,然后应用程序(React 或其它)将任意查询发送到后端。
这会让后端变得复杂。任何 SQL 级别的优化都不可能做到——你的服务器正在编写动态 SQL,优化只能依赖 GraphQL 服务,但它不会总是有效。例如:Juniper 默认情况下执行的是 N+1 查询,解决方案dataloader还比较粗糙且需要单独维护。因此,最终您将拥有一个非常快的应用程序层,但它所有的时间都花在了极其低效的数据库查询上。
总之,GraphQL 与 NoSQL 数据库配合使用效果非常好,它可以快速为这些类型的请求提供服务。我确信 Facebook 内部有一些特定的数据库与 GraphQL 结合在一起使用效果非常棒,但业内其他企业则非常依赖 Postgres 和同类产品。
首先,本文提到的问题并不针对在通用场景使用 Rust,只针对将 Rust 用于特定目标和生态系统,简单说就是 Web API。
注意事项 1:一般情况下,你可以用任何编程语言搭建网站,还记得基于C++实现的OkCupid吗?(译者注,OkCupid 是美国一个大型线上交友网站)还有一个非常流行的星象应用程序,Co-star,它全部是用 Haskell 编写的。如果你擅长其它编程语言,或者可以招聘到擅长这些编程语言的工程师,你一样可以取得成功。
注意事项 2:我试图构建的是重CRUD(增删改查)的 Web 应用程序 API。它可能不算是一个 Web“服务”——主要是快速、无数次地执行同一个操作,而是一个 Web“应用程序”——执行了许多不同的操作,包含了相当多的业务逻辑。如果你要开发的东西跟我在做的不一样,那我的建议可能就不适合你。如果你需要的是快速执行一两个操作,比如你正在写一个支付网关或语音消息应用程序,那 Rust 可能效果还是不错的。
注意事项 3:这篇文章写于 2021 年 1 月,如果接下来社区继续发展,Rust 将得到持续的改进,会变得更好并更易于 Web 应用程序开发。
总而言之,我真的很喜欢使用 Rust,这是一门美丽的编程语言,有很多很酷的想法。希望很快,Rust 会成为能用来构建我想做的东西的最合适的工具。不过,现在我想做的很多东西都要采用不同特性的编程语言才能更好地运行。
英文原文链接:
https://macwright.com/2021/01/15/rust.html
延伸阅读:
关注我并转发此篇文章,即可获得学习资料~若想了解更多,也可移步InfoQ官网,获取InfoQ最新资讯~
程序员至少要掌握几种编程语言?来看看这些编程语言的优势和用途
大家好,我是你们的W3Cschool小狮妹!
你可能听说过,作为一个程序员,你要学习很多种编程语言,才能应对各种不同的项目和需求。那么,程序员最少要掌握几种编程语言呢?其实,这个问题没有一个确定的答案,因为不同的编程语言有不同的优势和用途,你需要根据自己的兴趣和目标来选择适合自己的编程语言。
但是,有一些编程语言是比较基本和重要的,它们可以让你掌握不同的编程风格和维度,提高你的编程能力和思维。下面,由小狮妹来给你介绍一下这些编程语言。
我们要明白,掌握多种编程语言是有很多优势的。比如:
- 可以让你适应不同的项目和需求,比如网页开发、数据分析、人工智能、游戏开发等。
- 可以让你拓宽视野和知识面,了解不同的编程范式和思想,比如面向对象、函数式、逻辑式等。
- 可以让你提高代码质量和效率,学习不同的编程语言可以让你学习到不同的技巧和方法,比如模块化、重用、测试、调试等。
- 可以让你增加竞争力和就业机会,掌握多种编程语言可以让你在求职或者跳槽时有更多的选择和优势。
当然,掌握多种编程语言并不意味着你要精通所有的编程语言,而是要有一定的基础和了解,能够在需要时快速地学习和使用。那么,哪些编程语言是比较基本和重要的呢?小狮妹这边建议你至少学习以下几种。
C语言是一种非常经典的编程语言,它是很多其他编程语言的基础和灵感来源。C语言是一种底层的、静态的、结构化的语言,它可以让你直接操作计算机的硬件资源,比如内存、指针、数据结构等。学习C语言,可以让你明白计算机的运行机制和逻辑,对于提高你的编程能力和思维非常有帮助。
而且,C语言也是很多操作系统、嵌入式系统、游戏引擎等领域的主流语言,如果你想从事这些方面的开发,C语言是必不可少的。
Java和C++是两种非常流行和强大的编程语言,它们都是面向对象的、静态的、高级的语言。面向对象是一种非常重要的编程范式,它可以让你把复杂的问题分解成一系列的对象,每个对象都有自己的属性和方法,可以实现封装、继承、多态等特性。学习Java或C++,可以让你理解面向对象的设计和编程,提高你的代码的可读性、可维护性和可扩展性。
Java和C++也是很多领域的主流语言,比如企业级应用、桌面应用、移动应用、图形界面、网络编程等。
动态脚本语言是一些不需要编译的、灵活的、高级的语言,它们可以让你快速地开发出一些小型或者中型的应用或者功能。学习一门动态脚本语言,可以让你体验另一种编程视角,比如动态类型、元编程、函数式风格等。这些特点可以让你写出更简洁、更优雅、更易读的代码。
动态脚本语言也有很多优秀和流行的代表,比如PHP、JS和Python。PHP是网页开发中最常用的后端语言之一;JS是网页开发中唯一能在浏览器端运行的前端语言;Python是数据科学、人工智能、自动化等领域中最受欢迎的语言之一。
除了上面介绍的三种基本和重要的编程语言,还有一些其他值得关注的编程语言和风格,
除了以上提到的编程语言,还有一些其他值得关注的编程语言和风格,比如Go语言、量子编程语言和函数式编程语言。学习这些编程语言可以让你对编程的不同领域和思维方式有更深入的了解。
程序员最少要掌握几种编程语言?这个问题没有一个确定的答案,但是建议你至少学习以下几种:
- C语言:让你明白计算机的基本原理
- Java或C++:让你理解面向对象设计和编程
- 动态脚本语言Python或PHP:让你体验另一种编程视角
- 其他值得关注的编程语言和风格:让你拓展你的知识和能力
当然,这些只是小狮妹的建议,你可以根据自己的兴趣和目标来选择适合自己的编程语言~
希望这篇文章对你有所帮助,如果你有任何问题或建议,欢迎在评论区留言。谢谢!
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。