干貨分享|Web 和云開發(fā),Rust 會起飛?
發(fā)布時間:2023-08-17 14:08:27
去年,Web 開發(fā)公司 Mainmatter 對 Web 版 Rust 進(jìn)行了戰(zhàn)略押注,并發(fā)起了 EuroRust 會議,加入了 Rust 基金會,同時正在內(nèi)部以及開源領(lǐng)域從事許多 Rust 項(xiàng)目。Mainmatter 非常樂觀地認(rèn)為 Rust 將在未來幾個月和幾年內(nèi)在 Web 和云空間中起飛,并認(rèn)為 Rust 是邁向 Web 開發(fā)新時代的第一步,開發(fā)人員可以利用這項(xiàng)技術(shù),在不放棄開發(fā)人員經(jīng)驗(yàn)和生產(chǎn)力的情況下,達(dá)到更高的、以前難以想象的效率、穩(wěn)定性、可靠性和可維護(hù)性水平。這篇文章意在分享為什么 Mainmatter 有信心作這一押注,以及為什么我們相信 Rust 在 Web 和云領(lǐng)域擁有美好的未來。大廠偏愛,Rust 的未來
Rust 自從大約十年前登臺以來,就受到了很多開發(fā)人員的關(guān)注和喜愛。不僅開發(fā)人員喜歡這門語言,大公司的決策者也認(rèn)為 Rust 是一項(xiàng)偉大的技術(shù),并且在過去幾年里,該語言在整個行業(yè)得到了廣泛采用。AWS 在其平臺上大量使用 Rust ,Google 在 Android 中使用它,Microsoft 在 Windows 中使用它。從本質(zhì)上講,Rust 有望在以前使用的許多領(lǐng)域取代 C 和 C++:系統(tǒng)編程、操作系統(tǒng)、各種嵌入式系統(tǒng)、低級工具以及游戲和游戲引擎。當(dāng)然,除了以上這些,未來具有更大潛力的領(lǐng)域是 Web 和云。Rust 給這兩個領(lǐng)域帶來了無限想象的后端提升空間。一旦后端的開發(fā)提升到一個新的水平,就能讓團(tuán)隊(duì)能夠訪問以前無法實(shí)現(xiàn)的功能。盡管 Rust 還很年輕,但已經(jīng)看到很多公司在 Web 和云中成功使用 Rust,比如:Truelayer、Discord、Temporal、Nando's、svix、Wingback 等等。值得一提的是,谷歌多年來也一直大力采用 Rust,最近表示,與他們使用的任何其他語言相比,他們并沒有真正看到 Rust 的生產(chǎn)力損失。Rust 做 Web 的雄心
雖然相對年輕,畢竟距離 1.0 發(fā)布,Rust 的生態(tài)系統(tǒng)也只走過了 8 年。但 Rust 以及其 Web 生態(tài)已經(jīng)達(dá)到了一定的成熟度,足夠使其成為構(gòu)建真實(shí)應(yīng)用程序的可行選擇。正如 arewewebyet.org 所證實(shí)的,Rust 顯然已經(jīng)為 Web 做好了準(zhǔn)備:首先,有 tokio,一個異步運(yùn)行時,它是 Web 應(yīng)用程序的堅(jiān)實(shí)且高性能的基礎(chǔ);其次,最重要的是,Rust 已經(jīng)有了成熟且維護(hù)良好的 Web 框架,例如 axum 和 actix-web。所有相關(guān)數(shù)據(jù)存儲以及 ORM 都有成熟的驅(qū)動程序;最后,可以找到涵蓋構(gòu)建 Web 應(yīng)用程序的所有其他相關(guān)方面的庫,例如(反)序列化、國際化、模板化、可觀察性等。
總的來說,Rust 的雄心勃勃,構(gòu)建 Web 后端提供了堅(jiān)實(shí)而穩(wěn)定的構(gòu)建塊。當(dāng)然,有人可能會問:我為什么要換 Rust?對于已經(jīng)使用 Ruby、Java、Elixir、TypeScript、Go 或其他任何語言的團(tuán)隊(duì)而言,換 Rust 有哪些好處嗎?有兩個關(guān)鍵方面使 Rust 成為 Web 構(gòu)建的絕佳選擇:一是它的效率和性能;二是其類型系統(tǒng)帶來的可靠性和可維護(hù)性帶來的好處。Rust 以其高效和高性能而聞名。它將輕松超越 Web 應(yīng)用程序常用的 JavaScript、Ruby、Python 等語言幾個數(shù)量級。其他語言可能具有更高的性能上限(例如 Java 或 C# 或 Go),但你需要投入大量的工程精力才能接近 Rust 工具包開箱即用提供的性能水平。此外,Rust 還有一個關(guān)鍵優(yōu)勢:它不捆綁垃圾收集器。垃圾收集語言可以很快,但它們不能始終一致性地表現(xiàn)出色。垃圾收集器將引入暫停(pause)以釋放未使用的內(nèi)存,從而對應(yīng)用程序的尾部延遲產(chǎn)生負(fù)面影響。而 Rust 不存在這個問題:它可以提供一致的性能,而不會出現(xiàn)這些峰值。C 和 C++ 是唯一能夠?qū)崿F(xiàn)如此穩(wěn)定和一致性能的其他語言。不幸的是,這兩種語言往往搬起石頭砸自己腳,處處是陷阱,特別是在手動內(nèi)存管理時。正如 Linux 的創(chuàng)始人 Linus Torvalds 所說:“它離硬件太近了,你可以用它做任何事情。這很危險(xiǎn)。就像玩雜耍電鋸一樣。我還發(fā)現(xiàn)它確實(shí)有很多陷阱,而且很容易被忽視。
由于 C 和 C++ 的這些危險(xiǎn),除了這兩種語言的專家或擁有專家團(tuán)隊(duì)時才能使用。否則,你得到的就是一個不穩(wěn)定且充滿安全漏洞的系統(tǒng)。同時,別忘了,在 Web 領(lǐng)域,很少人具備這種專業(yè)知識,因?yàn)槊總€人大多都使用非常不同的語言,如 JavaScript、Python、Ruby、Elixir 等。反而 Rust 就不會遇到同樣的陷阱,使開發(fā)人員能夠以以前的效率水平構(gòu)建軟件。Rust 通常會比用于構(gòu)建 Web 后端的其他技術(shù)的性能好幾個數(shù)量級,同時保持顯著較低的內(nèi)存占用。當(dāng)然,如果與其他技術(shù)相比, Rust Web 服務(wù)器可以在一小部分時間內(nèi)響應(yīng)請求,這也意味著它可以用更少的服務(wù)器響應(yīng)相同數(shù)量的請求,這又意味著更少的托管成本。這對于中小型產(chǎn)品和公司來說,減少托管的云服務(wù)器數(shù)量,就意味每月就可以輕松減少不菲的費(fèi)用。我們的 Python 服務(wù)平均約為 50 個請求/秒,NodeJS 約為 100 個請求/秒,Rust 約為 690 個請求/秒。我們可以在通常托管單個 Python 服務(wù)的 k8 EKS 節(jié)點(diǎn)上安裝 4 個 Rust 服務(wù)?!猂eddit 某用戶
然而,成本節(jié)省還只是好處之一,使用更少的服務(wù)器也意味著使用更少的能源。盡管使用可再生能源運(yùn)行數(shù)據(jù)中心固然很好,但最綠色的能源仍然是我們不使用的能源。Rust 或許不能解決氣候危機(jī),但這里要承認(rèn)的是,運(yùn)行我們編寫的軟件,也會真真切切地消耗資源,從而對現(xiàn)實(shí)世界產(chǎn)生影響。軟件行業(yè)往往會忘記這一點(diǎn)——如果我們能夠更有效地利用資源,并以更少的投入獲得相同的產(chǎn)出,這是選擇技術(shù)時的一個重要考慮。雖然性能和效率很重要,但在許多情況下,可能更相關(guān)的原因則是 Rust 的強(qiáng)類型系統(tǒng)所帶來的可靠性和可維護(hù)性收益。像這樣的代碼片段對于 Web 應(yīng)用程序(Ruby on Rails)來說是相當(dāng)?shù)湫偷模?/span> def activate(activation_date) self.activation_date = activation_date
雖然這段代碼非常簡潔且易于閱讀,并且編寫這樣的代碼可以讓你快速實(shí)現(xiàn)目標(biāo),但也存在問題。在這個的示例中,雖然我們可以看到用戶的屬性,但我們不知道這些屬性周圍可能有什么規(guī)則(例如,如果 active 是 true,則 activation_date 可能也必須設(shè)置?如果 active 是 false,則大概 activation_date 應(yīng)該是 nil?)。為了驗(yàn)證這些假設(shè),我們必須研究該 activate 方法的實(shí)現(xiàn),這意味著需要付出相對較高的努力才能獲取信息。查看該 activate 方法的調(diào)用,我們無法知道它是否會引發(fā)錯誤,或者我們應(yīng)該在哪個時區(qū)中度過時間。雖然 Ruby 可能有點(diǎn)極端,但考慮到其眾所周知的靈活性,許多這些問題在其他語言中也存在。讓我們以 Java 為例。我們?nèi)匀粺o法在類型系統(tǒng)中對圍繞 active 和 activation_date 屬性的規(guī)則進(jìn)行編碼,即使可以 null,我們也有 NullPointerException 在運(yùn)行時獲取 s 的風(fēng)險(xiǎn)。隨著代碼庫的增長和開發(fā)團(tuán)隊(duì)的壯大,或者只是隨著一些人離開和加入而發(fā)生變化。從事代碼庫工作的每個人都對整個應(yīng)用程序以及整個代碼庫中所做的所有隱式假設(shè)都有一個完美的心智模型,但這很難做到,相反,理解這些概念需要人們認(rèn)真閱讀遺留代碼。這不僅降低了效率,而且還可能導(dǎo)致生產(chǎn)中的錯誤率增加。與上面相同的代碼片段,但在 Rust 中更加清晰和富有表現(xiàn)力: activation_date: DateTime<Utc>, fn activate(&self, activation_date: DateTime<Utc>) -> Result<(), DBError> { User::Inactive { name } => { let new_user = User::Active { activation_date: activation_date,