从 Actix-web 到 Salvo:Rust Web 开发体验对比
作为一名 Rust Web 服务开发者,选择框架往往比写业务逻辑更耗时。本文将对比 Actix-web 与 Salvo 两个框架在开发体验、性能及维护成本上的差异。
一、开发体验
1. 路由定义
Actix-web 的路由定义较为繁琐,需嵌套 Scope 和 Resource。Salvo 采用链式调用,结构更清晰。
// Actix-web 示例
App::new()
.service(web::scope("/users")
.route("", web::get().to(list_users))
.route("/{id}", web::get().to(get_user)))
// Salvo 示例
let user_router = Router::new()
.get("/list", list_users)
.get("/{id}", get_user)
.post("/create", create_user);
2. 语法糖与代码量
Salvo 提供了更简洁的语法糖,减少样板代码。
#[handler]
async fn register(req: Json<RegisterRequest>) -> Result<Json<User>, StatusCode> {
let user = User::create(req.name, req.email, req.password.hash());
let token = Jwt::generate(&user.id);
Ok(Json(user).with_header("Authorization", token))
}
3. 请求参数提取
使用 #[derive(Extractible)] 自动解析请求参数,支持编译期类型校验。
#[derive(Extractible)]
struct CreateUserRequest {
#[extract(source = "body")]
username: String,
#[extract(source = "query")]
role: Option<String>,
#[extract(source = "header")]
token: String,
}
#[handler]
async fn create_user(req: CreateUserRequest) -> Json<User> {
let user = User::new(req.username, req.role.unwrap_or_default());
Json(user_repository.save(user))
}
二、性能表现
1. 压测数据
使用 wrk 进行压力测试:
- Salvo:QPS 12.5 万,内存 8.2MB,延迟 0.8ms
- Actix-web:QPS 9.8 万,内存 15.6MB,延迟 1.2ms
Salvo 在高并发下内存占用更低,且支持流式处理大文件,避免 OOM。
2. 编译速度
Salvo 编译速度更快,50 个接口的项目仅需 30 秒,而 Actix-web 约需 45 秒。
3. 生产级指标对比
| 指标 | Actix-web | Salvo | 提升幅度 |
|---|---|---|---|
| 接口开发速度 | 3 人日/接口 | 0.8 人日/接口 | 75%↓ |
| 平均响应时间 | 250ms | 85ms | 66%↓ |
| 内存占用 | 1.2GB/实例 | 380MB/实例 | 68%↓ |
| 错误率 | 0.15% | 0.02% | 87%↓ |
三、维护与扩展
1. 依赖管理
Actix-web 依赖较多(actix-web, actix-rt, actix-files 等),版本冲突风险高。Salvo 核心依赖少(salvo, tokio, hyper),升级更平滑。
2. 中间件配置
Salvo 使用 .hoop() 添加中间件,顺序灵活,不易出错。
let router = Router::new()
.hoop(Logger::new())
.hoop(AuthMiddleware)
.get("/", hello);
3. 数据库集成
Salvo 通过扩展直接注入数据库连接,简化异步查询操作。
#[handler]
async fn list_users(conn: DieselHandler<DbConnection>) -> Json<Vec<User>> {
users::table.load(&conn.0).unwrap()
}
四、其他特性
1. 智能提示与工具链
VSCode 对 Salvo 支持良好,提供代码补全。支持自动生成 CRUD 接口。
# 生成 CRUD 接口
salvo generate crud User --fields "id:u64 name:String email:String"
2. WebSocket 支持
零配置实现 WebSocket,代码简洁。
#[handler]
async fn chat_ws(req: &mut Request, res: &mut Response) {
WebSocketUpgrade::new()
.on_upgrade(|ws| handle_socket(ws))
.upgrade(req, res)
.await
}
五、选型建议
| 场景 | 推荐框架 | 理由 |
|---|---|---|
| 新手入门/快速原型 | Salvo | 文档友好,上手快 |
| 中小型项目 | Salvo | 维护成本低,代码量少 |
| 高并发 API 网关 | Actix-web | 专为高并发设计 |
| 资源受限环境 | Salvo | 内存占用少 |
六、总结
框架的选择应基于实际需求。Salvo 凭借极简语法和高效架构,显著提升了开发效率;Actix-web 则在极致性能场景下仍有优势。建议根据团队规模与项目复杂度权衡选择。

