ActixMiddleTechnical
В чём разница между Actix-web и Axum по архитектуре, производительности и удобству использования?
Actix-web использует собственные трейты Transform/Service и показывает максимальный RPS в бенчмарках; Axum построен на Tower и официально поддерживается командой tokio, обеспечивая богатую экосистему middleware. На практике производительность сопоставима, выбор определяется архитектурными предпочтениями.
Actix-web vs Axum: сравнение архитектур
Оба фреймворка — топ-2 в экосистеме Rust для HTTP-серверов. Они используют tokio в качестве async runtime, поддерживают middleware, extractors и Tower-совместимый стек (Axum нативно, Actix-web через tower-http). Выбор между ними — вопрос архитектурных компромиссов.
Архитектурные различия
Actix-web
- Собственная система middleware через трейты
TransformиService - Extractors через трейт
FromRequest(не связан с Tower) - Маршрутизация через App + route() / resource() / scope()
- Работает поверх tokio, но со своим event-loop воркером
- Более «батарейный» набор из коробки: сессии, мультипарт, WebSocket через actix-web-actors
Axum
- Построен на Tower — middleware через
tower::Layer, совместимые с экосистемой Tower целиком - Extractors через трейт
FromRequest/FromRequestParts(схоже с Actix, но другой трейт) - Маршрутизация через
Routerс явными вложениями (.nest(),.merge()) - Zero-cost abstractions — компиляция в монолитный тип; ошибки типов при неправильном стеке
- Официально поддерживается командой tokio
Сравнение кода: простой хендлер
// Actix-web
use actix_web::{web, HttpResponse};
use serde::Serialize;
#[derive(Serialize)]
struct Item { id: u32, name: String }
async fn get_item(path: web::Path<u32>) -> HttpResponse {
HttpResponse::Ok().json(Item { id: *path, name: "Widget".into() })
}
// App::new().route("/items/{id}", web::get().to(get_item))
// Axum
use axum::{extract::Path, Json};
use serde::Serialize;
#[derive(Serialize)]
struct Item { id: u32, name: String }
async fn get_item(Path(id): Path<u32>) -> Json<Item> {
Json(Item { id, name: "Widget".into() })
}
// Router::new().route("/items/:id", get(get_item))
Сравнение middleware
// Actix-web: собственный Transform трейт (многословно)
// wrap(Logger::default()) для стандартного логирования
// Axum: Tower middleware — лаконично
use tower_http::trace::TraceLayer;
use tower_http::cors::CorsLayer;
let app = Router::new()
.route("/", get(handler))
.layer(TraceLayer::new_for_http())
.layer(CorsLayer::permissive());
Производительность
По бенчмаркам TechEmpower (round 22, plaintext):
- Actix-web: ~700k–800k RPS (один из лидеров среди всех фреймворков)
- Axum: ~500k–650k RPS (немного ниже, но разница нивелируется реальным IO)
На практике разница в производительности несущественна — bottleneck почти всегда в базе данных или сети.
Удобство использования
- Ошибки компиляции: Axum генерирует длинные сообщения о несовместимых типах в стеке; Actix-web — более читаемые ошибки в большинстве случаев
- Экосистема: Axum использует tower-http (CORS, tracing, compression, auth) — богатый набор готовых слоёв
- Интеграция с tokio: Axum разработан той же командой, что и tokio; глубже интегрирован
- WebSocket: Actix-web через actix-web-actors; Axum через axum::extract::ws
Когда выбирать Actix-web
- Проект уже использует Actix
- Нужны актив-акторы для WebSocket-чатов
- Максимальная производительность в тестах важна маркетингово
Когда выбирать Axum
- Новый проект с нуля
- Нужна совместимость с Tower middleware (tower-http, tower-sessions и т.д.)
- Команда ценит типобезопасность и тесную интеграцию с tokio
Подводные камни
- Axum ошибки типов — неправильный порядок extractors или несовместимый State приводит к эссе на несколько экранов от компилятора.
- Actix Transform — сложный API — написание custom middleware в Actix verbose и требует понимания Rc/Service/Transform.
- Миграция между фреймворками — несмотря на похожий API, код не переносится без переписывания; выбирайте заранее осознанно.
- actix-web-actors deprecated direction — команда Actix не развивает акторную модель активно; для WebSocket в новых проектах Axum может быть предпочтительнее.
- Версионирование tower-http — Axum жёстко привязан к конкретной версии Tower; несовместимость версий в transitive зависимостях — частая проблема.
Common mistakes
- Отвечать определением без production-сценария.
- Не называть runtime boundary, security boundary или failure mode.
- Игнорировать версию API, observability и тестовую проверку.
What the interviewer is testing
- Объясняет механизм своими словами и без выдуманных API.
- Называет реальные риски, диагностику и критерий корректности.
- Связывает ответ с текущей документацией и миграционными ограничениями.