hyperlane
是一個高性能且輕量級的 Rust HTTP 框架,設計目標是簡化現代 Web 服務的開發,同時兼顧靈活性和性能表現。本文將詳細介紹 hyperlane
框架的核心功能、API 設計、生命周期模型、路由支持及性能測試結果,幫助開發者快速掌握和應用該框架。
1. ctx 的額外封裝與簡化調用
在 hyperlane
中,Context
(簡稱 ctx
)封裝了請求和響應的各種信息。框架對 ctx
進行了擴展,使得調用請求和響應的子字段方法更加簡潔。
例如,request
結構體原有方法 get_method()
,傳統調用方式是:
let method = ctx.get_request().await.get_method();
hyperlane
允許直接調用簡化后的接口:
let method = ctx.get_request_method().await;
調用規則:
- 原
get
方法名后加子字段名稱(小寫,用下劃線分隔),例如get_method
->get_request_method
。 - 原
set
方法名后同樣加子字段名稱,例如set_status_code
->set_response_status_code
。
此設計極大提升了代碼的簡潔性與可讀性。
2. 請求方法宏(HTTP Methods)
hyperlane
提供了多種請求方法宏,用于路由函數標記允許的 HTTP 方法:
- 支持組合多個方法,使用
#[methods(get, post)]
。 - 支持單一方法簡寫,如
#[get]
、#[post]
等。 - 默認無宏時,路由允許所有請求方法訪問。
示例:
#[methods(get, post)]
async fn root_route(ctx: Context) {ctx.set_response_status_code(200).await;ctx.set_response_body("Hello hyperlane => /").await;
}#[get]
async fn ws_route(ctx: Context) {let key: String = ctx.get_request_header(SEC_WEBSOCKET_KEY).await.unwrap();let request_body: Vec<u8> = ctx.get_request_body().await;ctx.set_response_body(key).await.send_body().await;ctx.set_response_body(request_body).await.send_body().await;
}
3. 響應相關 API
獲取響應信息
-
獲取完整響應:
let response: Response = ctx.get_response().await;
-
獲取響應版本:
let version: ResponseVersion = ctx.get_response_version().await;
-
獲取響應狀態碼:
let status_code: ResponseStatusCode = ctx.get_response_status_code().await;
-
獲取響應原因短語:
let reason_phrase: ResponseReasonPhrase = ctx.get_response_reason_phrase().await;
-
獲取響應頭及單個響應頭:
let headers: ResponseHeaders = ctx.get_response_headers().await; let value: ResponseHeadersValue = ctx.get_response_header("key").await;
-
獲取響應體(支持二進制、字符串、JSON 反序列化):
let body: ResponseBody = ctx.get_response_body().await; let body_string: String = ctx.get_response_body_string().await; let body_json: T = ctx.get_response_body_json::<T>().await;
設置響應
-
設置響應體:
ctx.set_response_body(vec![]).await;
-
設置響應頭(響應頭 key 不區分大小寫,和請求頭不同):
ctx.set_response_header("server", "hyperlane").await;
-
設置狀態碼:
ctx.set_response_status_code(200).await;
發送響應
-
發送完整 HTTP 響應:
send()
發送響應后保持 TCP 連接。send_once()
發送響應后立即關閉 TCP 連接。
let res = ctx.set_response_body("hello").send().await; let res = ctx.set_response_body("hello").send_once().await;
-
發送響應體(支持多次發送):
let res = ctx.set_response_body("chunk").send_body().await; let res = ctx.set_response_body("chunk").send_once_body().await;
4. 中間件洋蔥模型
hyperlane
的請求處理采用洋蔥模型(Onion Model)中間件設計:
中間件層層嵌套,保證請求與響應處理順序清晰,方便擴展和功能解耦。
5. 生命周期演進(版本區別)
-
v3.0.0
以下版本- 先執行同步路由。
-
v3.0.0
到<v4.0.0
- 先執行異步中間件(保證注冊順序)
- 再執行同步路由(如果有同步路由則異步路由不執行)
- 最后執行異步路由
-
v4.0.0
及以上- 先執行所有異步中間件(按注冊順序)
- 再執行所有異步路由(按注冊順序)
-
v4.22.0
及以上- 先處理所有異步請求中間件
- 再執行異步路由
- 最后處理所有異步響應中間件
-
v4.89.0
及以上- 支持調用
ctx.aborted()
來中止后續流程,控制請求生命周期。
- 支持調用
-
v5.25.1
及以上- 支持調用
ctx.closed()
來停止后續響應發送,結束當前請求 TCP 連接。
- 支持調用
6. WebSocket 生命周期
7. 路由支持
靜態路由
- 框架支持靜態路由,重復注冊相同路徑時會拋出異常并退出。
server.route("/test", |ctx: Context| {}).await;
動態路由
- 使用
{}
包裹參數支持動態路由 - 支持正則表達式匹配
樸素動態路由
server.route("/test/{text}", |ctx: Context| {}).await;
正則表達式動態路由
server.route("/test/{number:\\d+}", |ctx: Context| {}).await;
獲取動態路由參數
let params = ctx.get_route_params().await;
let text: String = ctx.get_route_param("text").await;
8. 性能壓測結果
wrk 工具壓測
命令:
wrk -c360 -d60s http://127.0.0.1:60000/
QPS(請求每秒)結果:
排名 | 框架/運行時 | QPS |
---|---|---|
1 | Tokio | 340130.92 |
2 | Hyperlane | 324323.71 |
3 | Rocket | 298945.31 |
4 | Rust stdlib | 291218.96 |
5 | Gin | 242570.16 |
6 | Go stdlib | 234178.93 |
7 | Node stdlib | 139412.13 |
ab 工具壓測
命令:
ab -n 1000000 -c 1000 -r -k http://127.0.0.1:60000/
QPS 結果:
排名 | 框架/運行時 | QPS |
---|---|---|
1 | Tokio | 308596.26 |
2 | Hyperlane | 307568.90 |
3 | Rocket | 267931.52 |
4 | Rust stdlib | 260514.56 |
5 | Go stdlib | 226550.34 |
6 | Gin | 224296.16 |
7 | Node stdlib | 85357.18 |
hyperlane
在高并發下表現優異,接近 Tokio 的底層性能,明顯優于多數其他框架。
總結
hyperlane
以其靈活的 ctx
調用封裝、豐富的請求方法宏、完善的響應接口、多版本生命周期支持及強大的路由能力,為 Rust Web 開發提供了現代化且高性能的解決方案。結合其業界領先的性能表現,是構建高效、可擴展 HTTP 服務的理想框架。