Очереди задач для Go (Golang): полное руководство по библиотекам и инструментам
В мире современной разработки на Go (Golang) обработка фоновых задач и асинхронных операций — критически важная задача. Будь то отправка email, генерация отчетов, обработка изображений или взаимодействие с внешними API, очереди задач (task queues) позволяют разгрузить основной поток приложения и повысить его отказоустойчивость. В этой статье мы рассмотрим лучшие библиотеки для работы с очередями в Go, их особенности и примеры использования.
Что такое очередь задач и зачем она нужна?
Очередь задач — это механизм, который позволяет откладывать выполнение ресурсоемких или длительных операций на фоне. Основные преимущества:
- Асинхронность: пользователь не ждет завершения тяжелой операции.
- Масштабирование: вы можете запускать множество воркеров для параллельной обработки.
- Отказоустойчивость: если воркер упал, задача остается в очереди и будет выполнена другим.
- Планирование: отложенный запуск задач (например, через 1 час).
Топ-3 библиотеки для очередей задач в Go
1. Asynq
Asynq — современная, производительная и простая в использовании библиотека для распределенных очередей задач, построенная на Redis. Разработана командой Google и активно поддерживается сообществом.
Ключевые особенности:
- Работает поверх Redis (рекомендуется версия 6.0+).
- Поддержка отложенных задач (scheduled tasks).
- Встроенный веб-интерфейс для мониторинга (Asynqmon).
- Dead-letter очередь для упавших задач.
- Группы задач (task groups) для логической группировки.
- Retry с настраиваемой политикой повторных попыток.
Пример использования:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/hibiken/asynq"
)
// Определяем тип задачи
const TypeEmailDelivery = "email:deliver"
// Структура данных для задачи
type EmailTaskPayload struct {
UserID int
TemplateID string
}
// Обработчик задачи
func HandleEmailTask(ctx context.Context, t *asynq.Task) error {
var payload EmailTaskPayload
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
}
log.Printf("Sending email to user %d with template %s", payload.UserID, payload.TemplateID)
// Здесь логика отправки email
return nil
}
func main() {
// Клиент для постановки задач
client := asynq.NewClient(asynq.RedisClientOpt{Addr: "localhost:6379"})
defer client.Close()
// Создаем задачу
payload, _ := json.Marshal(EmailTaskPayload{UserID: 42, TemplateID: "welcome"})
task := asynq.NewTask(TypeEmailDelivery, payload, asynq.MaxRetry(5))
// Ставим задачу в очередь
info, err := client.Enqueue(task, asynq.ProcessIn(10*time.Second)) // отложить на 10 сек
if err != nil {
log.Fatal(err)
}
log.Printf("Task enqueued: ID=%s, Queue=%s", info.ID, info.Queue)
// Сервер-воркер
srv := asynq.NewServer(
asynq.RedisClientOpt{Addr: "localhost:6379"},
asynq.Config{Concurrency: 10},
)
// Регистрируем обработчик
mux := asynq.NewServeMux()
mux.HandleFunc(TypeEmailDelivery, HandleEmailTask)
// Запускаем воркер
if err := srv.Run(mux); err != nil {
log.Fatal(err)
}
}
2. Machinery
Machinery — одна из самых популярных и зрелых библиотек для Go. Поддерживает несколько брокеров: Redis, AMQP (RabbitMQ), AWS SQS, MongoDB и другие. Отличается богатой функциональностью и гибкостью.
Ключевые особенности:
- Поддержка множества брокеров и хранилищ результатов.
- Цепочки задач (chains) — выполнение задач последовательно.
- Группы задач (groups) — параллельное выполнение.
- Планирование (cron) — периодические задачи.
- Мониторинг через веб-интерфейс Flower.
- Поддержка отложенных задач (ETA).
Пример использования:
package main
import (
"context"
"fmt"
"log"
"github.com/RichardKnox/machinery/v1"