其實,Rust不適合開發Web API

Rust 是一門神奇的編程語言,有非常好的 CLI 工具,比如 ripgrep 和 exa。像 Cloudflare 這樣的公司正在使用並鼓勵人們寫 Rust 來運行微服務。Rust 編寫的軟件可能比 C++ 或 C 更安全、更小、更簡潔。

如果我正在編寫一個地理編碼器、一個路由引擎、一個實時消息平臺、一個數據庫或一個 CLI 工具,Rust 最合適。

但去年,我試圖用 Rust 寫一個傳統網站的純 API 服務,Rust 就不合適了。

1缺失很多小功能

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 令人印象深刻,非常棒。

2Rust 編譯器比以前快,但仍然很慢

我一直在看 Nicholas Nethercote 的博客,描述了 Rust 團隊如何優化編譯器,讓它更快!

但與其它編程語言相比,用它構建網站會很慢。它比編譯型編程語言 Go 慢得多,也比解釋型編程語言 JavaScript、Ruby 和 Python 等慢得多。

一旦代碼被編譯,一切就變得非常棒了!但在我的情況下,甚至基本 API 功能都不完整,一個不復雜的系統——居然花了 10 多分鐘來編譯。Google 代碼構建的硬件配置很差,每次都會超時,我啥都編譯不了。

只要不重建緩存依賴項,緩存就有意義。也許減少依賴會加快 Rust 項目編譯。但就像 serde,幾乎所有人都使用的 JSON 和其它序列化 / 反序列化程序佔用了大量的編譯時間。我們是否應該用編譯速度更快但缺乏大量文檔和生態系統支持的東西來取代 serde?這種取捨非常糟糕。

3Rust 很複雜

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 的異步將會穩定和統一,未來會更容易操作,但我現在就要用啊。

4Rust 生態系統不是以 Web 爲中心的

很多人正在學 Rust,用 Rust 編寫 CLI 應用程序或底層代碼,並且玩得非常開心。使用 Rust 編寫普通 Web 應用程序的人明顯少很多。

這是技術選擇中的重要部分:是否有人在使用該工具?他們大致在同一個領域嗎?不幸的是,Rust 生態系統中許多令人難以置信的令人興奮的工作與 Web 應用服務器無關。的確存在一些很有前途的 Web 框架——甚至更高層次的框架,但毫無疑問,它們市場很小。即使是主要的 Web 框架 Actix 也只有幾個頂尖貢獻者。

如果 Rust 以目前的速度增長,那麼社區中的 Web 部分將達到一個臨界值,但我認爲沒有足夠多的人使用 Rust 作爲網站的實用工具。與其它社區相比,有很多公司致力於使用現有的工具來構建 Web 應用程序,這些工具不是最前沿的,但足夠將成熟技術與新技術區分開來。

5Juniper 的 N+1 次查詢

這一部分不僅僅是 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 和同類產品。

6一些注意事項

首先,本文提到的問題並不針對在通用場景使用 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

1.國產替代摸不着門兒?快來回看兆易創新直播課!

2.開源的RISC-V能否成爲中國“缺芯”的解藥?

3.樹莓派Pico:僅4美元的MCU

4.MCU支持AI功能的多種原因~

5.2020年,我學習到的20條軟件工程準則~

6.狀態機思路在嵌入式開發中的應用~

免責聲明:本文系網絡轉載,版權歸原作者所有。如涉及作品版權問題,請與我們聯繫,我們將根據您提供的版權證明材料確認版權並支付稿酬或者刪除內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章