溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Rust Web框架有哪些

發(fā)布時間:2021-11-19 16:54:28 來源:億速云 閱讀:450 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“Rust Web框架有哪些”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Rust Web框架有哪些”吧!

Rust常見Web框架

Rust目前已知的Web框架也有幾十種,在flosse的rust-web-framework-comparison開源項目里面詳細列出(見文末參考資料的鏈接),感興趣的可以查看。但遺憾的是官方也沒有給出支持或者推薦的Web框架,所以我們就實際項目簡單使用的情況,挑出幾個比較下,希望給大家選型框架時參考下。

Rust Web框架的難點

在比較這些框架之前,我們先回顧下Rust語言處理Web流程困難的地方。眾所周知,Rust近年發(fā)展迅猛,同時也帶來一些新的概念,比如生命周期等,另外rust沒有全局狀態(tài),或者說實現(xiàn)比較困難,以及編譯檢查比較嚴(yán)格,相對速度也比較慢,這樣對實現(xiàn)web框架帶來一些困難,下來我們看下這些框架的實現(xiàn)情況。

Rust Web框架分類

Rust  Web框架中,hyper、h3、tiny-http屬于底層一些的框架,比如hyper,很多框架都是基于它開發(fā)的,它也是Rust語言中比較老牌的框架;Rocket框架相對比較專注,  大名鼎鼎的tokio的作者實現(xiàn)的Tower,目前跟warp交流較多,有可能會合并大家也可以持續(xù)關(guān)注;iron、gotham、nickel、rouille、actix-web功能相對全面些,就像其中Actix框架整個體系龐大,下面又拆分出許多子框架:web、http、net等。

Rust主流Web框架的比較

下面我們終于進入正題,挑出幾個我們實際項目中使用過的框架進行比較。當(dāng)然,可能有些框架的特性我們并未涉獵,文中有不妥之處歡迎指正。

Hyper

第一個出場的就是hyper,它的特點就是高性能,后面會給出的壓測結(jié)果,跟actix-web差不多;另外首先實現(xiàn)了Client組件,方便寫單元測試驗證;前面也提到很多web框架基于hyper實現(xiàn),側(cè)面說明他底層的封裝還是不錯的。不過它也有些缺點:

  • hyper應(yīng)用側(cè)的功能相對少,所以會導(dǎo)致很多框架又在他的基礎(chǔ)上繼續(xù)封裝;

  • 通過match block實現(xiàn)路由,這個筆者認為是一個比較明顯的缺點; 比如下面的例子:

async fn response_examples(     req: Request<Body>,client: Client<HttpConnector> ) -> Result<Response<Body>> {     match (req.method(), req.uri().path()) {         (&Method::GET, "/index.html") => {             Ok(Response::new(INDEX.into()))         },        (&Method::GET, "/json_api") => {             api_get_response().await         }         _ => {    Ok(Response::builder().status(StatusCode::NOT_FOUND)                 .body(NOTFOUND.into())                 .unwrap())         }     } }

這是一個典型的hyper的實現(xiàn),但實際項目中的match塊處理較復(fù)雜的流程時往往需要翻一兩頁,這樣開發(fā)和review都相對困難。

Actix-web

Actix-web是已知的所有web框架實現(xiàn)了actor模型,由微軟的工程師 Nikolay  開發(fā),Azure用的比較多;超級快是另一個優(yōu)點,在web性能評測網(wǎng)站刷榜,但有取巧嫌疑,下面會展開說下他怎么做的;底層基于tokio。整體層級結(jié)構(gòu)如下:

  • tokio && futures -> actix-net/actix-rt -> actix-net/其他子crate  -> actix-web

對于整個actix來說,功能還是比較豐富;今年6月發(fā)布的的1.0,進一步簡化actor模塊,service替代handle,大量的簡化代碼。

  • 缺點:大量的unsafe(如下圖),導(dǎo)致經(jīng)常有開發(fā)爆出堆棧溢出的bug;這也是他性能最好的原因之一;

Rust Web框架有哪些

他的另外一個缺點,代碼質(zhì)量不高,頻繁變動,至少是web模塊這塊,文檔和實例也不全;比如0.7版的handle,到1.0版變成service,他封裝的responder,也不穩(wěn)定,下面跟rocket的實現(xiàn)一起展開比較。

Rocket

Rocket是目前Rust主流的Web框架之一,github項目有8.9k的star。而它的http處理部分就是基于前面提到的Hyper。從官方資料看,具有如下三個特點:

  • 類型安全;

  • 上手簡單,讓你更專注于自己的業(yè)務(wù);

  • 組件豐富,且?guī)缀醵伎梢宰远x;

Rocket從筆者使用經(jīng)驗來看:確實上手非???,對各種語言背景的開發(fā)人員都相對友好;擴展容易,他的組件幾乎都可以自定義,requestGuard、state、fairing  都可以定制;另外,文檔、example都非常詳細,預(yù)定義很多宏,非常方便;  Rocket的缺點:性能上會略差些,后面會給出壓測數(shù)據(jù)。不過他的async分支也快發(fā)布了,都打磨了幾個月,大家可以關(guān)注;

匯總

簡單匯總一個表格(如下圖),總結(jié)下:從大家的關(guān)注度上,Rocket勝出;Actix-web的功能會多些,比如websocket等;從使用和應(yīng)用層的周邊支持上,Rocket做的最好;所以不太在意性能的話,建議選擇Rocket。下來我們就就詳細討論下Rocket。

Rust Web框架有哪些

Rocket

Rocket設(shè)計原則

首先看下rocket的設(shè)計原則,這也是其他框架沒有的,而且他們實際代碼落地上也履行的不錯,具體原則如下:

  • Security, correctness, and developer experience are paramount.

  • All request handling information should be typed and self-contained

  • Decisions should not be forced

筆者的理解:

  • 安全性,正確性和開發(fā)人員經(jīng)驗至關(guān)重要。這就充分挖掘了rust安全方面的優(yōu)勢,且對各語言開發(fā)人員友好,  后面講到request、guards這兩個組件再展開下;

  • 所有被處理請求信息都必須指定類型。這樣也對開發(fā)人員有所約束, 比如在使用Responder組件就深有感觸;

  • 不應(yīng)該強行限制。他的模板、序列化、會話等組件,幾乎所有的功能都是可選擇的插件形式。對于這些,Rocket都有官方庫和支持,完全可以自由選擇和替換。  所以,Rocket是Rust Web框架里面,完美的平衡了自由和約束。下面我們就幾個重要組件詳細展開。

RequestGuards

RequestGuards有些類似java的spring框架的velidator,是代表任意驗證策略的類型,驗證策略通過FromRequest實現(xiàn)。RequestGuards沒有數(shù)量限制,實際使用中根據(jù)自己需求添加,也可以自定義Guards。舉個例子:

#[get("/<param>")] fn index(param: isize, a: A, b: B, c: C) -> ... { ... }

上述例子中的A、B、C都是具體的實現(xiàn),比如A驗證auth,B驗證計數(shù),C具體業(yè)務(wù)校驗等;也可以用框架已經(jīng)實現(xiàn)的guard,或者自己定義,整體還是非常靈活。guard組件也是履行他的第一個設(shè)計原則:正確性、安全性;

Responder

我們直接看下Responder的定義:

pub trait Responder {     /// Returns `Ok` if a `Response` could be generated successfully. Otherwise,     /// returns an `Err` with a failing `Status`.     ///     /// The `request` parameter is the `Request` that this `Responder` is     /// responding to.     ///     /// When using Rocket's code generation, if an `Ok(Response)` is returned,     /// the response will be written out to the client. If an `Err(Status)` is     /// returned, the error catcher for the given status is retrieved and called     /// to generate a final error response, which is then written out to the     /// client.     fn respond_to(self, request: &Request) -> response::Result; }

筆者翻了一下這個trait的代碼記錄,從16年最開始設(shè)計就已經(jīng)確定,非常穩(wěn)定,之后再沒有更新過。respond_to返回的Result,他封裝了一下,要么是OK,要么是一個Err的status。  另外內(nèi)置實現(xiàn)了常用的類型( str 、String、 [u8] 、 File、 Option、 Status  ),基本覆蓋絕大部分業(yè)務(wù)場景;如果還不能滿足,那你也可以實現(xiàn)自定義的responder。  這也就體現(xiàn)他的第二設(shè)計原則:類型約束。不像其他的框架,比如Actix-web也有responder,但也是最近的版本才穩(wěn)定下來。如下要想自定義怎么辦?  這是一個自定義的例子:

impl Responder for Person {     fn respond_to(self, _: &Request) -> response::Result {         Response::build()              .sized_body(Cursor::new(format!("{}:{}", self.name, self.age)))              .raw_header("X-Person-Name", self.name)             .header(ContentType::new("application", "x-person"))             .ok()      }  } #[get("/person")]  fn person() -> Person { Person { name: "a".to_string(), age: 20 } }

這就是自定義的一個responder,直接返回一個Person對象;也可以加上err的處理;看起來還是比較簡單吧。我們可以對比下Actix-web的responder的實現(xiàn):

pub trait Responder {     /// The associated error which can be returned.     type Error: Into<Error>;      /// The future response value.     type Future: Future<Output = Result<Response, Self::Error>>;      /// Convert itself to `AsyncResult` or `Error`.     fn respond_to(self, req: &HttpRequest) -> Self::Future;       fn with_status(self, status: StatusCode) -> CustomResponder<Self>         where             Self: Sized,     {         CustomResponder::new(self).with_status(status)     }       fn with_header<K, V>(self, key: K, value: V) -> CustomResponder<Self>        &hellip; &hellip; }

Actix-web是19年3月份才有這個組件的,status,header還是后來加;實現(xiàn)的起來復(fù)雜的多;

State

我們看下Rocket的State組件,也是最后一個原則的體現(xiàn)。直接舉例說明:

use rocket::State; use rocket::response::content;  struct HitCount(AtomicUsize);  #[get("/")] fn index(hit_count: State<HitCount>) -> content::Html<String> {     hit_count.0.fetch_add(1, Ordering::Relaxed);     let msg = "Your visit has been recorded!";     let count = format!("Visits: {}", count(hit_count));     content::Html(format!("{}<br /><br />{}", msg, count)) }  #[get("/count")] fn count(hit_count: State<HitCount>) -> String {     hit_count.0.load(Ordering::Relaxed).to_string() }  fn rocket() -> rocket::Rocket {     rocket::ignite()         .mount("/", routes![index, count])         .manage(HitCount(AtomicUsize::new(0))) }

這是一個計數(shù)器的簡單實現(xiàn),通過state注入到handle中,每次訪問/都加1;也可以通過/cout接口拿到當(dāng)前計數(shù);這兩接口是無狀態(tài)的,但count是全局的,這就是state的魅力;  當(dāng)然state可以干的事情很多,另外也內(nèi)置實現(xiàn)了Request-local state,類似于thread-local 可以做鏈路跟蹤;

Fairing

Rocket還有個Fairing組件,結(jié)合上面提到的state組件,可以實現(xiàn)應(yīng)用啟動時,或者state的attach時,請求和響應(yīng)時的一些定制;比如定制filter,日志等插件都可以實現(xiàn);

#[derive(Default)] struct Counter {     get: AtomicUsize,     post: AtomicUsize, } impl Fairing for Counter {      fn on_request(&self, request: &mut Request, _: &Data) {   &hellip; &hellip;}      fn on_response(&self, request: Request, response: mut Response)       {&hellip; &hellip;} } fn rocket() -> rocket::Rocket {     rocket::ignite()         .mount("/", routes![&hellip; , &hellip;])         .attach(Counter::default())            &hellip; &hellip; }

這是一個根據(jù)請求方法不同而分別計數(shù)功能,你也可以實現(xiàn)Counter的attach的事件處理;但跟filter不同,F(xiàn)airing更通用些。其特點如下:

  • 掛載在Request的生命周期

  • 不能終止或者直接響應(yīng)Request

  • 不能將非請求數(shù)據(jù)注入Request

  • 可以檢查或者修改配置

  • 只有attach了才能觸發(fā)

  • 順序很重要

Fairing可以應(yīng)用在一些動態(tài)改配置的場景,或者多種環(huán)境的復(fù)雜配置場景;且官方貼心的內(nèi)置了Adhoc實現(xiàn),方便開發(fā)人員快速實現(xiàn)。

至此,Rocket的特性就講完了,所以建議大家根據(jù)自己的實際需求,來選擇自己合適的框架。

壓測數(shù)據(jù)參考

最后我們給出之前做的壓測結(jié)果:

Rust Web框架有哪些

感謝各位的閱讀,以上就是“Rust Web框架有哪些”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Rust Web框架有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI