Näin kopioit nettisivun otsikon helposti
Rust + Actix-web: APIs jotka todella skaalautuvat
Olen vuosien varrella rakentanut kymmeniä REST-rajapintoja. Node.js, Python, Go — kaikki ovat tuttuja. Mutta viime aikoina olen viettänyt yhä enemmän aikaa Rustin parissa, ja tulokset ovat pakottaneet minut kyseenalaistamaan vanhat totuudet.
Oppimiskäyrä on todellinen — ja se kannattaa
En voi valehdella: Rust ei ole helppo. Borrow checker on armottoman tarkka. Ensimmäiset viikot tulevat menemään lifetime-virheiden selvittämiseen sen sijaan, että rakentaisit mitään hyödyllistä.
Mutta yksi asia muutti ajattelutapani. Rust ei pakota sinua valitsemaan turvallisuuden ja nopeuden välillä. Saat molemmat.
Kun API toimii tuotannossa tuhansia pyyntöjä sekunnissa, jokainen yllätys on ongelma. Null-pointer-poikkeukset, datakilpailutilanteet, roskankeruun aiheuttamat piikit — näitä ei yksinkertaisesti tapahdu Rustilla. P99-latenssit pysyvät ennustettavina, koska ei ole mitään taustalla tapahtuvaa "maagista" prosessia, joka voisi yllättää.
Tämä on erityisen merkityksellistä, kun rakennat palveluita, jotka skaalautuvat. Pienellä tiimillä et halua sitoa resursseja monimutkaisten turvamekanismien hallintaan.
Actix-web: Tutun tuntuinen mutta erilainen
Actix-web nojaa samaan ajatteluun kuin Elixir/Phoenix, vaikka yhteyttä virallisesti ei olekaan. Actor-malli ja ergonominen API tekevät siitä helposti lähestyttävän, jos olet käyttänyt Expressiä tai Fastifya.
Aloitetaan.
Projektin pystyttäminen
cargo new rust-api-demo
cd rust-api-demo
cargo add actix-web actix-rt
Ensimmäinen endpoint
use actix_web::{web, App, HttpServer, HttpResponse};
async fn health_check() -> HttpResponse {
HttpResponse::Ok().json(serde_json::json!({
"status": "healthy",
"version": env!("CARGO_PKG_VERSION")
}))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/health", web::get().to(health_check))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Käännösaika on millisekunneissa. Käynnistys mikrosekunneissa. Ajetaan cargo run ja avataan selaimessa localhost:8080/health. Vastaus tulee välittömästi.
Käytännön API: Todo-listaus CRUD-operaatioilla
Terveysendpoints on hyvä alku, mutta rakennetaan jotain oikeaa.
Tietomalli
use serde::{Deserialize, Serialize};
use std::sync::Mutex;
use std::cell::Cell;
#[derive(Clone, Serialize, Deserialize)]
struct Todo {
id: u64,
title: String,
completed: bool,
}
Tässä kohtaa moni Node.js-taustan kehittäjä huomaa jotain: meillä ei ole erillistä validointikirjastoa, ei ulkoisia riippuvuuksia tietorakenteille. serde hoitaa sarjallistamisen suoraan struct-määrityksestä.
Lopullinen toteutus
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use std::sync::Mutex;
#[derive(Clone, Serialize, Deserialize)]
struct Todo {
id: u64,
title: String,
completed: bool,
}
struct AppState {
todos: Mutex<Vec<Todo>>,
}
async fn get_todos(data: web::Data<AppState>) -> impl Responder {
let todos = data.todos.lock().unwrap();
HttpResponse::Ok().json(&*todos)
}
async fn create_todo(
data: web::Data<AppState>,
body: web::Json<Todo>,
) -> impl Responder {
let mut todos = data.todos.lock().unwrap();
let new_id = todos.len() as u64 + 1;
let todo = Todo {
id: new_id,
title: body.title.clone(),
completed: body.completed,
};
todos.push(todo);
HttpResponse::Created().json(todo)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let state = web::Data::new(AppState {
todos: Mutex::new(Vec::new()),
});
HttpServer::new(move || {
App::new()
.app_data(state.clone())
.route("/todos", web::get().to(get_todos))
.route("/todos", web::post().to(create_todo))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Mitä tästä opimme
Tämä on tietysti yksinkertainen esimerkki. Mutta se havainnollistaa jotain oleellista: Rust + Actix-web yhdistelmä tuottaa koodia, joka on sekä turvallista että nopeaa. Kompromissit ovat minimaalisia, kunhan olet valmis näkemään vaivaa alussa.
Jos rakennat jotain, jossa suorituskyky ja luotettavuus ovat kriittisiä — oli kyse sitten mikropalveluista, API-gatewaystä tai reaaliaikaisista järjestelmistä — kannattaa kokeilla. Rust ei korvaa kaikkea, mutta se täydentää työkalupakkia tavalla, jota on vaikea sivuuttaa.