# Procesamiento en Streaming: Arquitectura como Bloques de LEGO
Los sistemas modernos de procesamiento de datos exigen flexibilidad y escalabilidad. En este artículo, desglosaremos cómo combinar Kafka, Flink, S3 y otros componentes en una plataforma unificada de streaming utilizando principios de arquitectura modular. Profundizaremos en las etapas de integración en detalle, desde la generación de datos hasta el análisis en tiempo real.
Fundamento del Sistema: Plataforma de Streaming
Para construir el procesamiento en streaming, utilizamos una pila de tecnologías probadas y robustas. El componente central es Apache Kafka, una plataforma de streaming distribuida que garantiza la entrega confiable de mensajes. Junto a él, empleamos:
- Kafka Connect para la integración con sistemas externos
- Schema Registry para la gestión de esquemas de datos
- Kafka UI como interfaz de gestión visual
La idea clave es tratar los componentes como bloques de LEGO. Cada uno maneja una función específica y se conecta a los demás mediante interfaces bien definidas. Para lanzar una configuración mínima, Docker Compose y Git LFS son todo lo que necesitas. El sistema se ensambla mediante builds multi-etapa, asegurando entornos reproducibles.
Ejemplo de configuración básica en docker-compose.yml:
services:
kafka:
image: confluentinc/cp-kafka:8.1.0
environment:
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
schema-registry:
image: confluentinc/cp-schema-registry:8.1.0
environment:
SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
Es importante entender la diferencia entre bases de datos tradicionales y sistemas de streaming. En los SGBD relacionales, el enfoque está en el estado (tablas, registros), mientras que en el procesamiento en streaming, se centra en eventos. Cada mensaje en Kafka representa un evento inmutable que se añade al final del log. Este enfoque permite sistemas con entrega garantizada y recuperación de estado.
Etapas de Integración de Datos
Dividiremos el proceso de construcción del sistema en cuatro etapas lógicas:
- Ingest — recepción de datos de fuentes externas
- Storage — almacenamiento persistente
- Transform — transformación y enriquecimiento
- Serve — entrega de resultados
Ingest: Generación e Ingestión de Datos
En la etapa Ingest, configuramos la fuente de datos mediante Kafka Connect. Para la demostración, implementaremos un generador de lecturas de sensores de temperatura. El conector Java genera datos sintéticos con coordenadas geográficas y temperatura, teniendo en cuenta la hora del día y la posición relativa al ecuador.
Configuración del conector:
{
"connector.class": "dev.miron.connect.temp.TempSourceConnector",
"tasks.max": "1",
"topic": "earth-temp",
"sensors": "5",
"messages.per.sensor.per.second": "1"
}
Nota el uso de Avro para serialización. Los mensajes se almacenan en formato binario, reduciendo el volumen de tráfico y acelerando el procesamiento. Schema Registry maneja el versionado de esquemas y las verificaciones de compatibilidad (modo BACKWARD). Cuando cambia la estructura de datos, el sistema rechaza automáticamente las actualizaciones inválidas.
Storage: Almacenamiento a Largo Plazo
Para el almacenamiento persistente, usamos una combinación de S3 y Apache Iceberg. S3 actúa como almacenamiento de objetos, mientras que Iceberg añade una capa de metadatos que permite transacciones ACID y viaje en el tiempo. Este enfoque maneja eficientemente grandes conjuntos de datos, evitando problemas con sistemas de archivos tradicionales.
Configuración del conector sink:
{
"connector.class": "io.confluent.connect.s3.S3SinkConnector",
"topics": "earth-temp",
"s3.bucket.name": "data-lake",
"storage.class": "io.confluent.connect.s3.storage.S3Storage",
"format.class": "io.confluent.connect.s3.format.avro.AvroFormat"
}
Para consultas de datos, usamos Trino, un motor SQL distribuido capaz de federar datos de múltiples fuentes. Esto permite consultas analíticas complejas sin mover datos.
Transformación de Datos
Implementamos la etapa Transform con Apache Flink, un motor de procesamiento en streaming que soporta ventanas y operaciones con estado. Tarea de ejemplo: convertir temperatura de Fahrenheit a Celsius y filtrar valores anómalos.
DataStream<TempEvent> processed = source
.map(event -> {
event.setCelsius((event.getFahrenheit() - 32) * 5/9);
return event;
})
.filter(event -> event.getCelsius() > -50 && event.getCelsius() < 60);
Flink se integra con Kafka mediante conectores nativos. Es crucial configurar correctamente el checkpointing para garantías de procesamiento exactly-once. Parámetros clave:
execution.checkpointing.interval: 60000state.backend: rocksdbstate.checkpoints.dir: file:///checkpoints
Para monitoreo, usamos la interfaz web integrada de Flink para rastrear retrasos de procesamiento (lag) y estados de operadores.
Capa de Servicio
En la etapa final, los datos están disponibles para los consumidores. Implementamos dos opciones:
- PostgreSQL mediante conector JDBC para consultas operacionales
- Redis para caché de datos calientes
Configuración sink de PostgreSQL:
{
"connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector",
"connection.url": "jdbc:postgresql://postgres:5432/analytics",
"topics": "processed-temp",
"auto.create": "true",
"insert.mode": "upsert",
"pk.fields": "sensorId,timestamp"
}
Para Redis, usamos un conector personalizado que almacena las últimas lecturas de cada sensor en tablas hash. Esto proporciona latencia de milisegundos para consultas a datos actuales.
Puntos Clave
- Los esquemas de datos deben gestionarse mediante Schema Registry con compatibilidad BACKWARD
- El procesamiento con estado en Flink requiere configuración de checkpointing y selección de backend de estado
- La descomposición del sistema en etapas Ingest/Storage/Transform/Serve simplifica la depuración
- La serialización binaria (Avro/Protobuf) es crítica para el rendimiento de sistemas de streaming
- Probar configuraciones mediante Docker Compose permite iteraciones rápidas
— Editorial Team
Aún no hay comentarios.