Rust Web 框架实战:Axum、Actix-web 与 Rocket 深度对比

Rust Web 框架全面评测:Axum(Tower 生态)、Actix-web(Actor 模型)、Rocket(声明式路由)的核心差异、中间件机制、状态管理、认证授权与数据库集成,附完整 CRUD 示例与选型指南。

目录

  1. 三大框架概览
  2. Axum:Tower 生态现代框架
  3. Actix-web:Actor 模型高性能
  4. Rocket:声明式语法先行者
  5. 框架选型指南
  6. 认证与授权实现
  7. 数据库集成:SQLx 与 ORM
  8. 生产部署与性能优化

1. 三大框架概览

特性AxumActix-webRocket
维护方Tokio 团队(官方)社区(Actix)社区(Sergio Benitez)
核心设计Tower Service 抽象Actor 模型声明式宏
性能⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
学习曲线中(需理解 Tower)
中间件Tower layer自定义 guard/middlewareFairing + 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 网关AxumTokio 官方支持,Tower 生态丰富,hyper 底层
极高吞吐量服务Actix-webTechEmpower 基准测试常年前三
快速原型开发Rocket声明式语法最简洁,文档优秀
需要 WebSocketActix-web内置完善的 WebSocket 支持
与 gRPC 混部Axumtonic (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/

Rust Web 框架在 HTTP 吞吐量上已达到甚至超越 Go 和 Java 的水平,同时提供编译期内存安全保证。Axum 的 Tower 生态、Actix-web 的极致性能、Rocket 的开发体验,三者覆盖不同场景,选型建议从团队熟悉度和具体需求出发。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「rust」更多文章