În timp ce limbajul Rust furnizează definiția de bază a trait-ului Future, el nu include un runtime asincron în biblioteca standard. În ecosistemul industrial, Tokio reprezintă standardul de aur de facto: un runtime asincron de nivel de producție, capabil să gestioneze milioane de conexiuni TCP concurente cu un consum minim de resurse.
Spre deosebire de un model 1:1 (unde fiecare conexiune consumă un thread fizic de sistem de operare de 1-8 MB), Tokio rulează un planificator multi-thread bazat pe furt de lucru (Work-Stealing Scheduler) peste un nucleu I/O non-blocant multiplexat cu epoll pe Linux sau kqueue pe macOS.
use tokio::sync::mpsc;
use tokio::time::{sleep, Duration};
use std::sync::Arc;
struct MesajComanda {
id: u64,
suma: f64,
}
#[tokio::main(flavor = "multi_thread", worker_threads = 4)]
async fn main() -> Result<(), Box> {
// 1. Canal MPSC limitat (Bounded Channel) pentru a asigura backpressure natural:
let (tx, mut rx) = mpsc::channel::(100);
// 2. Lansăm un lucrător în fundal (Worker Task):
let worker_handle = tokio::spawn(async move {
println!("Worker pornit pe thread pool-ul Tokio...");
while let Some(comanda) = rx.recv().await {
// Simulăm procesarea asincronă fără blocarea firului fizic:
sleep(Duration::from_millis(50)).await;
println!("Comanda {} ({} RON) a fost procesată cu succes.", comanda.id, comanda.suma);
}
println!("Canalul a fost închis; worker-ul se oprește curat.");
});
// 3. Producătorul trimite evenimente în canal:
for i in 1..=5 {
tx.send(MesajComanda { id: i, suma: 150.0 * (i as f64) }).await?;
}
// Închidem capătul transmițătorului pentru a semnaliza finalul fluxului:
drop(tx);
// Așteptăm finalizarea sarcinii de fundal:
worker_handle.await?;
Ok(())
}
Greșeala Fatală: Operațiuni Blocante pe Thread-uri Asincrone
Dacă apelați o funcție sincronă lentă (cum ar fi std::fs::read, std::thread::sleep sau un calcul masiv de criptografie CPU) direct într-o funcție async, blocați firul fizic din thread pool-ul Tokio. Alte zeci de mii de conexiuni mapate pe acel fir vor îngheța complet!
Soluția Corectă: tokio::task::spawn_blocking
// Delegarea calculelor grele CPU sau apelurilor sincrone către un thread pool dedicat de blocare:
let rezultat = tokio::task::spawn_blocking(|| {
// Aici este sigur să executăm operațiuni grele fără a afecta reactorul de rețea:
calculeaza_hash_sha256_fisier_mare("/var/data/arhiva.tar")
}).await?;
Multiplexare Avansată cu tokio::select! și Graceful Shutdown
use tokio::signal;
tokio::select! {
_ = server_web.start() => {
eprintln!("Serverul web s-a oprit neașteptat!");
}
_ = signal::ctrl_c() => {
println!("Semnal SIGINT recepționat! Se declanșează procedura de oprire sigură (Graceful Shutdown)...");
// Eliberăm conexiunile de baze de date și golim bufferele de rețea
}
}