💻 Exemplos: Capítulo 18: Programação Assíncrona com Runtime Tokio e Async/Await
💻 Exemplos: Capítulo 18: Programação Assíncrona com Runtime Tokio
Especialização em Sistemas com Rust • Demonstrações Práticas Compiláveis
🎯 Objetivo dos Exemplos
Apresentar a programação assíncrona orientada a eventos no Rust de alta performance: o modelo de Future baseado em polling, configuração do runtime multithread com #[tokio::main], despacho de tarefas não-bloqueantes com tokio::spawn, canais assíncronos de alta vazão e multiplexação com a macro tokio::select!.
1. Manifesto Cargo.toml com Dependências do Tokio
[package]
name = "servidor_assincrono_tokio"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { version = "1.38", features = ["full"] }
2. Código Fonte Completo (src/main.rs)
//! Servidor Assíncrono Concorrente com Tokio Runtime e Multiplexação
use std::time::Duration;
use tokio::sync::mpsc;
use tokio::time::sleep;
#[derive(Debug)]
struct PacoteTelemetria {
origem: String,
valor_kwh: f64,
}
/// Simula uma requisição HTTP ou leitura de socket assíncrona não bloqueante
async fn buscar_metrica_sensor(id: &str, latencia_ms: u64) -> PacoteTelemetria {
// sleep do Tokio cede a thread para outras tarefas (cooperative multitasking)
sleep(Duration::from_millis(latencia_ms)).await;
PacoteTelemetria {
origem: format!("SENSOR_{}", id),
valor_kwh: 45.2 + (latencia_ms as f64 * 0.1),
}
}
/// Processo de timeout e heartbeat concorrente com tokio::select!
async fn monitorar_canal_com_timeout(mut rx: mpsc::Receiver<PacoteTelemetria>) {
loop {
tokio::select! {
// Ramo 1: Recebe dados do canal assíncrono
Some(pacote) = rx.recv() => {
println!(" [RECEBIDO VIA TOKIO] Origem: {:<12} | Leitura: {:.2} kWh", pacote.origem, pacote.valor_kwh);
}
// Ramo 2: Dispara se não houver dados por mais de 100ms
_ = sleep(Duration::from_millis(100)) => {
println!(" [TIMEOUT DE SILÊNCIO] Nenhum pacote nos últimos 100ms. Verificando saúde do runtime...");
break;
}
}
}
}
#[tokio::main]
async fn main() {
println!("=== RUNTIME ASSÍNCRONO TOKIO DE ALTA PERFORMANCE ===");
println!("Iniciando Tokio Reactor Multithread...");
// 1. Canal assíncrono Tokio com buffer de 32 mensagens
let (tx, rx) = mpsc::channel::<PacoteTelemetria>(32);
// 2. Disparando tarefas assíncronas concorrentes (Green Tasks)
// Uma thread do SO pode orquestrar centenas de milhares de tarefas Tokio!
let tx1 = tx.clone();
tokio::spawn(async move {
let p = buscar_metrica_sensor("GRID_NORTE", 30).await;
tx1.send(p).await.expect("Falha ao enviar pacote Norte");
});
let tx2 = tx.clone();
tokio::spawn(async move {
let p = buscar_metrica_sensor("GRID_SUL", 60).await;
tx2.send(p).await.expect("Falha ao enviar pacote Sul");
});
// Descartamos o transmissor original para permitir que o canal finalize
drop(tx);
// 3. Executando o consumidor assíncrono com monitoramento de timeout
monitorar_canal_com_timeout(rx).await;
println!("Runtime Tokio liberado e finalizado com sucesso!");
}
3. Saída Esperada no Terminal
=== RUNTIME ASSÍNCRONO TOKIO DE ALTA PERFORMANCE ===
Iniciando Tokio Reactor Multithread...
[RECEBIDO VIA TOKIO] Origem: SENSOR_GRID_NORTE | Leitura: 48.20 kWh
[RECEBIDO VIA TOKIO] Origem: SENSOR_GRID_SUL | Leitura: 51.20 kWh
[TIMEOUT DE SILÊNCIO] Nenhum pacote nos últimos 100ms. Verificando saúde do runtime...
Runtime Tokio liberado e finalizado com sucesso!