Spring Boot y Virtual Threads

¿Una alternativa real a los servicios de mensajería en arquitecturas monolíticas?

La llegada de Java 21 y la oficialización de Project Loom marcaron un antes y un después en cómo la JVM maneja la concurrencia. Durante años, escalar aplicaciones con operaciones bloqueantes de entrada/salida (I/O) implicaba un compromiso costoso: o aumentabas drásticamente los recursos de hardware para soportar miles de Platform Threads, o adoptabas modelos de programación reactiva que añadían complejidad cognitiva al código.

Con la introducción de los Virtual Threads (hilos virtuales), Spring Boot ofrece ahora una herramienta poderosa que promete el rendimiento de lo asíncrono con la simplicidad de lo secuencial. Pero, ¿hasta dónde llega su potencia? ¿Es posible que esta tecnología haga innecesarios los servicios de mensajería tradicionales (como RabbitMQ o Kafka) en ciertos contextos?
En este artículo analizamos técnicamente cómo funcionan, cómo implementarlos en Spring Boot y el análisis costo-beneficio de utilizarlos como reemplazo de colas de mensajes en arquitecturas monolíticas.

¿Qué son realmente los Virtual Threads?

A diferencia de los hilos de plataforma tradicionales, que son costosos y tienen una relación 1:1 con los hilos del sistema operativo, los Virtual Threads son entidades ligeras gestionadas directamente por la JVM.

 

La diferencia en consumo de recursos es abismal: mientras un hilo de plataforma puede consumir megabytes de memoria para su pila, un hilo virtual consume apenas cientos de bytes. Esto permite un cambio de paradigma fundamental:

  • ANTES: Tenías que administrar pools de hilos limitados.
  • AHORA: Podés crear millones de hilos virtuales sin saturar el sistema operativo.

El modelo «Under the Hood»

La magia reside en cómo la JVM maneja las operaciones bloqueantes. Cuando un hilo virtual realiza una llamada a una base de datos o una API externa (I/O), la JVM lo «desmonta» de su hilo portador (carrier thread), liberando ese recurso del sistema operativo para que procese otras tareas. Cuando la operación de I/O termina, el hilo virtual se «remonta» y continúa su ejecución.

Esto revive el estilo de programación «thread-per-request». Podés escribir código secuencial, fácil de leer y depurar, obteniendo la escalabilidad que antes solo ofrecía la programación reactiva.

Nota importante: Los Virtual Threads no hacen que el código sea más rápido en tareas intensivas de CPU. Su valor está en la escalabilidad (throughput) para tareas que pasan mucho tiempo esperando (I/O bound).

Virtual Threads vs. Servicios de Mensajería

En arquitecturas de microservicios distribuidos, los servicios de mensajería (RabbitMQ, Kafka, SQS) son innegociables para garantizar el desacoplamiento. Sin embargo, en aplicaciones monolíticas o servicios autocontenidos con procesos por etapas, solemos usar colas internas simplemente para paralelizar tareas.

Aquí es donde los Virtual Threads plantean una alternativa interesante: Reemplazar la complejidad de un broker de mensajería con un patrón de Pipeline interno en memoria.

Otros temas

Implementación del Patrón Pipeline en Spring Boot

Si tenés un proceso secuencial (por ejemplo, Gestión de Pedidos o Procesamiento de Leads), podés orquestar las etapas utilizando CompletableFuture combinados con Virtual Threads.

Primero, habilitás la funcionalidad en tu application.properties:

Copy to Clipboard

Luego, para que el pipeline funcione, el servicio que realiza el trabajo debe estar marcado con @Async. Es aquí donde ocurre la «magia»: al estar habilitada la propiedad anterior, cada uno de estos métodos se ejecutará en su propio Virtual Thread.
Nota: No olvides incluir @EnableAsync en tu clase de configuración principal para activar esta funcionalidad.

Copy to Clipboard

Con los servicios preparados, el orquestador puede encadenar las etapas de forma no bloqueante. El hilo principal que recibe la solicitud queda libre de inmediato, mientras los Virtual Threads se encargan del flujo.

Copy to Clipboard

Si preferís no depender de las anotaciones de Spring y necesitás un control total sobre el ejecutor, podés definir e inyectar tu propio ExecutorService basado en Virtual Threads:

Copy to Clipboard

Este enfoque reduce la latencia al evitar saltos de red hacia un broker (como RabbitMQ o Kafka) cuando la persistencia del mensaje en una cola externa no es estrictamente necesaria, simplificando tu arquitectura sin sacrificar escalabilidad.

Análisis crítico: ¿Cuándo conviene hacer el cambio?

Reemplazar un sistema de mensajería robusto por hilos en memoria conlleva riesgos que debés evaluar. A continuación, comparamos ambas aproximaciones para que tomes una decisión informada.

Spring Boot y Virtual Threads

El veredicto técnico

Si optás por Virtual Threads para reemplazar colas, perdés la persistencia automática y los reintentos nativos. Esto significa que, si el sistema se cae a mitad de un proceso crítico, perdés el estado de esa tarea a menos que implementes tu propio mecanismo de persistencia en base de datos.

Recomendamos usar Virtual Threads como reemplazo de colas solo si:

  1. El proceso es simple, secuencial y está bien definido.
  2. La pérdida de un mensaje ocasional no es crítica para el negocio.
  3. Buscás reducir latencia eliminando intermediarios.
  4. Tenés implementado un mecanismo de recuperación (Scheduler) que escanee la base de datos buscando procesos «atascados» para reintentarlos, como en el caso de uso de reprocesamiento de Leads.

La solución híbrida: Lo mejor de los dos mundos

Para sistemas de misión crítica, la respuesta no suele ser «uno u otro», sino ambos.

Podés mantener RabbitMQ como columna vertebral para la comunicación entre servicios (garantizando durabilidad y desacoplamiento) y utilizar Virtual Threads dentro de los consumidores.

Por ejemplo, en un servicio de procesamiento de Leads, el consumidor de RabbitMQ recibe el mensaje y delega el trabajo pesado (transcripción, detección, validación) a un VirtualThreadExecutor. Esto maximiza la concurrencia del consumidor, permitiéndole procesar miles de mensajes en paralelo sin bloquear hilos del sistema operativo esperando respuestas de APIs externas, mientras mantienes la seguridad de la cola.

Conclusión

Los Virtual Threads en Spring Boot 3.2+ son una herramienta formidable para optimizar recursos y simplificar el código concurrente. Si bien pueden reemplazar colas internas en monolitos si se gestionan con cuidado los riesgos de persistencia, su mayor potencial en arquitecturas empresariales radica en potenciar los consumidores de mensajería existentes, no necesariamente en eliminarlos.

La escalabilidad de tu software no debería ser un pozo sin fondo de costes en infraestructura.

Si quieres saber cómo los Virtual Threads pueden optimizar tus sistemas actuales sin rediseñar toda tu arquitectura, hablemos.

También te puede interesar

  • 24 enero, 2024

    Automatización de procesos

  • 30 mayo, 2024

    Beneficios de la integración y despliegue continuo

    Tags: ,
  • 19 julio, 2024

    La Nube: revolucionando el mundo de los negocios