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 服务的理想框架。