¡Bienvenidos de nuevo a Rustaceo.es! Hoy daremos nuestros primeros pasos en la construcción de un microservicio en Rust, aprovechando la seguridad y el alto rendimiento del lenguaje. En esta entrega, aprenderemos cómo configurar un microservicio básico usando Actix-Web, gestionar datos con SQLx y conectar nuestro servicio con una base de datos PostgreSQL.
🚀 ¿Qué necesitamos para empezar? #
Antes de comenzar, asegurémonos de contar con lo siguiente: ✔ Rust y Cargo instalados (rustup update para actualizar). ✔ PostgreSQL configurado y en ejecución. ✔ Conocimientos básicos de HTTP y APIs REST.
📌 Instalación de dependencias #
Creamos un nuevo proyecto en Rust y agregamos las dependencias necesarias:
cargo new Rust-microservice --bin
cd Rust-microservice
Editamos Cargo.toml para incluir:
[dependencies]
actix-web = "4"
sqlx = { version = "0.6", features = ["postgres", "runtime-tokio-native-tls"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
dotenv = "0.15"
Ejecutamos cargo check para verificar que todo esté correctamente configurado.
🏗 Creando un servidor http con actix-web #
Actix-Web es un framework asíncrono que nos permite manejar peticiones HTTP de manera eficiente. Creemos nuestro primer servidor básico.
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
async fn status() -> impl Responder {
HttpResponse::Ok().json({ "status": "Microservicio en ejecución" })
}
#[Actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/status", web::get().to(status))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
✔ Manejo de rutas con web::route(). ✔ Respuesta en formato JSON usando HttpResponse::Ok().json(). ✔ Ejecución de servidor en 127.0.0.1:8080.
Ejecutamos el servidor con:
cargo run
Probamos la API con curl:
curl http://127.0.0.1:8080/status
📦 Conectando con postgresql usando sqlx #
Para almacenar datos, configuramos PostgreSQL y conectamos nuestra API con SQLx.
📌 1️⃣ Configurar la base de datos #
Dentro de PostgreSQL, creamos la base de datos:
CREATE DATABASE microservicio;
CREATE USER rustaceo WITH ENCRYPTED PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE microservicio TO rustaceo;
En .env definimos la URL de conexión:
DATABASE_URL=postgres://rustaceo:password@localhost/microservicio
📌 2️⃣ Integrar sqlx en actix-web #
Modificamos main.rs para manejar la conexión a la base de datos:
use sqlx::PgPool;
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use dotenv::dotenv;
use std::env;
async fn obtener_datos(pool: web::Data<PgPool>) -> impl Responder {
let datos = sqlx::query!("SELECT * FROM datos")
.fetch_all(pool.get_ref())
.await;
match datos {
Ok(datos) => HttpResponse::Ok().json(datos),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
#[Actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL no está configurado");
let pool = PgPool::connect(&database_url).await.expect("No se pudo conectar a la BD");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.route("/datos", web::get().to(obtener_datos))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
✔ Carga de variables de entorno con dotenv(). ✔ Conexión con PostgreSQL usando PgPool::connect(). ✔ Consulta segura de datos con sqlx::query!().
📡 Comunicación entre microservicios #
Para que nuestros microservicios interactúen entre sí, usamos reqwest para realizar peticiones HTTP a otros servicios.
📌 Ejemplo de Consumo de API desde otro Microservicio:
use reqwest;
#[Tokio::main]
async fn main() {
let respuesta = reqwest::get("http://127.0.0.1:8080/status")
.await.unwrap()
.text()
.await.unwrap();
println!("Respuesta del servicio: {}", respuesta);
}
✔ Consumo de APIs con reqwest::get(). ✔ Manejo de respuestas asíncronas con await.
🔐 Implementando seguridad con jwt #
Para proteger nuestras APIs, utilizamos autenticación con JSON Web Tokens (JWT):
📌 Ejemplo de Validación de JWT:
use jsonwebtoken::{decode, encode, Header, Validation, EncodingKey, DecodingKey};
#[Derive(serde::serialize, serde::deserialize)]
struct Claims {
sub: String,
exp: usize,
}
✔ Protección contra accesos no autorizados. ✔ Generación y validación de tokens JWT.
🏆 Conclusión #
Hemos creado un microservicio en Rust desde cero con Actix-Web y SQLx.
🎯 Resumen de lo aprendido: ✔ Configuración de un servidor HTTP con Actix-Web. ✔ Conexión con PostgreSQL usando SQLx. ✔ Comunicación entre microservicios con reqwest. ✔ Implementación de autenticación con JWT.
🔮 Próximo paso: Desplegar el microservicio en Docker y Kubernetes.
¡Nos vemos en la siguiente entrega, Rustaceos!