編譯 | 言征
去年,Web開發(fā)公司Mainmatter對Web版 Rust 進行了戰(zhàn)略押注,并發(fā)起了 EuroRust 會議,加入了 Rust 基金會,同時正在內(nèi)部以及開源領域從事許多 Rust 項目。
Mainmatter非常樂觀地認為 Rust 將在未來幾個月和幾年內(nèi)在Web和云空間中起飛,并認為Rust 是邁向 Web 開發(fā)新時代的第一步,開發(fā)人員可以利用這項技術,在不放棄開發(fā)人員經(jīng)驗和生產(chǎn)力的情況下,達到更高的、以前難以想象的效率、穩(wěn)定性、可靠性和可維護性水平。
這篇文章意在分享為什么Mainmatter有信心作這一押注,以及為什么我們相信 Rust 在Web和云領域擁有美好的未來。
一、大廠偏愛,Rust的未來
Rust 自從大約十年前登臺以來,就受到了很多開發(fā)人員的關注和喜愛。不僅開發(fā)人員喜歡這門語言,大公司的決策者也認為 Rust 是一項偉大的技術,并且在過去幾年里,該語言在整個行業(yè)得到了廣泛采用。
AWS在其平臺上大量使用 Rust ,Google在 Android 中使用它,Microsoft在 Windows 中使用它。從本質(zhì)上講,Rust 有望在以前使用的許多領域取代 C 和 C++:系統(tǒng)編程、操作系統(tǒng)、各種嵌入式系統(tǒng)、低級工具以及游戲和游戲引擎。
當然,除了以上這些,未來具有更大潛力的領域是Web和云。Rust給這兩個領域帶來了無限想象的后端提升空間。一旦后端的開發(fā)提升到一個新的水平,就能讓團隊能夠訪問以前無法實現(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)達到了一定的成熟度,足夠使其成為構(gòu)建真實應用程序的可行選擇。
正如arewewebyet.org所證實的,Rust 顯然已經(jīng)為Web做好了準備:
首先,有tokio,一個異步運行時,它是Web應用程序的堅實且高性能的基礎;其次,最重要的是,Rust已經(jīng)有了成熟且維護良好的 Web 框架,例如axum和actix-web。所有相關數(shù)據(jù)存儲以及 ORM 都有成熟的驅(qū)動程序;最后,可以找到涵蓋構(gòu)建 Web 應用程序的所有其他相關方面的庫,例如(反)序列化、國際化、模板化、可觀察性等。
總的來說,Rust的雄心勃勃,構(gòu)建 Web 后端提供了堅實而穩(wěn)定的構(gòu)建塊。
三、有必要換Rust做Web?
當然,有人可能會問:我為什么要換Rust?對于已經(jīng)使用 Ruby、Java、Elixir、TypeScript、Go 或其他任何語言的團隊而言,換 Rust有哪些好處嗎?
有兩個關鍵方面使 Rust 成為 Web 構(gòu)建的絕佳選擇:一是它的效率和性能;二是其類型系統(tǒng)帶來的可靠性和可維護性帶來的好處。
1.效率和性能
Rust 以其高效和高性能而聞名。它將輕松超越 Web 應用程序常用的 JavaScript、Ruby、Python 等語言幾個數(shù)量級。其他語言可能具有更高的性能上限(例如 Java 或 C# 或 Go),但你需要投入大量的工程精力才能接近 Rust 工具包開箱即用提供的性能水平。
此外,Rust 還有一個關鍵優(yōu)勢:它不捆綁垃圾收集器。垃圾收集語言可以很快,但它們不能始終一致性地表現(xiàn)出色。垃圾收集器將引入暫停(pause)以釋放未使用的內(nèi)存,從而對應用程序的尾部延遲產(chǎn)生負面影響。而Rust 不存在這個問題:它可以提供一致的性能,而不會出現(xiàn)這些峰值。
C 和 C++ 是唯一能夠?qū)崿F(xiàn)如此穩(wěn)定和一致性能的其他語言。不幸的是,這兩種語言往往搬起石頭砸自己腳,處處是陷阱,特別是在手動內(nèi)存管理時。正如 Linux 的創(chuàng)始人 Linus Torvalds 所說:
“它離硬件太近了,你可以用它做任何事情。這很危險。就像玩雜耍電鋸一樣。我還發(fā)現(xiàn)它確實有很多陷阱,而且很容易被忽視。
由于 C 和 C++ 的這些危險,除了這兩種語言的專家或擁有專家團隊時才能使用。否則,你得到的就是一個不穩(wěn)定且充滿安全漏洞的系統(tǒng)。
同時,別忘了,在 Web 領域,很少人具備這種專業(yè)知識,因為每個人大多都使用非常不同的語言,如 JavaScript、Python、Ruby、Elixir 等。反而Rust 就不會遇到同樣的陷阱,使開發(fā)人員能夠以以前的效率水平構(gòu)建軟件。
Rust 通常會比用于構(gòu)建 Web 后端的其他技術的性能好幾個數(shù)量級,同時保持顯著較低的內(nèi)存占用。
當然,如果與其他技術相比, Rust Web 服務器可以在一小部分時間內(nèi)響應請求,這也意味著它可以用更少的服務器響應相同數(shù)量的請求,這又意味著更少的托管成本。
這對于中小型產(chǎn)品和公司來說,減少托管的云服務器數(shù)量,就意味每月就可以輕松減少不菲的費用。
我們的 Python 服務平均約為 50 個請求/秒,NodeJS 約為 100 個請求/秒,Rust 約為 690 個請求/秒。我們可以在通常托管單個 Python 服務的 k8 EKS 節(jié)點上安裝 4 個 Rust 服務。——Reddit某用戶
然而,成本節(jié)省還只是好處之一,使用更少的服務器也意味著使用更少的能源。盡管使用可再生能源運行數(shù)據(jù)中心固然很好,但最綠色的能源仍然是我們不使用的能源。Rust 或許不能解決氣候危機,但這里要承認的是,運行我們編寫的軟件,也會真真切切地消耗資源,從而對現(xiàn)實世界產(chǎn)生影響。軟件行業(yè)往往會忘記這一點——如果我們能夠更有效地利用資源,并以更少的投入獲得相同的產(chǎn)出,這是選擇技術時的一個重要考慮。
2.可靠性和可維護性
雖然性能和效率很重要,但在許多情況下,可能更相關的原因則是 Rust 的強類型系統(tǒng)所帶來的可靠性和可維護性收益。
像這樣的代碼片段對于 Web 應用程序(Ruby on Rails)來說是相當?shù)湫偷模?/p>
復制
class User
attr :name
attr :active
attr :activation_date
def activate(activation_date)
self.active = true
self.activation_date = activation_date
save
end
def save
…
end
end
…
user.activate(Time.now)
雖然這段代碼非常簡潔且易于閱讀,并且編寫這樣的代碼可以讓你快速實現(xiàn)目標,但也存在問題。在這個的示例中,雖然我們可以看到用戶的屬性,但我們不知道這些屬性周圍可能有什么規(guī)則(例如,如果active是true,則activation_date可能也必須設置?如果active是false,則大概activation_date應該是nil?)。為了驗證這些假設,我們必須研究該activate方法的實現(xiàn),這意味著需要付出相對較高的努力才能獲取信息。
查看該activate方法的調(diào)用,我們無法知道它是否會引發(fā)錯誤,或者我們應該在哪個時區(qū)中度過時間。雖然 Ruby 可能有點極端,但考慮到其眾所周知的靈活性,許多這些問題在其他語言中也存在。讓我們以 Java 為例。我們?nèi)匀粺o法在類型系統(tǒng)中對圍繞active和activation_date屬性的規(guī)則進行編碼,即使可以null,我們也有NullPointerException在運行時獲取 s 的風險。
隨著代碼庫的增長和開發(fā)團隊的壯大,或者只是隨著一些人離開和加入而發(fā)生變化。從事代碼庫工作的每個人都對整個應用程序以及整個代碼庫中所做的所有隱式假設都有一個完美的心智模型,但這很難做到,相反,理解這些概念需要人們認真閱讀遺留代碼。這不僅降低了效率,而且還可能導致生產(chǎn)中的錯誤率增加。
與上面相同的代碼片段,但在 Rust 中更加清晰和富有表現(xiàn)力:
復制
enum User {
Inactive {
name: String,
},
Active {
name: String,
active: bool,
activation_date: DateTime,
},
}
impl User {
fn activate(&self, activation_date: DateTime) -> Result<(), DBError> {
match self {
User::Inactive { name } => {
let new_user = User::Active {
name: name.clone(),
active: true,
activation_date: activation_date,
};
new_user.save()
}
User::Active { .. } => Err(Error::default()),
}
}
fn save(&self) -> Result<(), DBError> {
…
}
}
首先,對于用戶模型,我們可以使用 Rust 的enum關聯(lián)數(shù)據(jù)。這樣,就可以完全清楚非活躍用戶和活躍用戶是什么樣子,以及在什么場景下可以設置哪些屬性——事實上,活躍用戶和非活躍用戶甚至不具有相同的屬性,但每個用戶都只具有對其有意義的屬性。它們代表各自的用戶狀態(tài)。此外,屬性的類型也被明確定義——不僅 Rust 是類型化的,而 Ruby 顯然是非類型化的,而且類型也非常精確,例如對于字段,activation_date預期的時區(qū)在類型中也是正確的。
該函數(shù)的簽名activate還顯式地編碼了 Rails 示例中隱含的許多信息。同樣,預期的時區(qū)activation_date在類型中是正確的,并且該函數(shù)返回Rust 的時區(qū)Result,這清楚地表明調(diào)用它時可能會發(fā)生錯誤。Result事實上,Rust 編譯器將要求處理的成功和錯誤變體,以便不會發(fā)生未處理的運行時異常。
此外,activation_date當調(diào)用函數(shù)時,函數(shù)的參數(shù)總是保證有一個值,因為 Rust 沒有隱式可空性的概念(與 Java 不同)。如果activation_date 可能在其計算位置沒有值,則它可能無法Option>傳遞給函數(shù)activate,因為它的類型與預期的不同DateTime。Rust 編譯器只允許Some其變體的代碼路徑Option導致方法的調(diào)用activate,以便activation_date保證在函數(shù)運行時有一個值。
雖然這顯然是一個相當簡單的示例,但它很好地說明了 Rust 的兩個主要優(yōu)點:
(1)Rails 示例中隱含的許多概念和規(guī)則都是通過 Rust 代碼中的類型顯式傳達的?梢郧宄貐^(qū)分活躍用戶和非活躍用戶,對于日期字段,甚至預期的時區(qū)也被編碼在類型中。這種表現(xiàn)力使代碼更容易理解,特別是對于代碼庫的新手來說,從而提高了可維護性。
(2)Rust 還大大提高了可靠性,因為其他語言(包括 Java 或 Go 等類型化語言)中常見的整類錯誤將在編譯時而不是運行時檢測到。編譯器保證函數(shù)activation_date的參數(shù)activate具有值以及要處理的函數(shù)可能返回的任何錯誤。
總體而言,當每個人都關注 Rust 的性能時,Rust 帶來的可靠性和可維護性方面的改進常常被忽視。然而,這些好處對于項目的長期成功可能比純粹的績效數(shù)字更相關。
四、Rust先苦后甜
由于 Rust 的主要優(yōu)點是可靠性、可維護性、效率和性能,因此該語言的用例顯然是與這四個方面特別相關的用例。但是,好處的代價是需要考慮在內(nèi)。
總體而言,Rust 仍然需要比其他技術更高的前期投資,特別是與 Web 項目中常用的技術相比:
雖然像 JavaScript 和 Ruby 這樣的語言是為了快速獲得結(jié)果而設計的,但 Rust 則沒有留下太多的自由度,并且要求程序在獲得工作結(jié)果之前通過所有編譯器的檢查。與這些語言相比,使用 Rust 就需要付出更多的初始工作。此外,人們在使用 Rust 之前還需要翻越一座山——那就是掌握 Rust 獨特的所有權(quán)系統(tǒng)。
然而,當跨過項目的初始階段并將視野擴展到更長的時間范圍時,可維護性、可靠性和穩(wěn)定性等方面變得極其重要,一開始使用 Rust 時進行的額外投資會隨著時間的推移而帶來回報——
Rust 應用程序更可靠,因此需要更少的時間投入到錯誤修復上,并且更易于維護,因此更容易與不斷增長和變化的團隊一起有效地工作。
最后就會呈現(xiàn)出:Rust工作量先大后小,先苦后甜。對于其他語言來說,情況往往是相反的:隨著時間的推移,隨著團隊的成長,可靠性和可維護性挑戰(zhàn)的影響變得更大、成本更高,工作量也會增加。
五、用Rust前的幾個問題
根據(jù) Rust 的優(yōu)勢和投入曲線,每當評估是否針對特定情況選擇 Rust 時,需要回答的主要問題是:
(1)團隊是否已經(jīng)具備 Rust 專業(yè)知識(許多不使用 Rust 的團隊實際上已經(jīng)擁有專業(yè)知識,因為很多開發(fā)人員在空閑時間使用 Rust 編寫代碼)?
(2)可靠性方面有哪些要求?
(3)長期維護計劃是什么?
(4)系統(tǒng)構(gòu)建的規(guī)模有多大,Rust 在托管方面可以節(jié)省多少錢?
(5)根據(jù)以上問題的答案,額外的初始投資值得嗎?
雖然在某些情況下,結(jié)論是額外的初始投資不值得,但在某些情況下,評估顯然對 Rust 有利。我們看到的一些典型用例包括:
(1)對于實現(xiàn)產(chǎn)品關鍵業(yè)務邏輯的核心業(yè)務系統(tǒng)來說,可靠性、長期可維護性等方面是首要考慮的問題。
(2)對于金融系統(tǒng)來說,通常對錯誤的容忍度很低,而 Rust 帶來的穩(wěn)定性的提高可能是一個決定性因素。另外,性能是一項關鍵要求,在特定場景(例如交易系統(tǒng))中具有明顯的財務影響。
(3)任何必須能夠提供高吞吐量和性能的系統(tǒng)顯然都會從 Rust 中受益。位于多個微服務前面的代理服務器等系統(tǒng)必須具有最小的開銷和一致的性能。在這些情況下,垃圾收集語言及其不可靠的性能特征通常不是一個選擇。
(4)最后,對于任何大規(guī)模運行的系統(tǒng),在托管成本方面都有很大的節(jié)省潛力。
一旦做出了使用 Rust 的決定,就有兩種主要的采用路徑——要么用 Rust 從頭開始(重新)編寫整個應用程序,要么考慮與其他技術一起逐步采用。篇幅原因,就不再展開了。
文章內(nèi)容僅供閱讀,不構(gòu)成投資建議,請謹慎對待。投資者據(jù)此操作,風險自擔。
2024年的Adobe MAX 2024發(fā)布會上,Adobe推出了最新版本的Adobe Creative Cloud。
奧維云網(wǎng)(AVC)推總數(shù)據(jù)顯示,2024年1-9月明火炊具線上零售額94.2億元,同比增加3.1%,其中抖音渠道表現(xiàn)優(yōu)異,同比有14%的漲幅,傳統(tǒng)電商略有下滑,同比降低2.3%。
“以前都要去窗口辦,一套流程下來都要半個月了,現(xiàn)在方便多了!”打開“重慶公積金”微信小程序,按照提示流程提交相關材料,僅幾秒鐘,重慶市民曾某的賬戶就打進了21600元。
華碩ProArt創(chuàng)藝27 Pro PA279CRV顯示器,憑借其優(yōu)秀的性能配置和精準的色彩呈現(xiàn)能力,為您的創(chuàng)作工作帶來實質(zhì)性的幫助,雙十一期間低至2799元,性價比很高,簡直是創(chuàng)作者們的首選。
9月14日,2024全球工業(yè)互聯(lián)網(wǎng)大會——工業(yè)互聯(lián)網(wǎng)標識解析專題論壇在沈陽成功舉辦。