Rust是目前最優雅而且熱門的程式語言之一,性能上可以比肩C、編譯時安全、沒有GC的累贅、異步和範型支持,註定這是將來流行的語言。一般認為Rust是一個很好的系統語言,但實際上Rust在各個領域都做的不錯,今天我們就來說說Rust的Web框架。
概述
截至2020年7月,Rust生態系統中的主要Web框架有:actix-web、rocket、tide和warp。那麼問題來了:如果要用Rust構建一個生產環境用的API,應該選擇哪框架呢?
本文我們就來解答這個問題,我們將從幾個方面對上述的各個框架予以說明:包括全面性(功能全面)、社區與採納度、同步和異步(及其選擇的future運行時)、文檔教程和示例以及API和人機工程學。
當然蟲蟲歷來奉行這樣的理念那就是沒有絕對的選擇:不同的環境(和個人好惡)可能會導致選擇不同的架構。
全面性
actix-web,tide和warp都是瘦web框架:他們只提供基本的HTTP Web伺服器,路由邏輯,中間件基礎設施,基本的構建模塊和抽象,從而解析、操作和響應HTTP請求。
rocket框架則與他們相反:它旨在一棧擼,對最常見的需求都可以通過rocket中的組件來提供,隨要隨取,開箱即用。另外它也提供了擴展機制,開發人員可以使用hook擴展用例。
rocket發內置了和ORM集成,可以管理和配置流行資料庫(例如Postgres,Redis,Memcache等)。
與其他語言的Web框架進來對比的話:
actix-web,tide和warp更像是Python語言的Flask或JS中的Express Javascript但是沒有提供現成的配置管理系統或ORM集成。需要有開發者手動自定義構建API,並需要引入所需的功能庫,自己處理圖片樣式等;
rocket則更接近於Python的Django或PHP的Symphony框架:擁有一個穩定而強大的核心,附帶一組高質量組件,可滿足構建堅固的Web應用程式時的日常需求。rocket要在寬度和範圍上與同行匹敵,還有很長的路要走,但這絕對是一個良好的開端。
當然,這是截止目前各框架的情況,各個框架可能也會不斷地調整改善。比如actix-web已經在慢慢積累更多的功能(從安全到會話管理),在GitHub下actix組織的actix-extras倉庫收集了相關的生態體系。
另外需要說明的是,用瘦Web框架開發,也並非就是從零開始要自己動手構建所有內容,畢竟有社區的生態體系,我們需要弄的也是別人需要的,很多已經前人幫我都做好了,我們無需重複造輪子,只需"拿來"用就好了。
社區與採納度
針對四個web框架,我們瀏覽Rust crates庫中的統計數字如下:
構架 總下載量 日下載量
actix-web 1250k 3000
rocket 525k 1000
warp 435k 3000
tide 47k 300
由於各個框架出現的早晚有別,總下載量不能客觀反映框架的流行程度,但是日下載量可以很好地衡量一個框架的目前的流行程度。我們考慮社區規模和流行程度主要考慮以下因素:
具有規模應用的框架,有更多人幫我們趟過它的坑,所以其穩定性也會更好。
規模越,該框架的支持crates的數量也越多;
框架用的人多,其使用教程,問題解決方案和使用經驗也會越多,遇到問題更容易得到解決。
對瘦框架來說,支持crates數量也是框架可實用的關鍵。我搜索框架名稱時查看在crates.io的搜索結果數,可以反應各個框架的社區規模的影響:
構架 搜索結果
rocket 178
actix-web 113
warp 57
tide 20
儘管搜索結果中的這些crates並非都會與搜索的框架相關,他們中也有一些可能是過時或者無法使用的。但是這個結果確實能反應一個框架的了流行程度和實用操作性。比如:
如果需要將Prometheus的指標添加到的API中,則可以使用actix-web-prom或rocket-prometheus在幾分鐘之內手動搞定,兩者都有數千次下載量。如果你選擇warp或tide框架,則這些工作都需要自己開始編寫和集成;
如果要添加分布式跟蹤,則可以使用actix-web-opentelemetry。如果選擇任何其他框架,則需要自己手動實現。
同步與異步
Rust 1.39版本(2019-11-07)中引入了async/await語法,改變了Rust異步編程的體驗。當然Rust生態系統追趕並採用async/await異步還需要一些時間,但是可以公平地說,處理IO受限工作負載的brates現在都是是異步優先的(例如reqwest)。那麼Web框架方面的情況呢?
actix-web和warp在0.2.x中 開始支持async/await,而tide中async/await支持基於其nightly rust編譯器。
rocket,仍然會公開一個同步接口。async/await支持預計將在其0.5發行版中提供,目前尚不支持異步編程。
如果要實現一個對性能嚴格要求的,大流量web應用程式,則最好選擇異步Web框架。
如果不是上面這種情況,那麼儘管缺少異步支持,選擇rocket也應該不是啥問題。
future運行時
Rust的異步編程是建立在其Future trait之上的:Future公開了poll一種必須調用的方法,以允許Future同步更新。可以將Rust的futur視為惰性的:除非進行poll,否則無法保證它們會執行完畢。與其他語言所採用的推模型相比,
異步運行時實際上是項目的依賴項,以brates形式引入,這為我們提供了極大的靈活性:確實可以實現自己的運行時,以針對用例的特定要求進行優化或者僅根據情況選擇最合適的運行時。
從表面上看,聽起來很棒,但現實卻很痛苦:目前,運行時之間的互操作性還很差。混合運行時可能會很痛苦,通常會導致無法分流、檢測或解決的問題不直接。
儘管大多數庫不應直接依賴於運行時,而應依賴futures庫公開的接口,但由於歷史包(例如tokio,長期以來是生態系統中唯一可用的運行時),實際需要(例如,一個框架必須能夠產生任務)或缺乏標準化。
因此,選擇一個異步Web框架超出了框架本身的範圍:正在選擇一個由brates組成的生態系統,這突然使依賴於不同異步運行時的庫變得更加麻煩。
當前的事務狀態還很不理想,但是如果從現在開始要編寫異步Rust,那麼建議在異步運行時進行做慎重的選擇。
目前在Rust中可用的兩個主要通用異步運行時為tokio和async-std。
tokio已經存在了很長一段時間,並且已經廣泛用於生產中。儘管這會導致更大,更複雜的API,但是它是相當可調的。
async-std是一年前發布的,和async/await穩定發布時間差不多。它提供了出色的人性化設計,同時為配置擴展留下了更少的空間。
crates搜索中,兩者的統計數據如下:準:
運行時 下載總量 日下載量
tokio 9600k 30k
async-std 600k 4千
四個web框架的對兩者的選擇如下:
構架 運行時
actix-web tokio
rocket(0.5.x) tokio
tide async-std
warp tokio
文檔,教程和示例
必須深入原始碼以了解某項工作原理是一件很意義的事情,但只應該一種選擇,而不是必須的。在大多數情況下,要依靠記錄良好的框架,包括有關使用模式的簡單示例。
良好的文檔,教程和功能齊全的示例對任務至關重要,特別是團隊中一個或多個成員都不是經驗豐富的Rust開發人員的時候。
Rust的生態體系將文檔為最重要的部分(只需運行cargo doc --open即可自動生成項目文檔),這也是Rust社區本身文化的一部分。庫作者通常會認真對待文檔,Web框架也不例外。在docs.rs上可以找到非常詳盡的內容,並在需要時提供上下文示例。
rocket和actix-web在各自的網站上提供高級文檔指南,所有框架都將大量示例作為其代碼庫的一部分。
項目文檔的教程之外的大多是一些隨時間的積累:actix-web和rocket很容易找到的材料(文章,講座,workshop),而warp和tide的材料則較為有限。在另一面,大量的材料可能會存在過時的情況,這些針對老版本的材料可能會引起誤解,這也是初學者常見的困惑之一。
這就是蟲蟲不建議大家使用搜尋引擎搜索材料,而是儘可能先去學習官方文檔。
總結
2020年今天面對這些Web框架,如何選擇呢?
7月開始,我建議actix-web選擇是否要在Rust中編寫生產API。
首先針對actix-web:
它已廣泛用於生產;依靠tokio作為異步運行時,從而最大程度地減少與異步生態系統中最流行的包的兼容性問題的可能性;擁有大量成熟的插件以及最大的社區。
儘管它的某些API絕對不是最符合人性化,但考慮到所有因素,這帶來的不便肯定很小。
當然如果都按部就班,不願意嘗試,Rust框架就無法百花齊放,繁榮昌盛。其他web框架也優勢明顯
tide並warp使用異步Rust突破了人性化極限;
用rocket可以最大程度上享受其功能方面的優勢,但是它採用了async/await以及用nightly Rust編譯器進行移植。
當然最好的框架是不用框架,是用自己的框架,如果你心有餘,力所及,去創建一個自己的Rust框架也是一個非常好的選擇,如果你有這方面的打算或者已經做了這方面的工作,請at蟲蟲,如果下次介紹Rust框架,我將予以優先介紹。