成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Rust Web框架怎么選?研究本文就夠了!

開發 架構
Rust語言這兩年在“安全、并發、性能”方面吸足了眼球,但在主流的web應用領域表現如何?有哪些可以推薦的Web框架?下面就這個話題深入展開。

 Rust語言這兩年在“安全、并發、性能”方面吸足了眼球,但在主流的web應用領域表現如何?有哪些可以推薦的Web框架?下面就這個話題深入展開。

[[315977]]

背景

Web框架

我們先簡單回顧下Web框架: Web框架主要用于動態Web開發,開發人員在框架基礎上實現自己的業務邏輯。 Web框架需要實現接收到請求后,能夠提供參數校驗的能力,然后根據請求參數從底層拿到數據,最后以特定格式返回。Web框架旨在簡化web開發流程,讓開發人員更專注于自己的業務邏輯。

其他語言現狀

其他主流語言,Web框架都已經發展非常成熟,大家耳熟能詳的比如:

  • PHP語言: Laravel
  • JAVA語言:Spring MVC
  • GO語言: Gin/Beego

這些框架介紹的文章已經滿大街了,在此就不贅述。

Rust常見Web框架

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

Rust Web框架的難點

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

Rust Web框架分類

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

Rust主流Web框架的比較

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

Hyper

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

  • hyper應用側的功能相對少,所以會導致很多框架又在他的基礎上繼續封裝;
  • 通過match block實現路由,這個筆者認為是一個比較明顯的缺點; 比如下面的例子:

  1. async fn response_examples( 
  2.     req: Request<Body>,client: Client<HttpConnector> 
  3. ) -> Result<Response<Body>> { 
  4.     match (req.method(), req.uri().path()) { 
  5.         (&Method::GET, "/index.html") => { 
  6.             Ok(Response::new(INDEX.into())) 
  7.         }, 
  8.        (&Method::GET, "/json_api") => { 
  9.             api_get_response().await 
  10.         } 
  11.         _ => { 
  12.    Ok(Response::builder().status(StatusCode::NOT_FOUND) 
  13.                 .body(NOTFOUND.into()) 
  14.                 .unwrap()) 
  15.         } 
  16.     } 

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

Actix-web

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

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

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

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

 

 

 

 

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

Rocket

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

  • 類型安全;
  • 上手簡單,讓你更專注于自己的業務;
  • 組件豐富,且幾乎都可以自定義;

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

匯總

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

 

 

 

 

Rocket

Rocket設計原則

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

  • Security, correctness, and developer experience are paramount.
  • All request handling information should be typed and self-contained
  • Decisions should not be forced

筆者的理解:

  • 安全性,正確性和開發人員經驗至關重要。這就充分挖掘了rust安全方面的優勢,且對各語言開發人員友好, 后面講到request、guards這兩個組件再展開下;
  • 所有被處理請求信息都必須指定類型。這樣也對開發人員有所約束, 比如在使用Responder組件就深有感觸;
  • 不應該強行限制。他的模板、序列化、會話等組件,幾乎所有的功能都是可選擇的插件形式。對于這些,Rocket都有官方庫和支持,完全可以自由選擇和替換。 所以,Rocket是Rust Web框架里面,完美的平衡了自由和約束。下面我們就幾個重要組件詳細展開。

RequestGuards

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

 

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

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

Responder

我們直接看下Responder的定義:

 

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

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

 

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

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

  1. pub trait Responder { 
  2.     /// The associated error which can be returned. 
  3.     type Error: Into<Error>; 
  4.  
  5.     /// The future response value. 
  6.     type Future: Future<Output = Result<Response, Self::Error>>; 
  7.  
  8.     /// Convert itself to `AsyncResult` or `Error`. 
  9.     fn respond_to(self, req: &HttpRequest) -> Self::Future; 
  10.  
  11.  
  12.     fn with_status(self, status: StatusCode) -> CustomResponder<Self> 
  13.         where 
  14.             Self: Sized, 
  15.     { 
  16.         CustomResponder::new(self).with_status(status) 
  17.     } 
  18.  
  19.  
  20.     fn with_header<K, V>(self, key: K, value: V) -> CustomResponder<Self> 
  21.        … … 

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

State

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

  1. use rocket::State; 
  2. use rocket::response::content; 
  3.  
  4. struct HitCount(AtomicUsize); 
  5.  
  6. #[get("/")] 
  7. fn index(hit_count: State<HitCount>) -> content::Html<String> { 
  8.     hit_count.0.fetch_add(1, Ordering::Relaxed); 
  9.     let msg = "Your visit has been recorded!"
  10.     let count = format!("Visits: {}"count(hit_count)); 
  11.     content::Html(format!("{}<br /><br />{}", msg, count)) 
  12.  
  13. #[get("/count")] 
  14. fn count(hit_count: State<HitCount>) -> String { 
  15.     hit_count.0.load(Ordering::Relaxed).to_string() 
  16.  
  17. fn rocket() -> rocket::Rocket { 
  18.     rocket::ignite() 
  19.         .mount("/", routes![indexcount]) 
  20.         .manage(HitCount(AtomicUsize::new(0))) 

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

Fairing

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

 

  1. #[derive(Default)] 
  2. struct Counter { 
  3.     get: AtomicUsize, 
  4.     post: AtomicUsize, 
  5. impl Fairing for Counter { 
  6.  
  7.     fn on_request(&self, request: &mut Request, _: &Data) {   
  8. … …} 
  9.  
  10.     fn on_response(&self, request: Request, response: mut Response) 
  11.       {… …} 
  12. fn rocket() -> rocket::Rocket { 
  13.     rocket::ignite() 
  14.         .mount("/", routes![… , …]) 
  15.         .attach(Counter::default()) 
  16.            … … 

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

  • 掛載在Request的生命周期
  • 不能終止或者直接響應Request
  • 不能將非請求數據注入Request
  • 可以檢查或者修改配置
  • 只有attach了才能觸發
  • 順序很重要

Fairing可以應用在一些動態改配置的場景,或者多種環境的復雜配置場景;且官方貼心的內置了Adhoc實現,方便開發人員快速實現。

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

壓測數據參考

最后我們給出之前做的壓測結果:

 

 

 

 

上述表格中Rocket sync(master分支)并發只能到50,如果業務場景非常注重性能的話,那你就慎重考慮,或者你持續關注async分支的進展;另外比較了hyper框架debug和release方式的差異,其他的差異比例也類似。

參考資料:

  1. Hyper官網
  2. Rocket官網
  3. Actix-web官網
  4. rust Web框架的比較
  5. the-best-rust-frameworks-to-check-out-in-2019

Westar實驗室成立于2018年,是分層區塊鏈的先行者。團隊致力于創建下一代分層區塊鏈及金融基礎設施。通過先進技術和工程能力,構建產品和基礎網絡,從而減少對信任的依賴,提高金融市場的效率。對于區塊鏈生態,通過分層區塊鏈技術,在保證安全性的同時,保證處理速度,達到可以商用的目的。

責任編輯:武曉燕 來源: 高可用架構
相關推薦

2021-12-06 09:57:25

容器Linux信號

2020-12-11 08:04:01

腳本動態 Async

2023-12-07 08:35:22

2020-07-03 08:21:57

Java集合框架

2024-07-12 05:00:00

2009-06-18 09:29:44

Spring Web

2024-02-01 00:21:41

Rust編程框架

2024-10-18 11:48:00

2018-07-06 14:27:26

存儲

2020-10-23 07:43:37

Log配置性能

2022-03-13 09:31:43

MQ消息隊列ActiveMQ

2021-09-30 07:59:06

zookeeper一致性算法CAP

2019-08-16 09:41:56

UDP協議TCP

2025-02-14 08:53:24

2015-04-14 09:26:52

WebWeb應用程序框架

2024-02-04 09:08:00

Autofac容器.NET

2020-05-20 14:05:19

自動化測試框架軟件測試

2020-07-07 07:55:53

web app數據科學機器學習

2019-10-31 09:48:53

MySQL數據庫事務
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久草综合在线视频 | 久久久www成人免费精品 | 国产欧美一区二区三区日本久久久 | 毛片免费看| 亚洲午夜视频 | 狠狠夜夜| 精品国产一区二区三区性色av | 午夜精品一区二区三区在线观看 | 很黄很污的网站 | 欧美日韩在线免费观看 | 国产午夜精品久久 | 亚洲三级在线 | 99福利在线观看 | 中文精品视频 | 精精久久| 狠狠色综合网站久久久久久久 | 国产一区二区三区四区三区四 | 日韩a视频| 亚洲网站在线观看 | 国产精品国产成人国产三级 | 91久久国产综合久久 | 91热爆在线观看 | 国产精品久久久久国产a级 欧美日韩国产免费 | 日日天天| 狠狠入ady亚洲精品经典电影 | 香蕉婷婷 | 亚洲a视频 | 日韩在线欧美 | 精品国产91久久久久久 | 欧美日韩一 | 一区二区三区视频在线 | 中文字幕综合 | 亚洲高清av| 91久久精品日日躁夜夜躁欧美 | 久久91精品久久久久久9鸭 | 国产欧美精品 | 久久99久久99精品免视看婷婷 | 亚洲精品在线免费 | 久久精品91 | 一区二区三区四区在线视频 | 在线看一区二区 |