目录
- 三大框架概览
- Axum:Tower 生态现代框架
- Actix-web:Actor 模型高性能
- Rocket:声明式语法先行者
- 框架选型指南
- 认证与授权实现
- 数据库集成:SQLx 与 ORM
- 生产部署与性能优化
- 中间件生态对比
- 测试策略
- WebSocket 与 Server-Sent Events
- 部署与运维
1. 三大框架概览
| 特性 | Axum | Actix-web | Rocket |
|---|---|---|---|
| 维护方 | Tokio 团队(官方) | 社区(Actix) | 社区(Sergio Benitez) |
| 核心设计 | Tower Service 抽象 | Actor 模型 | 声明式宏 |
| 性能 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 学习曲线 | 中(需理解 Tower) | 低 | 低 |
| 中间件 | Tower layer | 自定义 guard/middleware | Fairing + Guard |
| 稳定版状态 | ✅ 1.0 | ✅ 4.x | ✅ 0.5 |
2. Axum:Tower 生态现代框架
Axum 基于 hyper HTTP 服务器和 tower 中间件抽象,是 Tokio 官方推荐的 Web 框架。
2.1 Hello World
use axum::{routing::get, Router};
use std::net::SocketAddr;
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(|| async { "Hello, Axum!" }));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
}
2.2 路由与提取器
use axum::{
routing::{get, post},
extract::{Path, Query, Json, State},
Router,
};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct Pagination {
page: Option<u32>,
per_page: Option<u32>,
}
#[derive(Serialize)]
struct User {
id: u64,
name: String,
}
async fn list_users(
Query(pagination): Query<Pagination>,
) -> Json<Vec<User>> {
let page = pagination.page.unwrap_or(1);
Json(vec![User { id: 1, name: "Alice".to_string() }])
}
async fn get_user(Path(id): Path<u64>) -> Json<User> {
Json(User { id, name: "Bob".to_string() })
}
async fn create_user(Json(user): Json<CreateUserReq>) -> Json<User> {
Json(User { id: 42, name: user.name })
}
let app = Router::new()
.route("/users", get(list_users).post(create_user))
.route("/users/:id", get(get_user));
2.3 状态管理与依赖注入
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Clone)]
struct AppState {
db: Arc<RwLock<Vec<User>>>,
config: Arc<Config>,
}
let state = AppState {
db: Arc::new(RwLock::new(vec![])),
config: Arc::new(Config::default()),
};
let app = Router::new()
.route("/users", get(list_users))
.with_state(state);
async fn list_users(State(state): State<AppState>) -> Json<Vec<User>> {
let users = state.db.read().await.clone();
Json(users)
}
2.4 中间件(Tower Layer)
use tower_http::{trace::TraceLayer, cors::CorsLayer, compression::CompressionLayer};
let app = Router::new()
.route("/", get(handler))
.layer(CorsLayer::permissive())
.layer(CompressionLayer::new())
.layer(TraceLayer::new_for_http());
自定义中间件:
async fn auth_middleware<B>(
req: Request<B>,
next: Next<B>,
) -> Result<Response, StatusCode> {
let auth = req.headers()
.get("authorization")
.and_then(|h| h.to_str().ok());
match auth {
Some(token) if valid_token(token) => Ok(next.run(req).await),
_ => Err(StatusCode::UNAUTHORIZED),
}
}
let app = Router::new()
.route("/protected", get(secret_handler))
.layer(middleware::from_fn(auth_middleware));
2.5 错误处理
use axum::{response::IntoResponse, http::StatusCode};
use thiserror::Error;
#[derive(Error, Debug)]
enum AppError {
#[error("database error")]
Database(#[from] sqlx::Error),
#[error("not found")]
NotFound,
#[error("validation error: {0}")]
Validation(String),
}
impl IntoResponse for AppError {
fn into_response(self) -> Response {
let (status, message) = match self {
AppError::Database(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal error"),
AppError::NotFound => (StatusCode::NOT_FOUND, "Not found"),
AppError::Validation(msg) => (StatusCode::BAD_REQUEST, msg.as_str()),
};
(status, Json(json!({ "error": message }))).into_response()
}
}
3. Actix-web:Actor 模型高性能
Actix-web 基于 Actix Actor 框架,以极致性能和丰富功能著称。
3.1 Hello World
use actix_web::{get, App, HttpServer, Responder};
#[get("/")]
async fn hello() -> impl Responder {
"Hello, Actix!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(hello))
.bind("127.0.0.1:3000")?
.run()
.await
}
3.2 路由与数据提取
use actix_web::{web, HttpResponse, Result};
use serde::Deserialize;
#[derive(Deserialize)]
struct Info {
user_id: u64,
friend: String,
}
#[get("/users/{user_id}/{friend}")]
async fn user_info(info: web::Path<Info>) -> Result<HttpResponse> {
Ok(HttpResponse::Ok().json(json!({
"user_id": info.user_id,
"friend": info.friend,
})))
}
// 应用程序状态
struct AppState {
app_name: String,
}
#[get("/app_name")]
async fn app_name(data: web::Data<AppState>) -> String {
data.app_name.clone()
}
HttpServer::new(|| {
App::new()
.app_data(web::Data::new(AppState { app_name: "MyApp".to_string() }))
.service(user_info)
.service(app_name)
})
3.3 中间件
use actix_web::middleware::{Logger, Compress, DefaultHeaders};
HttpServer::new(|| {
App::new()
.wrap(Logger::default()) // 请求日志
.wrap(Compress::default()) // 响应压缩
.wrap(DefaultHeaders::new().add(("X-Version", "1.0")))
.service(hello)
})
3.4 多线程工作器
HttpServer::new(|| { ... })
.workers(4) // 4 个工作线程
.bind("127.0.0.1:3000")?
.run()
4. Rocket:声明式语法先行者
Rocket 使用 Rust 的声明宏实现高度简洁的代码。
4.1 Hello World
#[macro_use] extern crate rocket;
#[get("/")]
fn hello() -> &'static str {
"Hello, Rocket!"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![hello])
}
4.2 路由与守卫
use rocket::serde::{Serialize, json::Json};
use rocket::request::{FromRequest, Outcome, Request};
#[derive(Serialize)]
struct User { id: u64, name: String }
#[get("/users/<id>")]
fn get_user(id: u64) -> Option<Json<User>> {
Some(Json(User { id, name: "Alice".to_string() }))
}
// 自定义守卫:API Key 验证
struct ApiKey<'r>(&'r str);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKey<'r> {
type Error = ();
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match req.headers().get_one("x-api-key") {
Some(key) => Outcome::Success(ApiKey(key)),
None => Outcome::Forward(Status::Unauthorized),
}
}
}
#[get("/admin")]
fn admin_panel(key: ApiKey<'_>) -> String {
format!("Admin access with key: {}", key.0)
}
4.3 数据验证
use rocket::serde::Deserialize;
use rocket_validation::{Validate, Validated};
#[derive(Deserialize, Validate)]
struct CreateUser {
#[validate(length(min = 1, max = 50))]
name: String,
#[validate(email)]
email: String,
}
#[post("/users", data = "<user>")]
fn create_user(user: Validated<Json<CreateUser>>) -> Json<User> {
Json(User { id: 1, name: user.name.clone() })
}
5. 框架选型指南
| 场景 | 推荐框架 | 理由 |
|---|---|---|
| 微服务/API 网关 | Axum | Tokio 官方支持,Tower 生态丰富,hyper 底层 |
| 极高吞吐量服务 | Actix-web | TechEmpower 基准测试常年前三 |
| 快速原型开发 | Rocket | 声明式语法最简洁,文档优秀 |
| 需要 WebSocket | Actix-web | 内置完善的 WebSocket 支持 |
| 与 gRPC 混部 | Axum | tonic (gRPC) 同为 Tower 生态 |
| 团队 Rust 新手多 | Rocket | 编译器错误信息最友好 |
6. 认证与授权实现
6.1 JWT 认证中间件(Axum)
use jsonwebtoken::{decode, DecodingKey, Validation, Algorithm};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
exp: usize,
roles: Vec<String>,
}
async fn jwt_middleware<B>(
mut req: Request<B>,
next: Next<B>,
) -> Result<Response, StatusCode> {
let token = req.headers()
.get("authorization")
.and_then(|h| h.to_str().ok())
.and_then(|h| h.strip_prefix("Bearer "));
let claims = token
.and_then(|t| decode::<Claims>(
t,
&DecodingKey::from_secret("secret".as_ref()),
&Validation::new(Algorithm::HS256),
).ok())
.map(|d| d.claims)
.ok_or(StatusCode::UNAUTHORIZED)?;
req.extensions_mut().insert(claims);
Ok(next.run(req).await)
}
6.2 OAuth2 集成
use oauth2::{AuthorizationCode, TokenResponse};
async fn oauth_callback(
Query(params): Query<OAuthCallback>,
) -> Result<Redirect, AppError> {
let token = oauth_client
.exchange_code(AuthorizationCode::new(params.code))
.request_async(async_http_client)
.await?;
let user = fetch_user_info(token.access_token().secret()).await?;
// 创建/更新用户,颁发 JWT
Ok(Redirect::to("/dashboard"))
}
7. 数据库集成:SQLx 与 ORM
7.1 SQLx(编译时检查 SQL)
use sqlx::{PgPool, query_as};
#[derive(sqlx::FromRow)]
struct User {
id: i64,
name: String,
email: String,
}
async fn get_user(pool: &PgPool, id: i64) -> Result<User, sqlx::Error> {
query_as::<_, User>("SELECT id, name, email FROM users WHERE id = $1")
.bind(id)
.fetch_one(pool)
.await
}
// 连接池初始化
let pool = PgPool::connect("postgres://user:pass@localhost/db").await?;
7.2 Sea-ORM(异步 ORM)
use sea_orm::{entity::*, query::*, Database};
// 自动生成 entity
db_user::Entity::find()
.filter(db_user::Column::Name.contains("Alice"))
.order_by_asc(db_user::Column::Id)
.all(&db)
.await?;
7.3 Diesel(同步 ORM + spawn_blocking)
use diesel::prelude::*;
let users = web::block(move || {
let mut conn = pool.get()?;
users::table.filter(users::name.eq("Alice")).load::<User>(&mut conn)
})
.await??;
| 方案 | 类型安全 | 编译时检查 | 异步原生 | 成熟度 |
|---|---|---|---|---|
| SQLx | ✅ | ✅ SQL | ✅ | ⭐⭐⭐⭐⭐ |
| Sea-ORM | ✅ | ✅ Schema | ✅ | ⭐⭐⭐⭐ |
| Diesel | ✅ | ✅ Schema | ❌(需 blocking) | ⭐⭐⭐⭐⭐ |
8. 生产部署与性能优化
8.1 健康检查与指标
use axum::{Router, routing::get};
let app = Router::new()
.route("/health", get(|| async { "OK" }))
.route("/metrics", get(metrics_handler));
8.2 优雅关闭
async fn graceful_shutdown(handle: axum::ServerHandle) {
let ctrl_c = tokio::signal::ctrl_c();
let terminate = std::future::pending();
tokio::select! {
_ = ctrl_c => {},
_ = terminate => {},
}
println!("Shutdown signal received");
handle.graceful_shutdown(Some(Duration::from_secs(30)));
}
8.3 Docker 多阶段构建
FROM rust:1.80-slim AS builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM gcr.io/distroless/cc-debian12
COPY --from=builder /app/target/release/myapp /usr/local/bin/
EXPOSE 3000
CMD ["myapp"]
8.4 性能基准
# TechEmpower 单查询基准(每秒请求数)
# Actix-web: ~700K req/s
# Axum: ~650K req/s
# Rocket: ~400K req/s
# 对比 Go Gin: ~500K req/s
# 对比 Node.js Express: ~50K req/s
# 使用 wrk 自测
wrk -t12 -c400 -d30s http://localhost:3000/
9. 中间件生态对比
常用中间件
| 功能 | Axum (tower-http) | Actix-web | Rocket |
|---|---|---|---|
| CORS | ✅ CorsLayer | ✅ Cors | ✅ CORS Fairing |
| 压缩 | ✅ CompressionLayer | ✅ Compress | ✅ Compression |
| 限流 | ✅ RateLimitLayer | 需自定义 | 需自定义 |
| 追踪 | ✅ TraceLayer | Logger | AdHoc |
| 超时 | ✅ TimeoutLayer | 需自定义 | 需自定义 |
| 静态文件 | ✅ ServeDir | Files | FileServer |
自定义限流中间件(Axum)
use std::sync::Arc;
use tokio::sync::Mutex;
use tower::{Layer, Service};
use std::collections::HashMap;
use std::time::{Duration, Instant};
#[derive(Clone)]
struct RateLimiter {
requests: Arc<Mutex<HashMap<String, Vec<Instant>>>>,
max_requests: usize,
window: Duration,
}
impl RateLimiter {
async fn is_allowed(&self, key: &str) -> bool {
let mut requests = self.requests.lock().await;
let now = Instant::now();
let window_start = now - self.window;
let timestamps = requests.entry(key.to_string()).or_default();
timestamps.retain(|&t| t > window_start);
if timestamps.len() >= self.max_requests {
false
} else {
timestamps.push(now);
true
}
}
}
// 应用到路由
let app = Router::new()
.route("/api/", post(api_handler))
.layer(middleware::from_fn_with_state(
rate_limiter,
rate_limit_middleware,
));
10. 测试策略
集成测试
use axum::body::Body;
use axum::http::{Request, StatusCode};
use tower::ServiceExt;
#[tokio::test]
async fn test_create_user() {
let app = create_app().await;
let response = app
.oneshot(
Request::builder()
.method("POST")
.uri("/users")
.header("Content-Type", "application/json")
.body(Body::from(r#"{"name":"Alice","email":"alice@example.com"}"#))
.unwrap(),
)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::CREATED);
}
使用 sqlx::test 进行数据库测试
#[sqlx::test]
async fn test_user_repository(pool: PgPool) {
let repo = UserRepository::new(pool);
let user = repo.create("Alice", "alice@example.com").await.unwrap();
assert_eq!(user.name, "Alice");
let found = repo.find_by_id(user.id).await.unwrap();
assert!(found.is_some());
}
总结
Rust Web 框架在 HTTP 吞吐量上已达到甚至超越 Go 和 Java 的水平,同时提供编译期内存安全保证。Axum 的 Tower 生态、Actix-web 的极致性能、Rocket 的开发体验,三者覆盖不同场景,选型建议从团队熟悉度和具体需求出发。
| 优先级 | 选型建议 |
|---|---|
| 与现有 Tokio 生态整合 | → Axum |
| 极致性能 + 成熟度高 | → Actix-web |
| 快速开发 + 团队 Rust 新手多 | → Rocket |
| 需要 WebSocket + Actor 模式 | → Actix-web |
| 微服务网关 + gRPC 混部 | → Axum |
11. WebSocket 与 Server-Sent Events
实时通信是现代 Web 应用的基础设施。
WebSocket(Actix-web)
use actix_web::{web, HttpRequest, HttpResponse, Error};
use actix_web_actors::ws;
struct MyWebSocket;
impl Actor for MyWebSocket {
type Context = ws::WebsocketContext<Self>;
}
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWebSocket {
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
match msg {
Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
Ok(ws::Message::Text(text)) => ctx.text(text),
_ => (),
}
}
}
async fn websocket_handler(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
let resp = ws::start(MyWebSocket {}, &req, stream)?;
Ok(resp)
}
SSE(Axum)
use axum::{response::sse::Event, response::Sse};
use tokio_stream::wrappers::IntervalStream;
use std::time::Duration;
async fn sse_handler() -> Sse<impl Stream<Item = Result<Event, Infallible>>> {
let stream = IntervalStream::new(tokio::time::interval(Duration::from_secs(1)))
.map(|_| Ok(Event::default().data("heartbeat")));
Sse::new(stream)
}
实时通信选型
| 协议 | 方向 | 适用场景 |
|---|---|---|
| WebSocket | 双向 | 聊天、在线游戏、协同编辑 |
| SSE | 服务端→客户端 | 实时通知、股票价格、日志流 |
| Long Polling | 请求-响应 | 简单实时场景,兼容旧浏览器 |
12. 部署与运维
Docker 多阶段构建(Actix-web 示例)
FROM rust:1.80-slim AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo 'fn main() {}' > src/main.rs
RUN cargo build --release && rm -rf src
COPY . .
RUN cargo build --release
FROM gcr.io/distroless/cc
COPY --from=builder /app/target/release/myapp /usr/local/bin/app
EXPOSE 8080
CMD ["app"]
健康检查端点
async fn health_check() -> impl IntoResponse {
(StatusCode::OK, Json(json!({"status": "healthy"})))
}
优雅关闭
use tokio::signal;
async fn shutdown_signal() {
let ctrl_c = async { signal::ctrl_c().await.unwrap(); };
let terminate = async {
signal::unix::signal(signal::unix::SignalKind::terminate())
.unwrap().recv().await;
};
tokio::select! {
_ = ctrl_c => {},
_ = terminate => {},
}
}
性能调优实践
Rust Web 框架的高性能需要合理的配置才能充分发挥:
| 优化项 | 建议值 | 效果 |
|---|---|---|
| 工作线程数 | num_cpus() 或略多 | 匹配 CPU 核心数 |
| 连接超时 | 30-60s | 避免连接泄漏 |
| Keep-Alive | 启用 | 减少 TCP 握手开销 |
| 响应压缩 | CompressionLayer | 减少传输体积 |
| 连接池(数据库) | 10-50 | 避免过多连接压垮数据库 |
压测对比
使用 wrk 或 oha 对本地服务压测:
# wrk:12 线程,400 并发,30 秒
wrk -t12 -c400 -d30s http://localhost:3000/
# oha(Rust 编写,支持 HTTP/2)
oha -n 1000000 -c 1000 http://localhost:3000/
典型结果(单机):
- Actix-web: 600K-700K req/s(JSON 序列化)
- Axum: 500K-600K req/s
- Rocket: 300K-400K req/s
Rust Web 生态正在快速发展,三大框架各有优势,选型时应综合考虑团队技术储备、性能要求和生态整合需求。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。