Почему Rust для бэкенда
Rust — язык, гарантирующий безопасность памяти без сборщика мусора. Для бэкенда это значит:
Actix Web
▸Основы
1use actix_web::{web, App, HttpServer, HttpResponse};23async fn hello() -> HttpResponse {4 HttpResponse::Ok().body("Hello, world!")5}67#[actix_web::main]8async fn main() -> std::io::Result<()> {9 HttpServer::new(|| {10 App::new()11 .route("/", web::get().to(hello))12 })13 .bind("127.0.0.1:8080")?14 .run()15 .await16}
▸Маршруты и handlers
1use actix_web::{web, HttpResponse, Responder};2use serde::{Deserialize, Serialize};34#[derive(Serialize, Deserialize)]5struct User {6 id: u32,7 name: String,8 email: String,9}1011async fn get_user(path: web::Path<u32>) -> impl Responder {12 let id = path.into_inner();13 HttpResponse::Ok().json(User {14 id,15 name: "Alice".to_string(),16 email: "alice@example.com".to_string(),17 })18}1920async fn create_user(user: web::Json<User>) -> impl Responder {21 HttpResponse::Created().json(user.into_inner())22}2324// Настройка маршрутов25fn config(cfg: &mut web::ServiceConfig) {26 cfg.service(27 web::scope("/api/users")28 .route("/{id}", web::get().to(get_user))29 .route("", web::post().to(create_user))30 );31}
▸Middleware
1use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform};2use actix_web::Error;3use futures::future::{ok, Ready};45pub struct Logger;67impl<S, B> Transform<S, ServiceRequest> for Logger8where9 S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,10 S::Future: 'static,11 B: 'static,12{13 type Response = ServiceResponse<B>;14 type Error = Error;15 type InitError = ();16 type Transform = LoggerMiddleware<S>;17 type Future = Ready<Result<Self::Transform, Self::InitError>>;1819 fn new_transform(&self, service: S) -> Self::Future {20 ok(LoggerMiddleware { service })21 }22}
Axum
▸Основы
1use axum::{2 routing::{get, post},3 Router, Json, Path,4};5use serde::{Deserialize, Serialize};67async fn hello() -> &'static str {8 "Hello, world!"9}1011#[tokio::main]12async fn main() {13 let app = Router::new()14 .route("/", get(hello))15 .route("/users/{id}", get(get_user))16 .route("/users", post(create_user));1718 let listener = tokio::net::TcpListener::bind("127.0.0.1:8080")19 .await20 .unwrap();21 axum::serve(listener, app).await.unwrap();22}
▸Extractors
1use axum::extract::{Path, Query, State};2use serde::Deserialize;34#[derive(Deserialize)]5struct ListParams {6 page: Option<u32>,7 per_page: Option<u32>,8}910async fn list_users(11 Query(params): Query<ListParams>,12 State(db): State<DbPool>,13) -> Json<Vec<User>> {14 // Использование параметров15 Json(vec![])16}1718// State для общих ресурсов19let app = Router::new()20 .route("/users", get(list_users))21 .with_state(db_pool);
▸Middleware
1use axum::middleware::{self, Next};2use axum::extract::Request;34async fn logging_middleware(5 request: Request,6 next: Next,7) -> impl axum::response::IntoResponse {8 let start = std::time::Instant::now();9 let response = next.run(request).await;10 let duration = start.elapsed();11 tracing::info!("Request completed in {:?}", duration);12 response13}1415let app = Router::new()16 .route("/", get(handler))17 .layer(middleware::from_fn(logging_middleware));
Сравнение
▸Производительность
▸Экосистема
▸Типобезопасность
▸Простота использования
Когда что использовать
▸Actix Web
▸Axum
Заключение
Actix Web и Axum — оба отличные выбор для Rust-бэкенда. Actix проверен временем и быстрее, Axum проще и лучше интегрируется с современным tokio. На собеседовании важно понимать архитектуру обоих фреймворков и когда какой выбрать.