Files d'attente de tâches pour Go (Golang) : Aperçu et pratique
Dans les applications web modernes et les microservices, il est souvent nécessaire d'exécuter des opérations gourmandes en ressources ou longues de manière asynchrone : envoi d'emails, génération de rapports, traitement d'images, interaction avec des API externes. Pour cela, on utilise des files d'attente de tâches (task queues). Dans l'écosystème Go (Golang), il existe plusieurs bibliothèques matures qui permettent de mettre en œuvre une telle architecture. Dans cet article, nous examinerons trois outils les plus populaires : machinery, gocelery et asynq, nous analyserons leurs caractéristiques et fournirons des exemples de code.
Pourquoi une file d'attente de tâches en Go ?
Une file d'attente de tâches résout plusieurs problèmes clés :
- Séparation des responsabilités : Le gestionnaire HTTP n'attend pas la fin de la tâche d'arrière-plan.
- Mise à l'échelle : Vous pouvez lancer plusieurs workers sur différents serveurs.
- Fiabilité : En cas de panne d'un worker, la tâche n'est pas perdue et peut être retraitée.
- Planification : Possibilité de reporter l'exécution d'une tâche à un moment précis.
1. Machinery — une bibliothèque puissante et flexible
Machinery est une file d'attente de tâches asynchrone pour Go, écrite de zéro. Elle prend en charge plusieurs courtiers (Redis, RabbitMQ, AWS SQS) et stockages de résultats (Redis, MongoDB, Memcache). Machinery fournit une API riche pour créer des tâches, des chaînes (chains), des groupes (groups) et des tâches récurrentes.
Installation et exemple
go get github.com/RichardKnox/machinery/v2Exemple d'un worker et d'un client simples :
package main
import ( "github.com/RichardKnox/machinery/v2" "github.com/RichardKnox/machinery/v2/config" "github.com/RichardKnox/machinery/v2/tasks")
func main() { // Configuration avec un courtier 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) }
// Enregistrement de la tâche err = server.RegisterTasks(map[string]interface{}{ "add": func(a, b int) (int, error) { return a + b, nil }, }) if err != nil { panic(err) }
// Lancement du worker worker := server.NewWorker("worker1", 2) // 2 tâches concurrentes go worker.Launch()
// Envoi de la tâche task := tasks.Signature{ Name: "add", Args: []tasks.Arg{ {Type: "int", Value: 5}, {Type: "int", Value: 7}, }, } result, _ := server.SendTask(&task) // Attente du résultat if res, err := result.Get(10); err == nil { println("Résultat :", res.(int)) // Sortie : 12 }}Avantages : Prise en charge de graphes de tâches complexes, possibilité de nouvelle tentative, surveillance via une interface web.
Inconvénients : Configuration relativement complexe, documentation parfois en retard par rapport au code.
2. Asynq — une file d'attente moderne avec une interface utilisateur riche
Asynq est une bibliothèque des développeurs de Google, basée sur Redis. Elle fournit une API pratique, une planification intégrée, des priorités de tâches et une interface web intégrée pour la surveillance. Asynq est activement développé et possède une excellente documentation.
Installation et exemple
go get github.com/hibiken/asynqExemple d'un client et d'un worker simples :
package main
import ( "context" "log" "github.com/hibiken/asynq")
// Tâche typéeconst TypeEmailDelivery = "email:deliver"
func main() { // Client pour envoyer des tâches client := asynq.NewClient(asynq.RedisClientOpt{Addr: "localhost:6379"}) defer client.Clos Aussi dans la bibliothèque
Travail avec les images en Rust : aperçu des bibliothèques image, fast_image_resize et autres
Journalisation pour Swift (iOS/macOS) : meilleures solutions
node-cache : Mise en cache simple et efficace dans Node.js
Validation des données en Rust : aperçu des bibliothèques et frameworks