Filas de Tarefas para Go (Golang): Visão Geral e Prática
Em aplicações web modernas e microsserviços, surge frequentemente a necessidade de executar operações que consomem muitos recursos ou são demoradas de forma assíncrona: envio de e-mail, geração de relatórios, processamento de imagens, interação com APIs externas. Para esses fins, são utilizadas filas de tarefas (task queues). No ecossistema Go (Golang), existem várias bibliotecas maduras que permitem implementar essa arquitetura. Neste artigo, veremos três das ferramentas mais populares: machinery, gocelery e asynq, analisaremos suas características e forneceremos exemplos de código.
Por que preciso de uma fila de tarefas em Go?
Uma fila de tarefas resolve vários problemas-chave:
- Separação de responsabilidades: O manipulador HTTP não espera a conclusão da tarefa em segundo plano.
- Escalabilidade: Você pode executar vários workers em servidores diferentes.
- Confiabilidade: Em caso de falha do worker, a tarefa não é perdida e pode ser reprocessada.
- Agendamento: Possibilidade de adiar a execução de uma tarefa para um horário específico.
1. Machinery — Biblioteca Poderosa e Flexível
Machinery é uma fila de tarefas assíncrona para Go, escrita do zero. Ela suporta vários brokers (Redis, RabbitMQ, AWS SQS) e backends de resultados (Redis, MongoDB, Memcache). O Machinery fornece uma API rica para criar tarefas, cadeias (chains), grupos (groups) e tarefas recorrentes.
Instalação e Exemplo
go get github.com/RichardKnox/machinery/v2Exemplo de um worker e cliente simples:
package main
import ( "github.com/RichardKnox/machinery/v2" "github.com/RichardKnox/machinery/v2/config" "github.com/RichardKnox/machinery/v2/tasks")
func main() { // Configuração com 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 da tarefa err = server.RegisterTasks(map[string]interface{}{ "add": func(a, b int) (int, error) { return a + b, nil }, }) if err != nil { panic(err) }
// Iniciar worker worker := server.NewWorker("worker1", 2) // 2 tarefas concorrentes go worker.Launch()
// Envio da tarefa task := tasks.Signature{ Name: "add", Args: []tasks.Arg{ {Type: "int", Value: 5}, {Type: "int", Value: 7}, }, } result, _ := server.SendTask(&task) // Aguardando resultado if res, err := result.Get(10); err == nil { println("Result:", res.(int)) // Saída: 12 }}Prós: Suporte a grafos de tarefas complexos, possibilidade de nova tentativa, monitoramento via interface web.
Contras: Configuração relativamente complexa, documentação às vezes fica atrás do código.
2. Asynq — Fila Moderna com UI Rico
Asynq é uma biblioteca dos desenvolvedores do Google, baseada em Redis. Ela fornece uma API conveniente, agendamento integrado, prioridades de tarefas e uma interface web integrada para monitoramento. O Asynq está em desenvolvimento ativo e possui excelente documentação.
Instalação e Exemplo
go get github.com/hibiken/asynqExemplo de um cliente e worker simples:
package main
import ( "context" "log" "github.com/hibiken/asynq")
// Tarefa tipadaconst TypeEmailDelivery = "email:deliver"
func main() { // Cliente para enviar tarefas client := asynq.NewClient(asynq.RedisClientOpt{Addr: "localhost:6379"}) defer client.Clos Também na biblioteca
Geração de PDF em JavaScript: biblioteca pdf-lib
Registro em Kotlin: visão geral das melhores bibliotecas e soluções
Geolocalização e Mapas em Swift: CoreLocation e MapKit para iOS/macOS
Event Bus e padrão Observer em Go (Golang): implementação e exemplos