Colas de tareas para Go (Golang): Resumen y práctica
En las aplicaciones web modernas y los microservicios, a menudo surge la necesidad de ejecutar operaciones que consumen muchos recursos o son de larga duración de forma asíncrona: envío de correos electrónicos, generación de informes, procesamiento de imágenes, interacción con APIs externas. Para estos fines se utilizan colas de tareas (task queues). En el ecosistema de Go (Golang) existen varias bibliotecas maduras que permiten implementar dicha arquitectura. En este artículo, analizaremos tres de las herramientas más populares: machinery, gocelery y asynq, exploraremos sus características y proporcionaremos ejemplos de código.
¿Por qué se necesita una cola de tareas en Go?
Una cola de tareas resuelve varios problemas clave:
- Separación de responsabilidades: El manejador HTTP no espera a que finalice la tarea en segundo plano.
- Escalabilidad: Puedes ejecutar varios workers en diferentes servidores.
- Fiabilidad: Si un worker falla, la tarea no se pierde y puede ser reprocesada.
- Planificación: Posibilidad de retrasar la ejecución de una tarea para un momento específico.
1. Machinery — una biblioteca potente y flexible
Machinery es una cola de tareas asíncrona para Go, escrita desde cero. Soporta múltiples brokers (Redis, RabbitMQ, AWS SQS) y almacenes de resultados (Redis, MongoDB, Memcache). Machinery proporciona una API rica para crear tareas, cadenas (chains), grupos (groups) y tareas repetitivas.
Instalación y ejemplo
go get github.com/RichardKnox/machinery/v2Ejemplo de un worker y cliente simples:
package main
import ( "github.com/RichardKnox/machinery/v2" "github.com/RichardKnox/machinery/v2/config" "github.com/RichardKnox/machinery/v2/tasks")
func main() { // Configuración con broker Redis cnf := &config.Config{ Broker: "redis://localhost:6379", DefaultQueue: "machinery_tasks", ResultBackend: "redis://localhost:6379", }
server, err := machinery.NewServer(cnf) if err != nil { panic(err) }
// Registro de tarea err = server.RegisterTasks(map[string]interface{}{ "add": func(a, b int) (int, error) { return a + b, nil }, }) if err != nil { panic(err) }
// Inicio del worker worker := server.NewWorker("worker1", 2) // 2 tareas concurrentes go worker.Launch()
// Envío de tarea task := tasks.Signature{ Name: "add", Args: []tasks.Arg{ {Type: "int", Value: 5}, {Type: "int", Value: 7}, }, } result, _ := server.SendTask(&task) // Espera del resultado if res, err := result.Get(10); err == nil { println("Resultado:", res.(int)) // Salida: 12 }}Ventajas: Soporte para grafos complejos de tareas, posibilidad de reintento, monitoreo a través de interfaz web.
Desventajas: Configuración relativamente compleja, la documentación a veces va por detrás del código.
2. Asynq — cola moderna con una rica interfaz de usuario
Asynq es una biblioteca de los desarrolladores de Google, basada en Redis. Proporciona una API conveniente, planificación integrada, prioridades de tareas y una interfaz web incorporada para monitoreo. Asynq se desarrolla activamente y tiene una excelente documentación.
Instalación y ejemplo
go get github.com/hibiken/asynqEjemplo de un cliente y worker simples:
package main
import ( "context" "log" "github.com/hibiken/asynq")
// Tarea tipificadaconst TypeEmailDelivery = "email:deliver"
func main() { // Cliente para enviar tareas client := asynq.NewClient(asynq.RedisClientOpt{Addr: "localhost:6379"}) defer client.Clos También en la biblioteca
Framework CLI para C# (.NET): System.CommandLine y Spectre.Console
Tokens JWT en Swift: guía completa para trabajar con JSON Web Tokens
Quartz Scheduler Java: guía completa con ejemplos prácticos
Boost.Filesystem para C++: guía completa con ejemplos prácticos
Procesamiento de imágenes en Node.js: bibliotecas y herramientas