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